Compare commits
1775 Commits
release/24
...
work/ngrah
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c8ca778b2 | ||
|
|
ab8e2f7573 | ||
|
|
7991429ef4 | ||
|
|
e3b70a14be | ||
|
|
39abf6b5f3 | ||
|
|
096842bd3a | ||
|
|
c69db9d375 | ||
|
|
ec36d519b1 | ||
|
|
45b02ae34e | ||
|
|
9b763daf52 | ||
|
|
6e8ed5b341 | ||
|
|
63a3c3e58a | ||
|
|
aadd9b0189 | ||
|
|
39f595e45d | ||
|
|
823b2d3747 | ||
|
|
eb268576da | ||
|
|
8e51f3ec8e | ||
|
|
de03e1ce2b | ||
|
|
21b1258b8d | ||
|
|
becad8c127 | ||
|
|
4044048352 | ||
|
|
7d6bd7ab4c | ||
|
|
209ae00f8f | ||
|
|
f64c860453 | ||
|
|
36fccaffe6 | ||
|
|
13deb2d928 | ||
|
|
14fe71b556 | ||
|
|
ecb900994b | ||
|
|
55b97b469e | ||
|
|
1d594b492d | ||
|
|
3902293de7 | ||
|
|
a8bc51667c | ||
|
|
0bcf6e74c0 | ||
|
|
78b218fef3 | ||
|
|
964bcfd5f5 | ||
|
|
fc733f9ba1 | ||
|
|
e7e83fa789 | ||
|
|
ef4f11546f | ||
|
|
648796b9e0 | ||
|
|
3b5da2473d | ||
|
|
9a04ae3e02 | ||
|
|
9ed5224470 | ||
|
|
bc82ceeb5f | ||
|
|
5f7ff209d3 | ||
|
|
35b363fdce | ||
|
|
a74931e794 | ||
|
|
6698bbcf79 | ||
|
|
8c78992b1a | ||
|
|
04e3b88e8c | ||
|
|
9b8b13e98e | ||
|
|
e6dd6aec7f | ||
|
|
c6f0879c9c | ||
|
|
9e7ae37add | ||
|
|
0c727237ee | ||
|
|
bf66118355 | ||
|
|
aacb097650 | ||
|
|
ce5d60fc5d | ||
|
|
96a0b86c33 | ||
|
|
279b611754 | ||
|
|
f7c74a60cd | ||
|
|
3465fc7d39 | ||
|
|
6381f06acb | ||
|
|
a7c7a5c72d | ||
|
|
c8ded65e46 | ||
|
|
729b46fc71 | ||
|
|
e63e04aa57 | ||
|
|
ae88879651 | ||
|
|
dfd106258b | ||
|
|
4d29b9fd57 | ||
|
|
3de7ad237a | ||
|
|
7d4e589894 | ||
|
|
4bbd127fe8 | ||
|
|
f2a0a66b01 | ||
|
|
143c685045 | ||
|
|
b8fa6f0690 | ||
|
|
93b6c53c82 | ||
|
|
6822a1ef08 | ||
|
|
12b7c25395 | ||
|
|
42c0060122 | ||
|
|
b30ee55a81 | ||
|
|
9d2ef838bb | ||
|
|
b5351e48dd | ||
|
|
7b437d91e1 | ||
|
|
a9d39353ab | ||
|
|
5f778dbd81 | ||
|
|
b01286eae3 | ||
|
|
4688802628 | ||
|
|
0282f2c7aa | ||
|
|
53d0fd1663 | ||
|
|
24bdb7d651 | ||
|
|
dc32f2f947 | ||
|
|
401cf29ca8 | ||
|
|
f16dea85ed | ||
|
|
b4e1740cad | ||
|
|
501f14fead | ||
|
|
d14466451d | ||
|
|
f7cd4bd2fb | ||
|
|
7742c6d4b0 | ||
|
|
4f6dd50320 | ||
|
|
92f77860dd | ||
|
|
03035b735d | ||
|
|
4e0b295f66 | ||
|
|
8cbd3f5e0f | ||
|
|
a0b3e484f5 | ||
|
|
8ff83ca6df | ||
|
|
5fe28cb183 | ||
|
|
17af4dfddb | ||
|
|
43c6349359 | ||
|
|
265494ee44 | ||
|
|
a9e4996191 | ||
|
|
6e3276826d | ||
|
|
bfe976c438 | ||
|
|
f288367653 | ||
|
|
6082bc89b0 | ||
|
|
4d3791250b | ||
|
|
04472dae4f | ||
|
|
aa40fc84ea | ||
|
|
24e43d063a | ||
|
|
c5caffcdf9 | ||
|
|
95d334ad86 | ||
|
|
602ac5c55f | ||
|
|
247423bf83 | ||
|
|
24d35b3eae | ||
|
|
8bcd9f7469 | ||
|
|
edf5d55da4 | ||
|
|
976af783e2 | ||
|
|
d87954838e | ||
|
|
e757331dce | ||
|
|
bf4f6f5728 | ||
|
|
c73bc8fc29 | ||
|
|
211a08db68 | ||
|
|
38987e6d4c | ||
|
|
9d76e7e30b | ||
|
|
4c1a8d3657 | ||
|
|
7a5de25885 | ||
|
|
a17aa2c6fa | ||
|
|
207a7876b6 | ||
|
|
4c638a740e | ||
|
|
0ee89e1b2b | ||
|
|
4af42a57f4 | ||
|
|
34f2c2dabc | ||
|
|
9ff942915a | ||
|
|
10123abc5b | ||
|
|
ad993d4340 | ||
|
|
ddc0a66d5b | ||
|
|
e8981bdc0f | ||
|
|
c42486a061 | ||
|
|
64d82b8d2a | ||
|
|
677abee890 | ||
|
|
3a25a62350 | ||
|
|
bc7b480c41 | ||
|
|
d9b495356d | ||
|
|
ce82606e6e | ||
|
|
07837c2e64 | ||
|
|
1738253e6f | ||
|
|
17fa2246da | ||
|
|
4f5e096e7e | ||
|
|
b125c284bd | ||
|
|
87213903b1 | ||
|
|
3d9d211d25 | ||
|
|
d5d291396d | ||
|
|
d7cd38b5e5 | ||
|
|
1a25cfc0e3 | ||
|
|
8d9669e033 | ||
|
|
690d2e2b12 | ||
|
|
2208b1b2b3 | ||
|
|
67da272ccd | ||
|
|
171930fb1d | ||
|
|
2bd59fa16f | ||
|
|
d0d0384bdb | ||
|
|
680573de61 | ||
|
|
ba7f866cf5 | ||
|
|
57a95ae972 | ||
|
|
de97275a38 | ||
|
|
d08181f56d | ||
|
|
f6e8491bf1 | ||
|
|
a1447ebd6f | ||
|
|
3b67e4deaf | ||
|
|
e55afd0402 | ||
|
|
7c0710d445 | ||
|
|
61f9cd41f7 | ||
|
|
6c7a7a7be5 | ||
|
|
63125d97c3 | ||
|
|
cb4e7d4943 | ||
|
|
b9d5ed699e | ||
|
|
75fe5c8970 | ||
|
|
91da2d01b7 | ||
|
|
4bade72ce4 | ||
|
|
9c05e2feed | ||
|
|
ba94098411 | ||
|
|
43c691160e | ||
|
|
e2daa091e8 | ||
|
|
f026414b1a | ||
|
|
fd640a4bd0 | ||
|
|
dd433d7f99 | ||
|
|
3183e00acc | ||
|
|
1860de12ea | ||
|
|
277f1ab252 | ||
|
|
324b332fa6 | ||
|
|
33d29f6b02 | ||
|
|
419aed6375 | ||
|
|
7bb26ac3be | ||
|
|
7654333ec1 | ||
|
|
d3a2da391d | ||
|
|
f19f59c37f | ||
|
|
94e53e14a3 | ||
|
|
d2b3788872 | ||
|
|
8095062db2 | ||
|
|
89beaa9316 | ||
|
|
dfaffd043e | ||
|
|
a8c200222f | ||
|
|
598a1c28ac | ||
|
|
b972703f34 | ||
|
|
d30fdc67c6 | ||
|
|
6a5a2e6144 | ||
|
|
235143528c | ||
|
|
33ca2b8d09 | ||
|
|
50176cfafb | ||
|
|
a67fb36a84 | ||
|
|
aea9984187 | ||
|
|
7a6c234b40 | ||
|
|
4cdaa513d3 | ||
|
|
aaf655ea5b | ||
|
|
207c824ec7 | ||
|
|
29abe0bacb | ||
|
|
d14eda2ca0 | ||
|
|
0425cf41d0 | ||
|
|
4ff014f288 | ||
|
|
2e24500866 | ||
|
|
f13a256150 | ||
|
|
c958e8cba9 | ||
|
|
7668da68d3 | ||
|
|
c478a0c0fc | ||
|
|
fe60a08817 | ||
|
|
dec5369a8f | ||
|
|
5ec0b9393e | ||
|
|
3d8f724bb1 | ||
|
|
bc7a663f92 | ||
|
|
90369e927f | ||
|
|
034cad79c7 | ||
|
|
5c8ba7e29e | ||
|
|
bf1dc00338 | ||
|
|
54f7fd08cb | ||
|
|
e7afa07c84 | ||
|
|
e196ef03d6 | ||
|
|
0fa452ca04 | ||
|
|
15b625a3f8 | ||
|
|
e2427c0683 | ||
|
|
a0e8039d92 | ||
|
|
2f87b1f398 | ||
|
|
86fd2e8e1e | ||
|
|
4167f55ad8 | ||
|
|
76919a13b8 | ||
|
|
fe0f159490 | ||
|
|
4527a6399e | ||
|
|
b8ff75c5ce | ||
|
|
049e8af8b2 | ||
|
|
8ce2386cc9 | ||
|
|
5239040d9c | ||
|
|
c5eb7578b7 | ||
|
|
76ce44230d | ||
|
|
4a20371b87 | ||
|
|
9a76c30aaf | ||
|
|
9cba57368e | ||
|
|
d895f8d771 | ||
|
|
de8c9f4878 | ||
|
|
f029cf842a | ||
|
|
6ce9b77b3c | ||
|
|
5a60c6ec67 | ||
|
|
a1ca768711 | ||
|
|
f0d2c19393 | ||
|
|
67db05a0c3 | ||
|
|
05e932b884 | ||
|
|
763713cd32 | ||
|
|
2687448212 | ||
|
|
d059195e92 | ||
|
|
6ef7acc8e5 | ||
|
|
2cb89807ef | ||
|
|
b5fcad3db0 | ||
|
|
d3fd441c88 | ||
|
|
e9568b50fc | ||
|
|
e7040a518a | ||
|
|
495f7194ac | ||
|
|
d31cc486bb | ||
|
|
3ea844496a | ||
|
|
7b953d0cc0 | ||
|
|
becc127dc4 | ||
|
|
e2742cbf8b | ||
|
|
a1513b30cd | ||
|
|
e2c0316e7d | ||
|
|
fda84a6aac | ||
|
|
142312d87d | ||
|
|
906fb97259 | ||
|
|
80923a2025 | ||
|
|
12882586d3 | ||
|
|
d51e68e9e2 | ||
|
|
7f6e489f20 | ||
|
|
161111bf5c | ||
|
|
5452c51c6a | ||
|
|
09917d45e3 | ||
|
|
101a8b9ec3 | ||
|
|
a04769baad | ||
|
|
07441df3f6 | ||
|
|
b5465cd8d0 | ||
|
|
0a2af02c5f | ||
|
|
3183be460e | ||
|
|
beb72dfa48 | ||
|
|
60d493e34b | ||
|
|
36a5e8bdb5 | ||
|
|
489e60996a | ||
|
|
3d15e4f061 | ||
|
|
28c39292f7 | ||
|
|
d7c9bea783 | ||
|
|
e232501715 | ||
|
|
4757ac11dc | ||
|
|
14cbbd394f | ||
|
|
5d4529ccf9 | ||
|
|
baa214df0e | ||
|
|
6b5996a1bd | ||
|
|
86a43c4f7e | ||
|
|
107f3b6616 | ||
|
|
bcab617b9d | ||
|
|
f6c12dc27a | ||
|
|
3e954a24a1 | ||
|
|
08dc05c707 | ||
|
|
8817ca7f2b | ||
|
|
5262ec4b56 | ||
|
|
f4799a4287 | ||
|
|
97d5be9d81 | ||
|
|
6913a4b447 | ||
|
|
41e96fca70 | ||
|
|
f6b3f3ac80 | ||
|
|
db0c423763 | ||
|
|
df9a7292b9 | ||
|
|
7abca73339 | ||
|
|
30ee914baf | ||
|
|
5b835933e6 | ||
|
|
85f3d3b633 | ||
|
|
41d6233f78 | ||
|
|
ccb162cfed | ||
|
|
56472f6cfd | ||
|
|
14c26b1663 | ||
|
|
14043f861f | ||
|
|
7761e4e0f7 | ||
|
|
4214b7691f | ||
|
|
62da98af94 | ||
|
|
0cc14f710d | ||
|
|
a148c6e326 | ||
|
|
bb864cac5b | ||
|
|
e465ef6d41 | ||
|
|
1303dcce8f | ||
|
|
b6791485c4 | ||
|
|
0708f022bc | ||
|
|
d81478ac97 | ||
|
|
f57004601d | ||
|
|
c104c0b7d0 | ||
|
|
50ceddaa7e | ||
|
|
23803223bf | ||
|
|
438d4ca3fd | ||
|
|
d668d2f2de | ||
|
|
0f704417c6 | ||
|
|
9b8cfafa04 | ||
|
|
195e175186 | ||
|
|
2d5d2c6c06 | ||
|
|
e787eaabcd | ||
|
|
4aec891b1f | ||
|
|
86f04f8b98 | ||
|
|
cee9c90f55 | ||
|
|
2ca744c960 | ||
|
|
854aa34e52 | ||
|
|
b8d4ffcedc | ||
|
|
0380de698c | ||
|
|
380a52d981 | ||
|
|
ddc3c11e12 | ||
|
|
05e1c2e6f8 | ||
|
|
bffd7fb13d | ||
|
|
4fe9c76d90 | ||
|
|
866fee2ea3 | ||
|
|
b9ffe12154 | ||
|
|
09cb2bd261 | ||
|
|
3a4bc18d45 | ||
|
|
32ee590cef | ||
|
|
5ef4ab0756 | ||
|
|
1e26e740fb | ||
|
|
704505958e | ||
|
|
b230641600 | ||
|
|
3f457774dc | ||
|
|
6ff32d0935 | ||
|
|
928b48fd14 | ||
|
|
c040031771 | ||
|
|
324a8ee2e1 | ||
|
|
a866c9b924 | ||
|
|
9877962dd0 | ||
|
|
aef4f75c33 | ||
|
|
8327b4369e | ||
|
|
0403ecbd70 | ||
|
|
16daca09e8 | ||
|
|
9f60a8957b | ||
|
|
9a169bbf3d | ||
|
|
8af0ae6263 | ||
|
|
420baaaf4a | ||
|
|
c56054a05a | ||
|
|
d9b8b1c8ef | ||
|
|
73623ec41a | ||
|
|
02e11e8008 | ||
|
|
22b3641a07 | ||
|
|
913b4ea923 | ||
|
|
88eb2223c5 | ||
|
|
123d11945e | ||
|
|
7a078b2d34 | ||
|
|
054f87cae2 | ||
|
|
f026e4e5ed | ||
|
|
b9bd12e451 | ||
|
|
0f75369658 | ||
|
|
075f2c96b2 | ||
|
|
d3b9aa9808 | ||
|
|
16d42aa6e3 | ||
|
|
e90f038f6a | ||
|
|
bd0c76559b | ||
|
|
42fab806c6 | ||
|
|
fadb5725e0 | ||
|
|
8180f111d0 | ||
|
|
5c30785d8d | ||
|
|
581a1e7153 | ||
|
|
0b9a8be45d | ||
|
|
40883d9461 | ||
|
|
91010c52db | ||
|
|
2546d79f26 | ||
|
|
c3404936fd | ||
|
|
ec635d7de3 | ||
|
|
d416270cad | ||
|
|
3fa6dadb43 | ||
|
|
cee391746f | ||
|
|
8432fa82a8 | ||
|
|
72edfe1112 | ||
|
|
3b2a6800a0 | ||
|
|
6b7ad6b1af | ||
|
|
37d77f579a | ||
|
|
55d68af499 | ||
|
|
1ca4120fd9 | ||
|
|
9164660d19 | ||
|
|
ba78cf050d | ||
|
|
e8d1142a94 | ||
|
|
f40eaf55a3 | ||
|
|
0b85f62858 | ||
|
|
24235174fd | ||
|
|
4a800f99e1 | ||
|
|
96e61c8357 | ||
|
|
f153e57fdb | ||
|
|
bac93e778e | ||
|
|
2aeed10429 | ||
|
|
ea6ad902a7 | ||
|
|
f9c53ee3b0 | ||
|
|
3f0843647c | ||
|
|
a50df870e7 | ||
|
|
716ae11941 | ||
|
|
4ff16ff402 | ||
|
|
bd598b9c44 | ||
|
|
f1253e4ede | ||
|
|
79a3da3358 | ||
|
|
5a6bdfbbba | ||
|
|
3d663be506 | ||
|
|
0ada4cdebe | ||
|
|
d103de96aa | ||
|
|
f248b04834 | ||
|
|
9572f20682 | ||
|
|
409cec08fc | ||
|
|
51f330eae9 | ||
|
|
51750267e5 | ||
|
|
99948d5151 | ||
|
|
030726e6fb | ||
|
|
1fad54272f | ||
|
|
4af4bfd55f | ||
|
|
77cedef5bb | ||
|
|
db36f187dc | ||
|
|
2861eb9c60 | ||
|
|
9811c0d97a | ||
|
|
e9c21373ed | ||
|
|
bda23ec54a | ||
|
|
e23641375b | ||
|
|
024d54345a | ||
|
|
59fd4d3916 | ||
|
|
88d684b6c1 | ||
|
|
94fdf777cb | ||
|
|
dea70152e4 | ||
|
|
614caf5ca0 | ||
|
|
25dbae37fb | ||
|
|
e060032e6a | ||
|
|
4725410c0f | ||
|
|
20488ee400 | ||
|
|
b1c0619af5 | ||
|
|
ade730179a | ||
|
|
9264ad26d6 | ||
|
|
9020e2c7cb | ||
|
|
0f51c34b24 | ||
|
|
f6a427e865 | ||
|
|
9b95930463 | ||
|
|
cb96b4991e | ||
|
|
cde7a51cde | ||
|
|
046d611f56 | ||
|
|
d7b3748159 | ||
|
|
188c9fc726 | ||
|
|
dbc735e63b | ||
|
|
8750486f7b | ||
|
|
6dc4baeeb5 | ||
|
|
ff28828a2e | ||
|
|
e28452dfd1 | ||
|
|
5d7cb5c28f | ||
|
|
08b29f7081 | ||
|
|
c9e034b5b3 | ||
|
|
d9f0ff466f | ||
|
|
6b4b895102 | ||
|
|
0c7e02e7c9 | ||
|
|
4d1c82a623 | ||
|
|
8d33fe6221 | ||
|
|
9d27651411 | ||
|
|
268975bc3b | ||
|
|
66343ba11e | ||
|
|
684cd85a7a | ||
|
|
ef9a80e76f | ||
|
|
fbb5f02379 | ||
|
|
5f4bde96e9 | ||
|
|
f8c8a68840 | ||
|
|
bf6f4a951e | ||
|
|
58c9366548 | ||
|
|
f410ecac2b | ||
|
|
1d1a43ade2 | ||
|
|
37adb56233 | ||
|
|
aca0669bf6 | ||
|
|
b33ab76ff8 | ||
|
|
38a391b7fa | ||
|
|
82434fe87c | ||
|
|
8bf7c36249 | ||
|
|
cff3557a24 | ||
|
|
2c476c4351 | ||
|
|
82c8ab511d | ||
|
|
486ed6edd2 | ||
|
|
a4b0a9ed36 | ||
|
|
bba9c37ba5 | ||
|
|
febc7d1630 | ||
|
|
1ed071949b | ||
|
|
3878c264ef | ||
|
|
21daf0b664 | ||
|
|
5efaa72cea | ||
|
|
191cd7cbba | ||
|
|
c583e31b16 | ||
|
|
590fba7deb | ||
|
|
a8f22003cb | ||
|
|
54596e3fe6 | ||
|
|
2ee4d110a0 | ||
|
|
7a949dccbb | ||
|
|
111a45ab38 | ||
|
|
2bcf59c225 | ||
|
|
d542033125 | ||
|
|
44c72828e1 | ||
|
|
99d3ee32fa | ||
|
|
7df0ff309e | ||
|
|
856a751fcb | ||
|
|
da99bcae5d | ||
|
|
1b0c6c2847 | ||
|
|
c315e817b2 | ||
|
|
6fde07a20d | ||
|
|
8a86159fd7 | ||
|
|
1d532a1fc1 | ||
|
|
a67ce75924 | ||
|
|
b3d845ea32 | ||
|
|
008e12cb42 | ||
|
|
ceaed8be51 | ||
|
|
f0e0979366 | ||
|
|
c43563a804 | ||
|
|
8ec3b2d05d | ||
|
|
39a95c727f | ||
|
|
a2f5a585e3 | ||
|
|
aa95bc62bd | ||
|
|
ae7bfa5bcb | ||
|
|
37de1ec583 | ||
|
|
bb8f0eae1b | ||
|
|
571d3c14c8 | ||
|
|
d7202ae0a7 | ||
|
|
2a9c75e24f | ||
|
|
7231662f94 | ||
|
|
df83927ed7 | ||
|
|
f14dfc5de8 | ||
|
|
188d0c9d5c | ||
|
|
8d68c64fdf | ||
|
|
d796ab350e | ||
|
|
334a1b5bef | ||
|
|
3304ee0985 | ||
|
|
d7b3523544 | ||
|
|
1a8d346064 | ||
|
|
42f9b36667 | ||
|
|
c21e9f2114 | ||
|
|
3dbe605de8 | ||
|
|
41a6dd6175 | ||
|
|
09af6fe0a7 | ||
|
|
3b8c3afa3e | ||
|
|
7b7f4d264c | ||
|
|
c454a4942e | ||
|
|
44cd52af6c | ||
|
|
0d01339b02 | ||
|
|
e5b4ca53f8 | ||
|
|
703b03b33c | ||
|
|
73cdad66ac | ||
|
|
4b1afdbe2d | ||
|
|
64bfc0f29a | ||
|
|
28c4c0b48c | ||
|
|
40ccde9f06 | ||
|
|
baa7d02ba5 | ||
|
|
a391df1e67 | ||
|
|
1f26485208 | ||
|
|
733b72bcbd | ||
|
|
f0816260c5 | ||
|
|
32e9e66e49 | ||
|
|
6e4973cef7 | ||
|
|
4f02472421 | ||
|
|
00ce6be66e | ||
|
|
3eaef148fe | ||
|
|
c92284ab02 | ||
|
|
40718d1180 | ||
|
|
ca325cb7bf | ||
|
|
06e4fc0962 | ||
|
|
8f82ce6ffb | ||
|
|
138f224109 | ||
|
|
ef8c89b999 | ||
|
|
b595a2966c | ||
|
|
3480c5f067 | ||
|
|
a456b10420 | ||
|
|
b7dee707a3 | ||
|
|
9f2f0f1375 | ||
|
|
fe7cf0a595 | ||
|
|
0f79c04d93 | ||
|
|
2d3373efbb | ||
|
|
f3a96b3562 | ||
|
|
7f79fd95b5 | ||
|
|
2eab366a1b | ||
|
|
038a3bb5c8 | ||
|
|
7bef8c99ec | ||
|
|
5cbae6e8e6 | ||
|
|
862c022ec6 | ||
|
|
71349b575b | ||
|
|
2acc08402f | ||
|
|
adf79e1926 | ||
|
|
d2e5c1d33b | ||
|
|
3fce30f709 | ||
|
|
6bdb67f504 | ||
|
|
314f86007e | ||
|
|
476edc6ad3 | ||
|
|
a56cafb97e | ||
|
|
6663b0c257 | ||
|
|
c50d4289c4 | ||
|
|
595080b5c1 | ||
|
|
a9cbd766c8 | ||
|
|
fdfd49105f | ||
|
|
c7afddcfab | ||
|
|
9fe3d4faf0 | ||
|
|
41a827555c | ||
|
|
c9317e4ec5 | ||
|
|
0ae16ccf76 | ||
|
|
73d3b638df | ||
|
|
e2b0a105a7 | ||
|
|
195864d3ac | ||
|
|
c4aa843038 | ||
|
|
843da2664f | ||
|
|
23eaa6a4c7 | ||
|
|
f29bb971e0 | ||
|
|
266123a5e0 | ||
|
|
9b0d01619c | ||
|
|
291162f5f0 | ||
|
|
29820e2ab2 | ||
|
|
a92a72cebd | ||
|
|
fe09dc23a6 | ||
|
|
9cd4a7416e | ||
|
|
f6e3210b0d | ||
|
|
16d33eb02c | ||
|
|
326512697c | ||
|
|
f25de891bf | ||
|
|
e785533858 | ||
|
|
0699bc4147 | ||
|
|
d07a8258e9 | ||
|
|
d490e65315 | ||
|
|
7a632c9561 | ||
|
|
ec4b35fa5f | ||
|
|
b263755629 | ||
|
|
828585a260 | ||
|
|
3b33121dbc | ||
|
|
21484c8184 | ||
|
|
020385c850 | ||
|
|
c585f3d8ae | ||
|
|
3356e6c6cf | ||
|
|
2fa6ad22a3 | ||
|
|
b887519f26 | ||
|
|
b1e54a834c | ||
|
|
171e62a272 | ||
|
|
053770c117 | ||
|
|
911f3e1f54 | ||
|
|
1494ba95b3 | ||
|
|
c0b00ce146 | ||
|
|
47a08b829e | ||
|
|
953bb60aac | ||
|
|
fc4cb31277 | ||
|
|
9876636dbc | ||
|
|
8314ab03bd | ||
|
|
9d887ba3e7 | ||
|
|
1612a8a960 | ||
|
|
99af210e62 | ||
|
|
8fd108cde1 | ||
|
|
ca81d35936 | ||
|
|
d65aacac6f | ||
|
|
43f052a363 | ||
|
|
0e0a38ffa2 | ||
|
|
819586fc4e | ||
|
|
6b8a331428 | ||
|
|
57e7004e05 | ||
|
|
25c95cafe3 | ||
|
|
54be1a8918 | ||
|
|
d4a0573051 | ||
|
|
4a96eac67b | ||
|
|
2f4134a6d2 | ||
|
|
4f87dcc0c0 | ||
|
|
47eba6b720 | ||
|
|
cba537d561 | ||
|
|
c9d03cb042 | ||
|
|
e42c002fbd | ||
|
|
7c7b073a47 | ||
|
|
20090d21eb | ||
|
|
b0e69ff4b8 | ||
|
|
552bb0a98b | ||
|
|
19510858af | ||
|
|
44b2f6ee63 | ||
|
|
c5d3002f31 | ||
|
|
2e3659d4ee | ||
|
|
f8a5509a91 | ||
|
|
421f436871 | ||
|
|
a37c9d6cea | ||
|
|
d14d576d99 | ||
|
|
9391e44e4b | ||
|
|
a7aebe3a61 | ||
|
|
1fca9021a4 | ||
|
|
a39194b2ad | ||
|
|
bff93d9352 | ||
|
|
d76c9cd16d | ||
|
|
14774fe235 | ||
|
|
39046632aa | ||
|
|
fbb2afdb49 | ||
|
|
aff0402f71 | ||
|
|
cee9058c77 | ||
|
|
3f922b4c90 | ||
|
|
02d2d31cf3 | ||
|
|
240cf6a0ed | ||
|
|
dcd9ee93de | ||
|
|
2a8cd74ab1 | ||
|
|
63bc7055c2 | ||
|
|
1cca9733d6 | ||
|
|
1104da5e2c | ||
|
|
3a9718c09d | ||
|
|
55362c5573 | ||
|
|
0bba2299b3 | ||
|
|
45685af9e9 | ||
|
|
6c416a9338 | ||
|
|
1b0027e1d2 | ||
|
|
2409adf516 | ||
|
|
554801dfe4 | ||
|
|
20c23917e9 | ||
|
|
ef953b7574 | ||
|
|
6b79795229 | ||
|
|
9cb7ec2348 | ||
|
|
437c981d30 | ||
|
|
0334cae4c8 | ||
|
|
24c405d747 | ||
|
|
a3f5962809 | ||
|
|
0deb7495f0 | ||
|
|
d34f89fc4b | ||
|
|
a909ed498f | ||
|
|
16f4e17e8f | ||
|
|
0e9592a96c | ||
|
|
704ee6a53a | ||
|
|
5b9afbce9a | ||
|
|
396cc8e8ef | ||
|
|
bf776b5c06 | ||
|
|
be319f88d3 | ||
|
|
af40d555d4 | ||
|
|
f802dbe686 | ||
|
|
2379e3d83b | ||
|
|
9e90ac0412 | ||
|
|
c27948ca3c | ||
|
|
c3b9d664df | ||
|
|
31ef0a5223 | ||
|
|
14c58acea1 | ||
|
|
5dae20603e | ||
|
|
3f6fa94289 | ||
|
|
117615a8b0 | ||
|
|
4a52773c7d | ||
|
|
edfee495c6 | ||
|
|
7d112df7c6 | ||
|
|
9acaaade45 | ||
|
|
aaca28dbf6 | ||
|
|
d4ef5f9d4d | ||
|
|
2095dea801 | ||
|
|
a36f7ef10d | ||
|
|
9874962ee3 | ||
|
|
4b08022075 | ||
|
|
dc3db3aec4 | ||
|
|
0568c2a93d | ||
|
|
7ab0a6fc9e | ||
|
|
d6b780762e | ||
|
|
5ef66b5cf6 | ||
|
|
19e8cd5e48 | ||
|
|
df5117892f | ||
|
|
aaa4216f55 | ||
|
|
85ee5084b6 | ||
|
|
bb9ce117de | ||
|
|
00c5aa26bb | ||
|
|
bae4de227c | ||
|
|
253f891c5a | ||
|
|
6966159062 | ||
|
|
07d3b80c3e | ||
|
|
a41d0f3214 | ||
|
|
1ee15de78b | ||
|
|
b044358970 | ||
|
|
d2e11bb3bb | ||
|
|
a55bac899c | ||
|
|
c2380fb8df | ||
|
|
f31c644b13 | ||
|
|
26cd621d0e | ||
|
|
4c58512c54 | ||
|
|
04c1b47660 | ||
|
|
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 | ||
|
|
5022ed1a63 | ||
|
|
799ffa18c4 | ||
|
|
6323e27040 | ||
|
|
03acb26109 | ||
|
|
34fc1f6a6b | ||
|
|
042032ec46 | ||
|
|
73de99f661 | ||
|
|
cc068f9ebb | ||
|
|
2bfc2b1944 | ||
|
|
029936112f | ||
|
|
d5e400e8a4 | ||
|
|
9dbb9c3f3b | ||
|
|
a101e6b0a7 | ||
|
|
c525ea55ce | ||
|
|
8ca45f298f | ||
|
|
cb4c6cb677 | ||
|
|
d574a97a35 | ||
|
|
20f9a86ad9 | ||
|
|
a4a411cf1f | ||
|
|
029bda5734 | ||
|
|
0fd578e6aa | ||
|
|
95e1bee5e6 | ||
|
|
c8dc10f311 | ||
|
|
a00f4e393b | ||
|
|
5a7dea8857 | ||
|
|
27e8970fff | ||
|
|
7848274ba1 | ||
|
|
145bf0298b | ||
|
|
0392a33b54 | ||
|
|
b211f46e3e | ||
|
|
709711c3ca | ||
|
|
841607406f | ||
|
|
70b726b04d | ||
|
|
2799248106 | ||
|
|
2321299084 | ||
|
|
aa00773a3b | ||
|
|
733de1d0e1 | ||
|
|
c16e4ad412 | ||
|
|
d1cf7a07f1 | ||
|
|
8751f6fea7 | ||
|
|
ea1b577ec7 | ||
|
|
a41afa70eb | ||
|
|
e11c97cdc0 | ||
|
|
d76e44512e | ||
|
|
fd1931377d | ||
|
|
68ce6c4ed7 | ||
|
|
a2ee330307 | ||
|
|
c3a17f951e | ||
|
|
443c0f34d7 | ||
|
|
8725600368 | ||
|
|
3b83b7f190 | ||
|
|
e0c3a1c143 | ||
|
|
bec1ad7bee | ||
|
|
9e6c00f78c | ||
|
|
abbbd9d705 | ||
|
|
4a5c012f05 | ||
|
|
319862b3d4 | ||
|
|
1fcf58024d | ||
|
|
9db162d0fc | ||
|
|
13b15390c3 | ||
|
|
799b62e9d2 | ||
|
|
d91ed535ad | ||
|
|
c48b9874bf | ||
|
|
6a788f6c32 | ||
|
|
53519a604e | ||
|
|
2818b87f02 | ||
|
|
50e10133b9 | ||
|
|
068161719e | ||
|
|
c8d5d095e0 | ||
|
|
52d07320ef | ||
|
|
158b9ea2ca | ||
|
|
6a100bfbab | ||
|
|
b3bd6ee176 | ||
|
|
04696b27eb | ||
|
|
332937dbc1 | ||
|
|
92d932ce5c | ||
|
|
af3c4f536a | ||
|
|
b98ca5af52 | ||
|
|
a15a11f44b | ||
|
|
1460132772 | ||
|
|
76d68bb3e4 | ||
|
|
08df0ebbea | ||
|
|
e918db2cc1 | ||
|
|
2e0dc8db94 | ||
|
|
b78a9f2a9c | ||
|
|
832e6b9de0 | ||
|
|
feec7ca408 | ||
|
|
408f0a12e2 | ||
|
|
35ab4e6e09 | ||
|
|
430bafafe7 | ||
|
|
58d727350d | ||
|
|
c6a4057659 | ||
|
|
60ac806690 | ||
|
|
e9263fc596 | ||
|
|
3dd28a0382 | ||
|
|
066cb8184e | ||
|
|
373e22b999 | ||
|
|
fd8725f649 | ||
|
|
3d433762b1 | ||
|
|
ea4cb5bf62 | ||
|
|
a6ca3b8203 | ||
|
|
bc4ceb6d52 | ||
|
|
24480229cd | ||
|
|
8b10573197 | ||
|
|
cbc81e8285 | ||
|
|
0b9a978061 | ||
|
|
e974e5d13b | ||
|
|
5a42e86bf6 | ||
|
|
889946e186 | ||
|
|
5c47e8044e | ||
|
|
1a974ac305 | ||
|
|
db1bf61805 | ||
|
|
5456b4a7ff | ||
|
|
a08ffaae77 | ||
|
|
18445f55f0 | ||
|
|
2daf3b5c4b | ||
|
|
923b844212 | ||
|
|
0aec9f8472 | ||
|
|
23b0c8a143 | ||
|
|
3c2c2e2bd8 | ||
|
|
c1465a7368 | ||
|
|
be1dadab74 | ||
|
|
1cba39eae9 | ||
|
|
a0c8bdf021 | ||
|
|
6fdb22a5b5 | ||
|
|
19c370a273 | ||
|
|
861336ea97 | ||
|
|
24219bcb03 | ||
|
|
77ed762e2c | ||
|
|
d45b6cb03d | ||
|
|
9a921b2e0d | ||
|
|
c17e213e11 | ||
|
|
6275d7afaa | ||
|
|
364eda6400 | ||
|
|
ccf34cfe20 | ||
|
|
7daae6a2d9 | ||
|
|
277a4ad124 | ||
|
|
b11d46e34a | ||
|
|
e8ad0a055d | ||
|
|
8a8c745d77 | ||
|
|
a523fe7674 | ||
|
|
dc9a150929 | ||
|
|
be66ffef0f | ||
|
|
f278cc0c86 | ||
|
|
7f72808a9a | ||
|
|
1d5297c0f0 | ||
|
|
e40528ba45 | ||
|
|
29972b5867 | ||
|
|
91109ca845 | ||
|
|
8e5ccb5461 | ||
|
|
8a75967953 | ||
|
|
3f4965b182 | ||
|
|
2ac266029c | ||
|
|
3261231d07 | ||
|
|
95ce6385b0 | ||
|
|
64c5894602 | ||
|
|
8c4839c300 | ||
|
|
80c2bc1a52 | ||
|
|
bcd417e039 | ||
|
|
ac216f697f | ||
|
|
9893fae27c | ||
|
|
cb183efa66 | ||
|
|
87d707bc21 | ||
|
|
227ebd610a | ||
|
|
ab4af48e52 | ||
|
|
78a8227219 | ||
|
|
ec73a53101 | ||
|
|
3fb1d086b7 | ||
|
|
5d4a12c127 | ||
|
|
d2a79214b5 | ||
|
|
db57111188 | ||
|
|
b22276bcd5 | ||
|
|
6e2d85f2d2 | ||
|
|
efb72652ce | ||
|
|
3615c3e8e5 | ||
|
|
8186ee0e3f | ||
|
|
74aa14c011 | ||
|
|
aa68369f95 | ||
|
|
7837364b86 | ||
|
|
31f0e39617 | ||
|
|
a48151920d | ||
|
|
8199653ddd | ||
|
|
9d650519c7 | ||
|
|
a545eaca97 | ||
|
|
9da9de2d2d | ||
|
|
c9ddd9d513 | ||
|
|
415cfd57e7 | ||
|
|
b1ede93cdb | ||
|
|
32df465c8a | ||
|
|
2f1c5df11d | ||
|
|
f85f6a7fdc | ||
|
|
93cc80a4b3 | ||
|
|
0f3e401d42 | ||
|
|
a9f2c33053 | ||
|
|
c5ef8c3fec | ||
|
|
ad696bd60b | ||
|
|
9da7462f3e | ||
|
|
0ecdf354c6 | ||
|
|
67f10632fb | ||
|
|
044b910357 | ||
|
|
3de943e50f | ||
|
|
1a2272249d | ||
|
|
0dfeec6cae | ||
|
|
8d193021ab | ||
|
|
f45226a680 | ||
|
|
40d55805ff | ||
|
|
7d6d0b012b | ||
|
|
d7d2c6bf01 | ||
|
|
ce1c6096d3 | ||
|
|
8c4ea6180a | ||
|
|
95649ba758 | ||
|
|
2b61f2a9e8 | ||
|
|
47242aa66c | ||
|
|
31a8abe615 | ||
|
|
4dae3c34b4 | ||
|
|
65aa8919b9 | ||
|
|
acf8eac0d4 | ||
|
|
e8aa29d3c2 | ||
|
|
a36194afe2 | ||
|
|
8554898e45 | ||
|
|
55b29f645b | ||
|
|
52cc91ba3e | ||
|
|
c9e3a9f8fe | ||
|
|
c3de788956 | ||
|
|
53e3c36f7e | ||
|
|
20908107a0 | ||
|
|
cbe1a0d6f8 | ||
|
|
7d8c79ec57 | ||
|
|
9bb89c728f | ||
|
|
be2e28cc53 | ||
|
|
57be57971d | ||
|
|
64eed47f04 | ||
|
|
7659105fda | ||
|
|
18c9376992 | ||
|
|
3a4aca7fbd | ||
|
|
85ff8cdd4a | ||
|
|
b1048cb84a | ||
|
|
ff9cf9abf6 | ||
|
|
157c84663d | ||
|
|
908e4fb5a4 | ||
|
|
fdca7d58e5 | ||
|
|
2eb26d512b | ||
|
|
b7fdf7d60f | ||
|
|
2a1e66468d | ||
|
|
cd7faf751e | ||
|
|
d79d806cda | ||
|
|
cae389c04c | ||
|
|
4e6850a60c | ||
|
|
a71f8cf358 | ||
|
|
fe6ff9b2b6 | ||
|
|
5a0f3e474d | ||
|
|
cd9c4239b1 | ||
|
|
0cf1d87b12 | ||
|
|
99d91c1e07 | ||
|
|
457f80bc9b | ||
|
|
968e3fc23b | ||
|
|
b1e338579d | ||
|
|
7e4361bb5e | ||
|
|
dd35fa3d91 | ||
|
|
affb911d97 | ||
|
|
785f9cd1b6 | ||
|
|
419056f098 | ||
|
|
396db18de2 | ||
|
|
f124721cd9 | ||
|
|
52e49b49fb | ||
|
|
10e03777e9 | ||
|
|
27538b72e9 | ||
|
|
19ace37a75 | ||
|
|
90c5377ef0 | ||
|
|
f0e3d3e474 | ||
|
|
26064ebf8c | ||
|
|
1d92b74131 | ||
|
|
5f83c137d2 | ||
|
|
fa57db8e83 | ||
|
|
9d3c2e19f5 | ||
|
|
46a9600d55 | ||
|
|
de40701cf6 | ||
|
|
307536c6b6 | ||
|
|
203be8bd35 | ||
|
|
1e644587b3 | ||
|
|
66a60f09e3 | ||
|
|
69b6f16ec1 | ||
|
|
10b4274a3d | ||
|
|
28c9d94457 | ||
|
|
d74fd1a560 | ||
|
|
624b1b06c5 | ||
|
|
95376c2ccc | ||
|
|
1eb622165b | ||
|
|
9d6ba324fb | ||
|
|
d462852ab9 | ||
|
|
eeec81898b | ||
|
|
ab0c8b8170 | ||
|
|
91d295e0bb | ||
|
|
125974dd7a | ||
|
|
92895a7d00 | ||
|
|
d9308440e6 | ||
|
|
5340142c06 | ||
|
|
012d30ee9f | ||
|
|
031d69d996 | ||
|
|
8b63c18f65 | ||
|
|
dc2f11eb2b | ||
|
|
13e64a9487 | ||
|
|
6a3c88ae5b | ||
|
|
08a7e324aa | ||
|
|
9202a4525f | ||
|
|
bfc756fb35 | ||
|
|
2a735ff1cc | ||
|
|
551092a1b4 | ||
|
|
ddd12688aa | ||
|
|
71767c4172 | ||
|
|
ee405fbff6 | ||
|
|
c87c6fbabb | ||
|
|
096b36b89b | ||
|
|
c3db90d2e3 | ||
|
|
b7df10aa45 | ||
|
|
fea5e02e7d | ||
|
|
cb94261727 | ||
|
|
efac7e4860 | ||
|
|
0f6fd3adee | ||
|
|
e5e0405401 | ||
|
|
bb35e9ce15 | ||
|
|
5881db4e55 | ||
|
|
89f7167b08 | ||
|
|
3b39fcff84 | ||
|
|
0daf45a465 | ||
|
|
c0d7b96e79 | ||
|
|
a247e40865 | ||
|
|
c3e7a99bca | ||
|
|
9080d8be6a | ||
|
|
b7ee83f6b6 | ||
|
|
1e24bde9a9 | ||
|
|
ba82df1152 | ||
|
|
8980fe7838 | ||
|
|
ef34ed7c20 | ||
|
|
17d60b79ca | ||
|
|
ab0a32c339 | ||
|
|
697778df8d | ||
|
|
55caf84b94 | ||
|
|
335c012f1b | ||
|
|
3c4c538de8 | ||
|
|
c344a3ee55 | ||
|
|
d2695947ed | ||
|
|
21beeef920 | ||
|
|
a4630a53fa | ||
|
|
f5aef8d0c3 | ||
|
|
e044e66030 | ||
|
|
88bfacd386 | ||
|
|
c61c73088f | ||
|
|
2887263f26 | ||
|
|
72b90bdf5c | ||
|
|
163b02f023 | ||
|
|
1a96899336 | ||
|
|
554c086aba | ||
|
|
1fad9bf7db | ||
|
|
22d922e451 | ||
|
|
70bff21632 | ||
|
|
f58c390a47 | ||
|
|
089a9abcb4 | ||
|
|
bf1c76d0a6 | ||
|
|
879da627b1 | ||
|
|
9b93eb44d5 | ||
|
|
b30220eca9 | ||
|
|
d270d4e5e1 | ||
|
|
21da6cb0f4 | ||
|
|
6ac75df935 | ||
|
|
f29781349c | ||
|
|
bb776d5c2b | ||
|
|
6cfab9e3ea | ||
|
|
6373186c15 | ||
|
|
e342de3bc1 | ||
|
|
4cd7b69ea5 | ||
|
|
988e8529da | ||
|
|
6a32d1e961 | ||
|
|
0552c798fb | ||
|
|
a53ad41879 | ||
|
|
92351edcd0 | ||
|
|
878eb48cb0 | ||
|
|
053ca6bed8 | ||
|
|
78ae14ab2f | ||
|
|
5fdc2ad765 | ||
|
|
b75dbe8d5c | ||
|
|
eaf4663c84 | ||
|
|
64b8cd5bcc | ||
|
|
482d61ee47 | ||
|
|
276dcce95e | ||
|
|
217f9e2e02 | ||
|
|
f40a0a6f5f | ||
|
|
9bd67acc2f | ||
|
|
e87da0feb0 | ||
|
|
2608d879fa | ||
|
|
6ab61fd41f | ||
|
|
30dd6297ee | ||
|
|
ce02183f82 | ||
|
|
7c74a6cbe1 | ||
|
|
e6a11b2ad8 | ||
|
|
158942d1b5 | ||
|
|
aaa97ec029 | ||
|
|
882ead5715 | ||
|
|
ab4519dedd | ||
|
|
c3fd2428a2 | ||
|
|
fbb4b962fa | ||
|
|
9bf65de649 | ||
|
|
75f069cb7d | ||
|
|
87d50125ab | ||
|
|
dc2cf21cb8 | ||
|
|
bae14ecd35 | ||
|
|
b48c1c3b80 | ||
|
|
0f9eb4beeb | ||
|
|
0ab8624d79 | ||
|
|
e872c934c3 | ||
|
|
c3d5d18aae | ||
|
|
ff5853a850 | ||
|
|
f772906324 | ||
|
|
07eabb2dc1 | ||
|
|
b3c88763a4 | ||
|
|
f7081f8829 | ||
|
|
ceef2167fd | ||
|
|
1dcfd94328 | ||
|
|
a1aa0804e2 | ||
|
|
77176478eb | ||
|
|
bf4ebfa7a8 | ||
|
|
6e7d622b41 | ||
|
|
8398b7d24d | ||
|
|
aef9b7375a | ||
|
|
ba45318b56 | ||
|
|
7d4f8780ad | ||
|
|
b504c990f8 | ||
|
|
e07b876677 | ||
|
|
a0bfd34951 | ||
|
|
b173714bbe | ||
|
|
db4021b601 | ||
|
|
2f46fd1d2c | ||
|
|
1f85f848e2 | ||
|
|
d7e0954e86 | ||
|
|
1671e05d12 | ||
|
|
33c55d1563 | ||
|
|
4984181613 | ||
|
|
af75136269 | ||
|
|
c8eb75a148 | ||
|
|
5109b4fcd1 | ||
|
|
1b7f482d0b | ||
|
|
6f9a273d39 | ||
|
|
51d354a9c8 | ||
|
|
40b2b9554b | ||
|
|
ba1aca84ff | ||
|
|
17688a49d5 | ||
|
|
5ff199cc3e | ||
|
|
81a79105d7 | ||
|
|
e39760ccfb | ||
|
|
1c43da2532 | ||
|
|
2846def00f | ||
|
|
e2eb6ab33c | ||
|
|
35b08d085c | ||
|
|
064b0581a7 | ||
|
|
0cc38aa69a | ||
|
|
8312483659 | ||
|
|
0ceb0b4421 | ||
|
|
cc373365fb | ||
|
|
75d9b6e2a1 | ||
|
|
78fa38ba68 | ||
|
|
0b28712a34 | ||
|
|
48937c8d9a | ||
|
|
8c966a5e1a | ||
|
|
f49dd371b7 | ||
|
|
6947fbc12a | ||
|
|
550dc43dc0 | ||
|
|
23c9a4fea7 | ||
|
|
7d26f3351f | ||
|
|
b546554fef | ||
|
|
cc058a7cd3 | ||
|
|
7654b83339 | ||
|
|
93426546ad | ||
|
|
23bc38ca6c | ||
|
|
5ccce364d3 | ||
|
|
b488b55a71 | ||
|
|
0bace17074 | ||
|
|
ad6c7dbd1f | ||
|
|
2a6e63595e | ||
|
|
4d62ad1938 | ||
|
|
e7c3a24011 | ||
|
|
37468607fe | ||
|
|
5b007129e3 | ||
|
|
93ceb4d49c | ||
|
|
85b806fcba | ||
|
|
20596aabb8 | ||
|
|
825108c59e | ||
|
|
09c31b20e6 | ||
|
|
78271a3738 | ||
|
|
e029aaadfc | ||
|
|
f6efa35ed2 | ||
|
|
728bad00b4 | ||
|
|
97f3013f7a | ||
|
|
269a832ac9 | ||
|
|
3b5b7af531 | ||
|
|
76e7eb7009 | ||
|
|
fa99b8829d | ||
|
|
98b749ee9f | ||
|
|
cb9fd02dc7 | ||
|
|
1f4a271dd6 | ||
|
|
bdf192df58 | ||
|
|
1249304907 | ||
|
|
10e3ab1f78 | ||
|
|
59ea270b2f | ||
|
|
3b748e2e21 | ||
|
|
432fae5ce2 | ||
|
|
f557ceda19 | ||
|
|
943f6c762c | ||
|
|
5a9293e293 | ||
|
|
a1bc52c1a5 | ||
|
|
dcd752be8f | ||
|
|
deb2c61b28 | ||
|
|
5e346283a9 | ||
|
|
dc1e4219a0 | ||
|
|
a916f70698 | ||
|
|
77da4d2d53 | ||
|
|
1ae3fc86da | ||
|
|
0c24996b44 | ||
|
|
1cbb4a93eb | ||
|
|
1fac6ca34a | ||
|
|
ca439b0f86 | ||
|
|
f70febc8d3 | ||
|
|
628de56087 | ||
|
|
bc67033c00 | ||
|
|
e0ba2a179c | ||
|
|
e0ce5d9544 | ||
|
|
38acfe04b9 | ||
|
|
5b0068d9e4 | ||
|
|
38edad2ac5 | ||
|
|
e95f191dc6 | ||
|
|
8ae92ff4d4 | ||
|
|
40e15d456a | ||
|
|
a1b3308cd7 | ||
|
|
48ef19e4be | ||
|
|
d3f00b9246 | ||
|
|
89de676982 | ||
|
|
6dec624d22 | ||
|
|
d4eb9ea320 | ||
|
|
1cfaa88989 | ||
|
|
82ae0891a8 | ||
|
|
58c43b0cd4 | ||
|
|
1c373031bd | ||
|
|
e93842a95f | ||
|
|
9cdb34cb1d | ||
|
|
864f9b8f74 | ||
|
|
d99fae333a | ||
|
|
b27bec3e16 | ||
|
|
5fb4838734 | ||
|
|
1296255a86 | ||
|
|
e3ed2fcaa9 | ||
|
|
69d6b90a12 | ||
|
|
6937a4b2fe | ||
|
|
621c36f821 | ||
|
|
940929d044 | ||
|
|
bac5fa8c14 | ||
|
|
a10da64378 | ||
|
|
f2c12c582e | ||
|
|
a686c44555 | ||
|
|
8e96217ae6 | ||
|
|
ec906813fc | ||
|
|
36543d0872 | ||
|
|
fc6ea0b779 | ||
|
|
dae23ccd4b | ||
|
|
666cd3c81f | ||
|
|
dc5366e924 | ||
|
|
f21b3bb0e4 | ||
|
|
4ebcc36fb3 | ||
|
|
292cfb0d3d | ||
|
|
1b59917f16 | ||
|
|
fcf64a7e1b | ||
|
|
b598584aea | ||
|
|
0ebcacce69 | ||
|
|
33c38288a3 | ||
|
|
f00e3ded45 | ||
|
|
250483fbe7 | ||
|
|
755a060e12 | ||
|
|
6d3839dd42 | ||
|
|
15084459bb | ||
|
|
7150445f8e | ||
|
|
b02bdd22dd | ||
|
|
8755cd9d61 | ||
|
|
2c4c07dc81 | ||
|
|
645771c03d | ||
|
|
b2af69fd92 | ||
|
|
ca57732871 | ||
|
|
cd9e98f24b | ||
|
|
136da65381 | ||
|
|
b909cb2db8 | ||
|
|
3a4b531edf | ||
|
|
413453dd85 | ||
|
|
fe52d26f05 | ||
|
|
6029c0d0b3 | ||
|
|
12bfe9d6ca | ||
|
|
dd910f2856 | ||
|
|
b4e0d9e996 | ||
|
|
d3f691548c | ||
|
|
367131d64c | ||
|
|
2895b7bc21 | ||
|
|
f9cdd55a4d | ||
|
|
1854373dd6 | ||
|
|
00a621a5f7 | ||
|
|
f047bd797e | ||
|
|
777f8b4276 | ||
|
|
0992b7fc93 | ||
|
|
b7d6208869 | ||
|
|
da4ce27168 | ||
|
|
4746401bec | ||
|
|
79cf399bf5 | ||
|
|
563323f241 | ||
|
|
e2048dfa1c | ||
|
|
c986c63b84 | ||
|
|
0b3426a9b2 | ||
|
|
173e507ebf | ||
|
|
fb3b1490a9 | ||
|
|
48502480df | ||
|
|
efb3b8f38c | ||
|
|
f185b1773c | ||
|
|
95fff4c9f7 | ||
|
|
27662f9a4a | ||
|
|
f9f678a801 | ||
|
|
8e07e7553a | ||
|
|
bb566e3c7b | ||
|
|
35c68a6de1 | ||
|
|
7fd8394253 | ||
|
|
c54a447caf | ||
|
|
61b009422d | ||
|
|
5a8b0184ea | ||
|
|
f48c2a21d9 | ||
|
|
538cfbee8d | ||
|
|
7666f1c362 | ||
|
|
4b5d828bf8 | ||
|
|
4bd160cceb | ||
|
|
5f56fc1156 | ||
|
|
72a2a74395 | ||
|
|
f6a5cc7c25 | ||
|
|
80f3bd64b6 | ||
|
|
1f69a96766 | ||
|
|
f963e06983 | ||
|
|
e6980e2370 | ||
|
|
8e8105d04d | ||
|
|
21d9e69712 | ||
|
|
e0783a3c6e | ||
|
|
3b9337d2a8 | ||
|
|
85cda8ffa7 | ||
|
|
f1efc1f17d | ||
|
|
0486fa61cd | ||
|
|
2247a2a7af | ||
|
|
08a0fbfd6b | ||
|
|
898b993b94 | ||
|
|
77e366b179 | ||
|
|
981edc9cf7 | ||
|
|
d45aa14348 | ||
|
|
4926488d49 | ||
|
|
dcc1935150 | ||
|
|
55364a8eb8 | ||
|
|
70bb06715f | ||
|
|
ec4aa73e37 | ||
|
|
c1d122a717 |
2
.contextProperties.ini
Normal file
2
.contextProperties.ini
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[General]
|
||||||
|
disableUnqualifiedAccess = "i18nc,xi18nc,i18ncp"
|
||||||
@@ -2,4 +2,5 @@
|
|||||||
; SPDX-License-Identifier: CC0-1.0
|
; SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
[BlueprintSettings]
|
[BlueprintSettings]
|
||||||
kde/applications/neochat.packageAppx = True
|
kde/applications/neochat.packageAppx=True
|
||||||
|
libs/qt.qtMajorVersion=6
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"id": "org.kde.neochat",
|
"id": "org.kde.neochat",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"runtime": "org.kde.Platform",
|
"runtime": "org.kde.Platform",
|
||||||
"runtime-version": "6.6",
|
"runtime-version": "6.9",
|
||||||
"sdk": "org.kde.Sdk",
|
"sdk": "org.kde.Sdk",
|
||||||
"command": "neochat",
|
"command": "neochat",
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -20,18 +20,36 @@
|
|||||||
"--talk-name=org.kde.kwalletd5",
|
"--talk-name=org.kde.kwalletd5",
|
||||||
"--talk-name=org.kde.StatusNotifierWatcher",
|
"--talk-name=org.kde.StatusNotifierWatcher",
|
||||||
"--talk-name=org.freedesktop.secrets",
|
"--talk-name=org.freedesktop.secrets",
|
||||||
|
"--talk-name=org.kde.kuiserver",
|
||||||
"--own-name=org.kde.StatusNotifierItem-2-2"
|
"--own-name=org.kde.StatusNotifierItem-2-2"
|
||||||
],
|
],
|
||||||
|
"cleanup": [
|
||||||
|
"/include",
|
||||||
|
"/lib/*.a",
|
||||||
|
"/lib/cmake",
|
||||||
|
"/lib/pkgconfig",
|
||||||
|
"/share/ndk-modules"
|
||||||
|
],
|
||||||
"modules": [
|
"modules": [
|
||||||
{
|
{
|
||||||
"name": "kirigamiaddons",
|
"name": "kirigamiaddons",
|
||||||
"config-opts": [ "-DBUILD_TESTING=OFF" ],
|
"config-opts": [
|
||||||
|
"-DBUILD_TESTING=OFF"
|
||||||
|
],
|
||||||
"buildsystem": "cmake-ninja",
|
"buildsystem": "cmake-ninja",
|
||||||
"sources": [ { "type": "git", "url": "https://invent.kde.org/libraries/kirigami-addons.git" } ]
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://invent.kde.org/libraries/kirigami-addons.git"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "kquickimageeditor",
|
"name": "kquickimageeditor",
|
||||||
"config-opts": [ "-DBUILD_WITH_QT6=ON" ],
|
"config-opts": [
|
||||||
|
"-DBUILD_WITH_QT6=ON",
|
||||||
|
"-DBUILD_TESTING=OFF"
|
||||||
|
],
|
||||||
"buildsystem": "cmake-ninja",
|
"buildsystem": "cmake-ninja",
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
@@ -43,17 +61,19 @@
|
|||||||
{
|
{
|
||||||
"name": "olm",
|
"name": "olm",
|
||||||
"buildsystem": "cmake-ninja",
|
"buildsystem": "cmake-ninja",
|
||||||
"config-opts": [ "-DOLM_TESTS=OFF" ],
|
"config-opts": [
|
||||||
|
"-DOLM_TESTS=OFF"
|
||||||
|
],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://gitlab.matrix.org/matrix-org/olm.git",
|
"url": "https://gitlab.matrix.org/matrix-org/olm.git",
|
||||||
"tag": "3.2.10",
|
"tag": "3.2.16",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"tag-pattern": "^([\\d.]+)$"
|
"tag-pattern": "^([\\d.]+)$"
|
||||||
},
|
},
|
||||||
"commit": "9908862979147a71dc6abaecd521be526ae77be1"
|
"commit": "7e0c8277032e40308987257b711b38af8d77cc69"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -65,13 +85,13 @@
|
|||||||
"-Dvapi=false",
|
"-Dvapi=false",
|
||||||
"-Dgtk_doc=false",
|
"-Dgtk_doc=false",
|
||||||
"-Dintrospection=false",
|
"-Dintrospection=false",
|
||||||
"-Dgcrypt=false"
|
"-Dcrypto=disabled"
|
||||||
],
|
],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"url": "https://download.gnome.org/sources/libsecret/0.20/libsecret-0.20.5.tar.xz",
|
"url": "https://download.gnome.org/sources/libsecret/0.21/libsecret-0.21.7.tar.xz",
|
||||||
"sha256": "3fb3ce340fcd7db54d87c893e69bfc2b1f6e4d4b279065ffe66dac9f0fd12b4d",
|
"sha256": "6b452e4750590a2b5617adc40026f28d2f4903de15f1250e1d1c40bfd68ed55e",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "gnome",
|
"type": "gnome",
|
||||||
"name": "libsecret",
|
"name": "libsecret",
|
||||||
@@ -86,13 +106,13 @@
|
|||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"url": "https://github.com/frankosterfeld/qtkeychain/archive/0.14.2.tar.gz",
|
"url": "https://github.com/frankosterfeld/qtkeychain/archive/refs/tags/0.15.0.tar.gz",
|
||||||
"sha256": "cf2e972b783ba66334a79a30f6b3a1ea794a1dc574d6c3bebae5ffd2f0399571",
|
"sha256": "f4254dc8f0933b06d90672d683eab08ef770acd8336e44dfa030ce041dc2ca22",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "anitya",
|
"type": "anitya",
|
||||||
"project-id": 4138,
|
"project-id": 4138,
|
||||||
"stable-only": true,
|
"stable-only": true,
|
||||||
"url-template": "https://github.com/frankosterfeld/qtkeychain/archive/v$version.tar.gz"
|
"url-template": "https://github.com/frankosterfeld/qtkeychain/archive/refs/tags/$version.tar.gz"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -100,7 +120,8 @@
|
|||||||
"-DBUILD_WITH_QT6=ON",
|
"-DBUILD_WITH_QT6=ON",
|
||||||
"-DCMAKE_INSTALL_LIBDIR=/app/lib",
|
"-DCMAKE_INSTALL_LIBDIR=/app/lib",
|
||||||
"-DLIB_INSTALL_DIR=/app/lib",
|
"-DLIB_INSTALL_DIR=/app/lib",
|
||||||
"-DBUILD_TRANSLATIONS=NO"
|
"-DBUILD_TRANSLATIONS=NO",
|
||||||
|
"-DBUILD_TESTING=OFF"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -123,34 +144,33 @@
|
|||||||
{
|
{
|
||||||
"name": "cmark",
|
"name": "cmark",
|
||||||
"buildsystem": "cmake-ninja",
|
"buildsystem": "cmake-ninja",
|
||||||
"config-opts": [ "-DCMARK_TESTS=OFF" ],
|
"config-opts": [
|
||||||
|
"-DCMARK_TESTS=OFF",
|
||||||
|
"-DCMAKE_BUILD_TYPE=Release",
|
||||||
|
"-DCMAKE_INSTALL_PREFIX=/app"
|
||||||
|
],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/commonmark/cmark.git"
|
"url": "https://github.com/commonmark/cmark.git"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"config-opts": [
|
|
||||||
"-DCMARK_TESTS=OFF",
|
|
||||||
"-DCMAKE_BUILD_TYPE=Release",
|
|
||||||
"-DCMAKE_INSTALL_PREFIX=/app"
|
|
||||||
],
|
|
||||||
"builddir": true
|
"builddir": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "qcoro",
|
"name": "kunifiedpush",
|
||||||
"buildsystem": "cmake-ninja",
|
"buildsystem": "cmake-ninja",
|
||||||
"config-opts": [ "-DQCORO_BUILD_EXAMPLES=OFF", "-DBUILD_TESTING=OFF" ],
|
"builddir": true,
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"url": "https://github.com/danvratil/qcoro/archive/refs/tags/v0.7.0.tar.gz",
|
"url": "https://download.kde.org/stable/release-service/25.04.3/src/kunifiedpush-25.04.3.tar.xz",
|
||||||
"sha256": "23ef0217926e67c8d2eb861cf91617da2f7d8d5a9ae6c62321b21448b1669210",
|
"sha256": "a16ffe4117b14baa02f3b8ae7de9e509a17359c1b67dcd851aef4f3c3661a1df",
|
||||||
"x-checker-data": {
|
"x-checker-data": {
|
||||||
"type": "anitya",
|
"type": "anitya",
|
||||||
"project-id": 236236,
|
"project-id": 8763,
|
||||||
"stable-only": true,
|
"stable-only": true,
|
||||||
"url-template": "https://github.com/danvratil/qcoro/archive/refs/tags/v$version.tar.gz"
|
"url-template": "https://download.kde.org/stable/release-service/$version/src/kunifiedpush-$version.tar.xz"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -158,14 +178,15 @@
|
|||||||
{
|
{
|
||||||
"name": "neochat",
|
"name": "neochat",
|
||||||
"buildsystem": "cmake-ninja",
|
"buildsystem": "cmake-ninja",
|
||||||
|
"config-opts": [
|
||||||
|
"-DBUILD_TESTING=OFF",
|
||||||
|
"-DNEOCHAT_FLATPAK=ON"
|
||||||
|
],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "dir",
|
"type": "dir",
|
||||||
"path": "."
|
"path": "."
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"config-opts": [
|
|
||||||
"-DNEOCHAT_FLATPAK=ON"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,3 +12,4 @@ kate.project.ctags.*
|
|||||||
.idea/
|
.idea/
|
||||||
cmake-build-*
|
cmake-build-*
|
||||||
src/res.generated.qrc
|
src/res.generated.qrc
|
||||||
|
.qmlls.ini
|
||||||
|
|||||||
@@ -5,11 +5,17 @@ include:
|
|||||||
- project: sysadmin/ci-utilities
|
- project: sysadmin/ci-utilities
|
||||||
file:
|
file:
|
||||||
- /gitlab-templates/reuse-lint.yml
|
- /gitlab-templates/reuse-lint.yml
|
||||||
|
- /gitlab-templates/json-validation.yml
|
||||||
|
- /gitlab-templates/xml-lint.yml
|
||||||
|
- /gitlab-templates/yaml-lint.yml
|
||||||
- /gitlab-templates/android-qt6.yml
|
- /gitlab-templates/android-qt6.yml
|
||||||
- /gitlab-templates/linux-qt6.yml
|
- /gitlab-templates/linux-qt6.yml
|
||||||
|
- /gitlab-templates/linux-qt6-next.yml
|
||||||
- /gitlab-templates/windows-qt6.yml
|
- /gitlab-templates/windows-qt6.yml
|
||||||
- /gitlab-templates/freebsd-qt6.yml
|
- /gitlab-templates/freebsd-qt6.yml
|
||||||
- /gitlab-templates/flatpak.yml
|
- /gitlab-templates/flatpak.yml
|
||||||
|
- /gitlab-templates/snap-snapcraft-lxd.yml
|
||||||
- /gitlab-templates/craft-android-qt6-apks.yml
|
- /gitlab-templates/craft-android-qt6-apks.yml
|
||||||
- /gitlab-templates/craft-appimage-qt6.yml
|
- /gitlab-templates/craft-appimage-qt6.yml
|
||||||
- /gitlab-templates/craft-windows-x86-64-qt6.yml
|
- /gitlab-templates/craft-windows-x86-64-qt6.yml
|
||||||
|
- /gitlab-templates/craft-windows-appx-qt6.yml
|
||||||
|
|||||||
70
.kde-ci.yml
70
.kde-ci.yml
@@ -2,40 +2,44 @@
|
|||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
Dependencies:
|
Dependencies:
|
||||||
- 'on': ['Linux', 'Android', 'FreeBSD', 'Windows']
|
- 'on': ['Linux', 'Android', 'FreeBSD', 'Windows']
|
||||||
'require':
|
'require':
|
||||||
'frameworks/extra-cmake-modules': '@latest-kf6'
|
'frameworks/extra-cmake-modules': '@latest-kf6'
|
||||||
'frameworks/kcoreaddons': '@latest-kf6'
|
'frameworks/kcoreaddons': '@latest-kf6'
|
||||||
'frameworks/kirigami': '@latest-kf6'
|
'frameworks/kirigami': '@latest-kf6'
|
||||||
'frameworks/ki18n': '@latest-kf6'
|
'frameworks/ki18n': '@latest-kf6'
|
||||||
'frameworks/kconfig': '@latest-kf6'
|
'frameworks/kconfig': '@latest-kf6'
|
||||||
'frameworks/syntax-highlighting': '@latest-kf6'
|
'frameworks/syntax-highlighting': '@latest-kf6'
|
||||||
'frameworks/kitemmodels': '@latest-kf6'
|
'frameworks/kitemmodels': '@latest-kf6'
|
||||||
'frameworks/kquickcharts': '@latest-kf6'
|
'frameworks/kquickcharts': '@latest-kf6'
|
||||||
'frameworks/knotifications': '@latest-kf6'
|
'frameworks/knotifications': '@latest-kf6'
|
||||||
'frameworks/kcolorscheme': '@latest-kf6'
|
'frameworks/kcolorscheme': '@latest-kf6'
|
||||||
'libraries/kquickimageeditor': '@latest-kf6'
|
'frameworks/kiconthemes': '@latest-kf6'
|
||||||
'frameworks/sonnet': '@latest-kf6'
|
'libraries/kquickimageeditor': '@latest-kf6'
|
||||||
'frameworks/prison': '@latest-kf6'
|
'frameworks/sonnet': '@latest-kf6'
|
||||||
'libraries/kirigami-addons': '@latest-kf6'
|
'frameworks/prison': '@latest-kf6'
|
||||||
'third-party/libquotient': '@latest'
|
'libraries/kirigami-addons': '@latest-kf6'
|
||||||
'third-party/qtkeychain': '@latest'
|
'third-party/libquotient': '@latest'
|
||||||
'third-party/cmark': '@latest'
|
'third-party/qtkeychain': '@latest'
|
||||||
'third-party/qcoro': '@latest'
|
'third-party/cmark': '@latest'
|
||||||
- 'on': ['Windows', 'Linux', 'FreeBSD']
|
'third-party/qcoro': '@latest'
|
||||||
'require':
|
- 'on': ['Windows', 'Linux', 'FreeBSD']
|
||||||
'frameworks/qqc2-desktop-style': '@latest-kf6'
|
'require':
|
||||||
'frameworks/kio': '@latest-kf6'
|
'frameworks/qqc2-desktop-style': '@latest-kf6'
|
||||||
'frameworks/kwindowsystem': '@latest-kf6'
|
'frameworks/kio': '@latest-kf6'
|
||||||
'frameworks/kstatusnotifieritem': '@latest-kf6'
|
'frameworks/kwindowsystem': '@latest-kf6'
|
||||||
- 'on': ['Linux', 'FreeBSD']
|
'frameworks/kstatusnotifieritem': '@latest-kf6'
|
||||||
'require':
|
'frameworks/kcrash': '@latest-kf6'
|
||||||
'frameworks/kdbusaddons': '@latest-kf6'
|
- 'on': ['Linux', 'FreeBSD']
|
||||||
|
'require':
|
||||||
|
'frameworks/kdbusaddons': '@latest-kf6'
|
||||||
|
'frameworks/purpose': '@latest-kf6'
|
||||||
|
'libraries/kunifiedpush': '@latest-kf6'
|
||||||
|
|
||||||
- 'on': ['Linux']
|
- 'on': ['Linux']
|
||||||
'require':
|
'require':
|
||||||
'sdk/selenium-webdriver-at-spi': '@latest-kf6'
|
'sdk/selenium-webdriver-at-spi': '@latest-kf6'
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
per-test-timeout: 90
|
per-test-timeout: 90
|
||||||
require-passing-tests-on: [ '@all' ]
|
require-passing-tests-on: ['Linux', 'Android', 'FreeBSD', 'Windows']
|
||||||
|
|||||||
51
.reuse/dep5
51
.reuse/dep5
@@ -1,51 +0,0 @@
|
|||||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|
||||||
Upstream-Name: NeoChat
|
|
||||||
Upstream-Contact: Carl Schwan <carlschwan@kde.org>
|
|
||||||
|
|
||||||
Files: 128-logo.png icons/* logo.png org.kde.neochat.svg org.kde.neochat.tray.svg android/res/drawable/neochat.png
|
|
||||||
Copyright: 2020 Carson Black <uhhadd@gmail.com>
|
|
||||||
License: LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
|
||||||
|
|
||||||
Files: android/res/drawable/splash.xml
|
|
||||||
Copyright: 2020 Tobias Fella <tobias.fella@kde.org>
|
|
||||||
License: BSD-2-Clause
|
|
||||||
|
|
||||||
Files: .gitignore
|
|
||||||
Copyright: None
|
|
||||||
License: CC0-1.0
|
|
||||||
|
|
||||||
Files: .gitlab/issue_templates/bug.md
|
|
||||||
Copyright: 2021 Carl Schwan <carlschwan@kde.org>
|
|
||||||
License: CC0-1.0
|
|
||||||
|
|
||||||
Files: src/res.qrc src/res_android.qrc src/res_desktop.qrc
|
|
||||||
Copyright: None
|
|
||||||
License: CC0-1.0
|
|
||||||
|
|
||||||
Files: cmake/Flatpak/99-noto-mono-color-emoji.conf
|
|
||||||
Copyright: 2021 Carl Schwan <carlschwan@kde.org>
|
|
||||||
License: BSD-2-Clause
|
|
||||||
|
|
||||||
Files: src/neochatconfig.kcfg
|
|
||||||
Copyright: 2020-2021 Carl Schwan <carlschwan@kde.org>, Tobias Fella <tobias.fella@kde.org>
|
|
||||||
License: BSD-2-Clause
|
|
||||||
|
|
||||||
Files: src/neochat.notifyrc
|
|
||||||
Copyright: 2020 Tobias Fella <tobias.fella@kde.org>
|
|
||||||
License: BSD-2-Clause
|
|
||||||
|
|
||||||
Files: src/qml/confetti.png src/qml/glowdot.png
|
|
||||||
Copyright: 2021 Alexey Andreyev <aa13q@ya.ru>
|
|
||||||
License: CC0-1.0
|
|
||||||
|
|
||||||
Files: .flatpak-manifest.json
|
|
||||||
Copyright: 2020-2022 Tobias Fella <tobias.fella@kde.org>
|
|
||||||
License: BSD-2-Clause
|
|
||||||
|
|
||||||
Files: autotests/data/*
|
|
||||||
Copyright: none
|
|
||||||
License: CC0-1.0
|
|
||||||
|
|
||||||
Files: appiumtests/data/*
|
|
||||||
Copyright: 2023 Tobias Fella <tobias.fella@kde.org>
|
|
||||||
License: CC0-1.0
|
|
||||||
@@ -7,14 +7,14 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
# KDE Applications version, managed by release script.
|
# KDE Applications version, managed by release script.
|
||||||
set(RELEASE_SERVICE_VERSION_MAJOR "24")
|
set(RELEASE_SERVICE_VERSION_MAJOR "25")
|
||||||
set(RELEASE_SERVICE_VERSION_MINOR "02")
|
set(RELEASE_SERVICE_VERSION_MINOR "11")
|
||||||
set(RELEASE_SERVICE_VERSION_MICRO "2")
|
set(RELEASE_SERVICE_VERSION_MICRO "70")
|
||||||
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
||||||
|
|
||||||
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
|
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
|
||||||
|
|
||||||
set(KF_MIN_VERSION "5.240.0")
|
set(KF_MIN_VERSION "6.16")
|
||||||
set(QT_MIN_VERSION "6.5")
|
set(QT_MIN_VERSION "6.5")
|
||||||
|
|
||||||
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
|
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
|
||||||
@@ -24,7 +24,7 @@ set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
|||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
set(KDE_COMPILERSETTINGS_LEVEL 5.105)
|
set(KDE_COMPILERSETTINGS_LEVEL 6.0)
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
include(ECMSetupVersion)
|
include(ECMSetupVersion)
|
||||||
@@ -38,6 +38,9 @@ include(KDEGitCommitHooks)
|
|||||||
include(ECMCheckOutboundLicense)
|
include(ECMCheckOutboundLicense)
|
||||||
include(ECMQtDeclareLoggingCategory)
|
include(ECMQtDeclareLoggingCategory)
|
||||||
include(ECMAddAndroidApk)
|
include(ECMAddAndroidApk)
|
||||||
|
include(ECMQmlModule)
|
||||||
|
include(GenerateExportHeader)
|
||||||
|
include(ECMGenerateHeaders)
|
||||||
if (NOT ANDROID)
|
if (NOT ANDROID)
|
||||||
include(KDEClangFormat)
|
include(KDEClangFormat)
|
||||||
endif()
|
endif()
|
||||||
@@ -53,12 +56,17 @@ ecm_setup_version(${PROJECT_VERSION}
|
|||||||
VERSION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/neochat-version.h
|
VERSION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/neochat-version.h
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(Qt6 ${QT_MIN_VERSION} NO_MODULE COMPONENTS Core Quick Gui QuickControls2 Multimedia Svg WebView)
|
find_package(Qt6 ${QT_MIN_VERSION} NO_MODULE COMPONENTS Core Quick Gui QuickControls2 Multimedia Svg TextToSpeech WebView)
|
||||||
set_package_properties(Qt6 PROPERTIES
|
set_package_properties(Qt6 PROPERTIES
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
PURPOSE "Basic application components"
|
PURPOSE "Basic application components"
|
||||||
)
|
)
|
||||||
find_package(KF6 ${KF_MIN_VERSION} COMPONENTS Kirigami I18n Notifications Config CoreAddons Sonnet ItemModels ColorScheme)
|
|
||||||
|
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 IconThemes ColorScheme)
|
||||||
set_package_properties(KF6 PROPERTIES
|
set_package_properties(KF6 PROPERTIES
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
PURPOSE "Basic application components"
|
PURPOSE "Basic application components"
|
||||||
@@ -67,7 +75,11 @@ set_package_properties(KF6Kirigami PROPERTIES
|
|||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
PURPOSE "Kirigami application UI framework"
|
PURPOSE "Kirigami application UI framework"
|
||||||
)
|
)
|
||||||
find_package(KF6KirigamiAddons 0.7.2 REQUIRED)
|
find_package(KF6KirigamiAddons 1.6.0 REQUIRED)
|
||||||
|
|
||||||
|
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT NEOCHAT_FLATPAK AND NOT NEOCHAT_APPIMAGE)
|
||||||
|
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS Purpose)
|
||||||
|
endif ()
|
||||||
|
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
find_package(OpenSSL)
|
find_package(OpenSSL)
|
||||||
@@ -77,7 +89,8 @@ if(ANDROID)
|
|||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
find_package(Qt6 ${QT_MIN_VERSION} COMPONENTS Widgets)
|
find_package(Qt6 ${QT_MIN_VERSION} COMPONENTS Widgets)
|
||||||
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle KIO WindowSystem StatusNotifierItem)
|
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle KIO WindowSystem StatusNotifierItem Crash)
|
||||||
|
find_package(KF6SyntaxHighlighting ${KF_MIN_VERSION} REQUIRED)
|
||||||
set_package_properties(KF6QQC2DesktopStyle PROPERTIES
|
set_package_properties(KF6QQC2DesktopStyle PROPERTIES
|
||||||
TYPE RUNTIME
|
TYPE RUNTIME
|
||||||
)
|
)
|
||||||
@@ -90,11 +103,11 @@ else()
|
|||||||
)
|
)
|
||||||
endif()
|
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)
|
find_package(KF6DBusAddons ${KF_MIN_VERSION} REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(QuotientQt6 0.7)
|
find_package(QuotientQt6 0.9.1)
|
||||||
set_package_properties(QuotientQt6 PROPERTIES
|
set_package_properties(QuotientQt6 PROPERTIES
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
DESCRIPTION "Qt wrapper around Matrix API"
|
DESCRIPTION "Qt wrapper around Matrix API"
|
||||||
@@ -102,11 +115,6 @@ set_package_properties(QuotientQt6 PROPERTIES
|
|||||||
PURPOSE "Talk with matrix server"
|
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)
|
find_package(cmark)
|
||||||
set_package_properties(cmark PROPERTIES
|
set_package_properties(cmark PROPERTIES
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
@@ -139,16 +147,24 @@ set_package_properties(KF6DocTools PROPERTIES DESCRIPTION
|
|||||||
TYPE OPTIONAL
|
TYPE OPTIONAL
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(KUnifiedPush QUIET)
|
option(WITH_UNIFIEDPUSH "Build with KUnifiedPush support" ON)
|
||||||
set_package_properties(KUnifiedPush PROPERTIES
|
|
||||||
TYPE OPTIONAL
|
if (ANDROID OR APPLE OR WIN32 OR HAIKU)
|
||||||
PURPOSE "Push notification support"
|
set(WITH_UNIFIEDPUSH OFF)
|
||||||
URL "https://invent.kde.org/libraries/kunifiedpush"
|
endif()
|
||||||
)
|
|
||||||
|
if (WITH_UNIFIEDPUSH)
|
||||||
|
find_package(KUnifiedPush)
|
||||||
|
set_package_properties(KUnifiedPush PROPERTIES
|
||||||
|
TYPE REQUIRED
|
||||||
|
PURPOSE "Push notification support"
|
||||||
|
URL "https://invent.kde.org/libraries/kunifiedpush"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
find_package(Sqlite3)
|
find_package(Sqlite3)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/android/version.gradle.in ${CMAKE_BINARY_DIR}/version.gradle)
|
set(BUILD_TESTING FALSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
ki18n_install(po)
|
ki18n_install(po)
|
||||||
@@ -163,9 +179,12 @@ add_definitions(-DQT_NO_FOREACH)
|
|||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
if (BUILD_TESTING)
|
if (BUILD_TESTING)
|
||||||
find_package(Qt6 ${QT_MIN_VERSION} NO_MODULE COMPONENTS Test)
|
find_package(Qt6 ${QT_MIN_VERSION} NO_MODULE COMPONENTS Test HttpServer)
|
||||||
add_subdirectory(autotests)
|
add_subdirectory(autotests)
|
||||||
add_subdirectory(appiumtests)
|
# add_subdirectory(appiumtests)
|
||||||
|
if (NOT ANDROID)
|
||||||
|
add_subdirectory(memorytests)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(KF6DocTools_FOUND)
|
if(KF6DocTools_FOUND)
|
||||||
@@ -173,7 +192,7 @@ if(KF6DocTools_FOUND)
|
|||||||
add_subdirectory(doc)
|
add_subdirectory(doc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||||
|
|
||||||
if (NOT ANDROID)
|
if (NOT ANDROID)
|
||||||
file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES src/*.cpp src/*.h)
|
file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES src/*.cpp src/*.h)
|
||||||
|
|||||||
50
README.md
50
README.md
@@ -1,6 +1,6 @@
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carlschwan@kde.org>
|
SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carlschwan@kde.org>
|
||||||
SPDX-FileCopyrightText: 2020-2021 Tobias Fella <tobias.fella@kde.org>
|
SPDX-FileCopyrightText: 2020-2024 Tobias Fella <tobias.fella@kde.org>
|
||||||
SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
|
SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
|
||||||
SPDX-License-Identifier: CC0-1.0
|
SPDX-License-Identifier: CC0-1.0
|
||||||
-->
|
-->
|
||||||
@@ -11,24 +11,23 @@ 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://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://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
|
## Introduction
|
||||||
|
|
||||||
NeoChat is a client for [Matrix](https://matrix.org), the decentralized communication protocol for instant
|
NeoChat is a client for [Matrix](https://matrix.org), the decentralized communication protocol for instant
|
||||||
messaging. It is a fork of Spectral, using KDE frameworks, most notably [Kirigami](https://invent.kde.org/frameworks/kirigami)
|
messaging.
|
||||||
to provide a convergent experience across multiple platforms.
|
|
||||||
|
|
||||||
NeoChat also make use of other KDE Frameworks as well as [libQuotient](https://github.com/quotient-im/libQuotient), a
|
NeoChat is based on KDE frameworks and as [libQuotient](https://github.com/quotient-im/libQuotient), a
|
||||||
Qt-based SDK for the [Matrix Protocol](https://spec.matrix.org/).
|
Qt-based SDK for the [Matrix Protocol](https://spec.matrix.org/).
|
||||||
|
|
||||||

|

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

|

|
||||||
|
|
||||||
@@ -100,9 +86,9 @@ The best place to reach the maintainers is on the KDE Matrix instance in the Neo
|
|||||||
|
|
||||||
## Acknowledgement
|
## Acknowledgement
|
||||||
|
|
||||||
This program utilizes [libQuotient](https://github.com/quotient-im/libQuotient/) as its Matrix SDK.
|
NeoChat utilizes [libQuotient](https://github.com/quotient-im/libQuotient/) as its Matrix SDK.
|
||||||
|
|
||||||
This program is a fork of [Spectral](https://gitlab.com/spectral-im/spectral/).
|
NeoChat is a fork of [Spectral](https://gitlab.com/spectral-im/spectral/).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
96
REUSE.toml
Normal file
96
REUSE.toml
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# SPDX-FileCopyrightText: none
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
version = 1
|
||||||
|
SPDX-PackageName = "NeoChat"
|
||||||
|
SPDX-PackageSupplier = "Carl Schwan <carlschwan@kde.org>"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = ["128-logo.png", "icons/**", "logo.png", "org.kde.neochat.svg", "org.kde.neochat.tray.svg", "android/res/drawable/neochat.png", "android/neochat-playstore.png"]
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2020 Carson Black <uhhadd@gmail.com>"
|
||||||
|
SPDX-License-Identifier = "LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "android/res/drawable/splash.xml"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2020 Tobias Fella <tobias.fella@kde.org>"
|
||||||
|
SPDX-License-Identifier = "BSD-2-Clause"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = ".gitignore"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "None"
|
||||||
|
SPDX-License-Identifier = "CC0-1.0"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = ".gitlab/issue_templates/bug.md"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2021 Carl Schwan <carlschwan@kde.org>"
|
||||||
|
SPDX-License-Identifier = "CC0-1.0"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = ["src/res.qrc", "src/res_android.qrc", "src/res_desktop.qrc"]
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "None"
|
||||||
|
SPDX-License-Identifier = "CC0-1.0"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "cmake/Flatpak/99-noto-mono-color-emoji.conf"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2021 Carl Schwan <carlschwan@kde.org>"
|
||||||
|
SPDX-License-Identifier = "BSD-2-Clause"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "src/app/neochatconfig.kcfg"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2020-2021 Carl Schwan <carlschwan@kde.org>, Tobias Fella <tobias.fella@kde.org>"
|
||||||
|
SPDX-License-Identifier = "BSD-2-Clause"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "src/app/neochat.notifyrc"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2020 Tobias Fella <tobias.fella@kde.org>"
|
||||||
|
SPDX-License-Identifier = "BSD-2-Clause"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = ["src/qml/confetti.png", "src/qml/glowdot.png"]
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2021 Alexey Andreyev <aa13q@ya.ru>"
|
||||||
|
SPDX-License-Identifier = "CC0-1.0"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = ".flatpak-manifest.json"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2020-2022 Tobias Fella <tobias.fella@kde.org>"
|
||||||
|
SPDX-License-Identifier = "BSD-2-Clause"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "autotests/data/**"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "none"
|
||||||
|
SPDX-License-Identifier = "CC0-1.0"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "appiumtests/data/**"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2023 Tobias Fella <tobias.fella@kde.org>"
|
||||||
|
SPDX-License-Identifier = "CC0-1.0"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "src/purpose/purposeplugin.json"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2023 Tobias Fella <tobias.fella@kde.org>"
|
||||||
|
SPDX-License-Identifier = "BSD-2-Clause"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "memorytests/memtest-sync.json"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2024 James Graham <james.h.graham@protonmail.com>"
|
||||||
|
SPDX-License-Identifier = "BSD-2-Clause"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = ".contextProperties.ini"
|
||||||
|
precedence = "aggregate"
|
||||||
|
SPDX-FileCopyrightText = "2025 Tobias Fella <tobias.fella@kde.org>"
|
||||||
|
SPDX-License-Identifier = "BSD-2-Clause"
|
||||||
@@ -55,5 +55,6 @@
|
|||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <!-- for Android >= 33 -->
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.4.1'
|
classpath 'com.android.tools.build:gradle:8.6.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,8 +23,7 @@ repositories {
|
|||||||
|
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply from: '../version.gradle'
|
apply from: '../ecm-version.gradle'
|
||||||
def timestamp = (int)(new Date().getTime()/1000)
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
||||||
@@ -79,9 +78,9 @@ android {
|
|||||||
targetSdkVersion qtTargetSdkVersion
|
targetSdkVersion qtTargetSdkVersion
|
||||||
applicationId "org.kde.neochat"
|
applicationId "org.kde.neochat"
|
||||||
namespace "org.kde.neochat"
|
namespace "org.kde.neochat"
|
||||||
versionCode timestamp
|
versionCode ecmVersionCode
|
||||||
versionName projectVersionFull
|
versionName ecmVersionName
|
||||||
manifestPlaceholders = [versionName: projectVersionFull, versionCode: timestamp]
|
manifestPlaceholders = [versionName: ecmVersionName, versionCode: ecmVersionCode]
|
||||||
}
|
}
|
||||||
|
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
|
|||||||
BIN
android/neochat-playstore.png
Normal file
BIN
android/neochat-playstore.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
@@ -1,6 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
|
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
ext {
|
|
||||||
projectVersionFull = "@NEOCHAT_VERSION@"
|
|
||||||
}
|
|
||||||
56
appiumtests/createroomtest.py
Executable file
56
appiumtests/createroomtest.py
Executable file
@@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
# SPDX-FileCopyrightText: 2024 Tobias Fella <tobias.fella@kde.org>
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
import time
|
||||||
|
|
||||||
|
from appium import webdriver
|
||||||
|
from appium.options.common.base import AppiumOptions
|
||||||
|
from appium.webdriver.common.appiumby import AppiumBy
|
||||||
|
|
||||||
|
|
||||||
|
class CreateRoomTest(unittest.TestCase):
|
||||||
|
|
||||||
|
mockServerProcess: subprocess.Popen
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.mockServerProcess = subprocess.Popen([sys.executable, os.path.join(os.path.dirname(__file__), "login-server.py")])
|
||||||
|
options = AppiumOptions()
|
||||||
|
options.set_capability("app", "neochat --ignore-ssl-errors --test")
|
||||||
|
cls.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', options=options)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
if not self._outcome.result.wasSuccessful():
|
||||||
|
self.driver.get_screenshot_as_file("failed_test_shot_{}.png".format(self.id()))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(self):
|
||||||
|
self.mockServerProcess.terminate()
|
||||||
|
self.driver.quit()
|
||||||
|
|
||||||
|
def test_create_room(self):
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="@user:localhost:1234").click()
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Show Menu").click()
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Create a Room").click()
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Name:").send_keys("Super awesome room name")#
|
||||||
|
time.sleep(0.1) # without this, the second half of the text is sent to the topic field?!
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Topic:").send_keys("There are not enough raccoons here")
|
||||||
|
time.sleep(0.1)
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Create Room").click()
|
||||||
|
time.sleep(0.1)
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Super awesome room name").click()
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Show Room Information").click()
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="There are not enough raccoons here")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
78
appiumtests/data/sync_response_new_room.json
Normal file
78
appiumtests/data/sync_response_new_room.json
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"next_batch": "batch1234",
|
||||||
|
"rooms": {
|
||||||
|
"join": {
|
||||||
|
"!newroom123321:localhost:1234": {
|
||||||
|
"state": {
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"type": "m.room.member",
|
||||||
|
"state_key": "@user:localhost:1234",
|
||||||
|
"sender": "@user:localhost:1234",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"event_id": "$event_id_1234_0:localhost:1234",
|
||||||
|
"room_id": "!newroom123321:localhost:1234",
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "",
|
||||||
|
"displayname": "A Display Name",
|
||||||
|
"membership": "join",
|
||||||
|
"reason": "Nothing"
|
||||||
|
},
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"state_key": "",
|
||||||
|
"sender": "@user:localhost:1234",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"event_id": "$event_id_1234_1:localhost:1234",
|
||||||
|
"room_id": "!newroom123321:localhost:1234",
|
||||||
|
"content": {
|
||||||
|
"name": "Super awesome room name"
|
||||||
|
},
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "m.room.topic",
|
||||||
|
"state_key": "",
|
||||||
|
"sender": "@user:localhost:1234",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"event_id": "$event_id_1234_2:localhost:1234",
|
||||||
|
"room_id": "!newroom123321:localhost:1234",
|
||||||
|
"content": {
|
||||||
|
"topic": "There are not enough raccoons here"
|
||||||
|
},
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"timeline": {
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"type": "m.room.message",
|
||||||
|
"sender": "@user:localhost:1234",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"event_id": "$event_id_1234_1:localhost:1234",
|
||||||
|
"room_id": "!newroom123321:localhost:1234",
|
||||||
|
"content": {
|
||||||
|
"body": "This is a message",
|
||||||
|
"format": "org.matrix.custom.html",
|
||||||
|
"formatted_body": "<a href=\"https://matrix.to/#/@user:localhost:1234\">User</a>:",
|
||||||
|
"msgtype": "m.text"
|
||||||
|
},
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,26 @@
|
|||||||
"!room_id_1234:localhost:1234": {
|
"!room_id_1234:localhost:1234": {
|
||||||
"state": {
|
"state": {
|
||||||
"events": [
|
"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",
|
"type": "m.room.member",
|
||||||
"state_key": "@user:localhost:1234",
|
"state_key": "@user:localhost:1234",
|
||||||
@@ -26,6 +46,26 @@
|
|||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"events": [
|
"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",
|
"type": "m.room.message",
|
||||||
"sender": "@user:localhost:1234",
|
"sender": "@user:localhost:1234",
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ from flask import Flask, request, abort
|
|||||||
import os
|
import os
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
next_sync_payload = ""
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_matrix/client/v3/login", methods=["GET"])
|
@app.route("/_matrix/client/v3/login", methods=["GET"])
|
||||||
def login_get():
|
def login_get():
|
||||||
@@ -42,8 +44,13 @@ def load_json(name):
|
|||||||
|
|
||||||
@app.route("/_matrix/client/r0/sync")
|
@app.route("/_matrix/client/r0/sync")
|
||||||
def sync():
|
def sync():
|
||||||
|
global next_sync_payload
|
||||||
result = load_json("sync_response_no_rooms") if ("login" in request.headers.get("Authorization")) else load_json("sync_response_rooms")
|
result = dict()
|
||||||
|
if len(next_sync_payload) > 0:
|
||||||
|
result = load_json(next_sync_payload)
|
||||||
|
next_sync_payload = ""
|
||||||
|
else:
|
||||||
|
result = load_json("sync_response_no_rooms") if ("login" in request.headers.get("Authorization")) else load_json("sync_response_rooms")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@app.route("/.well-known/matrix/client")
|
@app.route("/.well-known/matrix/client")
|
||||||
@@ -65,6 +72,27 @@ def upload_keys():
|
|||||||
reply = dict()
|
reply = dict()
|
||||||
return reply
|
return reply
|
||||||
|
|
||||||
|
@app.route("/_matrix/client/v3/createRoom", methods=["POST"])
|
||||||
|
def create_room():
|
||||||
|
global next_sync_payload
|
||||||
|
data = request.get_json()
|
||||||
|
if data["name"] != "Super awesome room name" or data["topic"] != "There are not enough raccoons here":
|
||||||
|
return dict(), 400
|
||||||
|
response = dict()
|
||||||
|
response["room_id"] = "!newroom123321:localhost:1234"
|
||||||
|
next_sync_payload = "sync_response_new_room"
|
||||||
|
return response
|
||||||
|
|
||||||
|
@app.route("/_matrix/client/v3/publicRooms", methods=["POST"])
|
||||||
|
def public_rooms():
|
||||||
|
if request.get_json()["filter"]["generic_search_term"] == "forbidden":
|
||||||
|
data = dict()
|
||||||
|
data["errcode"] = "M_FORBIDDEN"
|
||||||
|
data["error"] = "You are not allowed to search for this. Go to https://wikipedia.org for more information"
|
||||||
|
return data, 403
|
||||||
|
return dict()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(ssl_context='adhoc', port=1234)
|
app.run(ssl_context='adhoc', port=1234)
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ class OpenUserDetailsTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_open_sheet(self):
|
def test_open_sheet(self):
|
||||||
self.driver.find_element(by=AppiumBy.NAME, value="@user:localhost:1234").click()
|
self.driver.find_element(by=AppiumBy.NAME, value="@user:localhost:1234").click()
|
||||||
|
try:
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Expand Normal").click()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
self.driver.find_element(by=AppiumBy.NAME, value="Empty room (!room_id_1234:localhost:1234)").click()
|
self.driver.find_element(by=AppiumBy.NAME, value="Empty room (!room_id_1234:localhost:1234)").click()
|
||||||
self.driver.find_element(by=AppiumBy.NAME, value="A Display Name").click()
|
self.driver.find_element(by=AppiumBy.NAME, value="A Display Name").click()
|
||||||
self.driver.find_element(by=AppiumBy.NAME, value="Account Details")
|
self.driver.find_element(by=AppiumBy.NAME, value="Account Details")
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
|
add_library(neochat_server STATIC server.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(neochat_server PUBLIC Qt::HttpServer QuotientQt6)
|
||||||
|
|
||||||
add_definitions(-DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" )
|
add_definitions(-DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" )
|
||||||
|
|
||||||
ecm_add_test(
|
ecm_add_test(
|
||||||
@@ -48,15 +52,9 @@ ecm_add_test(
|
|||||||
)
|
)
|
||||||
|
|
||||||
ecm_add_test(
|
ecm_add_test(
|
||||||
messageeventmodeltest.cpp
|
timelinemessagemodeltest.cpp
|
||||||
LINK_LIBRARIES neochat Qt::Test
|
LINK_LIBRARIES neochat Qt::Test
|
||||||
TEST_NAME messageeventmodeltest
|
TEST_NAME timelinemessagemodeltest
|
||||||
)
|
|
||||||
|
|
||||||
ecm_add_test(
|
|
||||||
actionshandlertest.cpp
|
|
||||||
LINK_LIBRARIES neochat Qt::Test
|
|
||||||
TEST_NAME actionshandlertest
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ecm_add_test(
|
ecm_add_test(
|
||||||
@@ -82,3 +80,21 @@ ecm_add_test(
|
|||||||
LINK_LIBRARIES neochat Qt::Test
|
LINK_LIBRARIES neochat Qt::Test
|
||||||
TEST_NAME linkpreviewertest
|
TEST_NAME linkpreviewertest
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ecm_add_test(
|
||||||
|
messagecontentmodeltest.cpp
|
||||||
|
LINK_LIBRARIES neochat Qt::Test
|
||||||
|
TEST_NAME messagecontentmodeltest
|
||||||
|
)
|
||||||
|
|
||||||
|
ecm_add_test(
|
||||||
|
actionstest.cpp
|
||||||
|
LINK_LIBRARIES neochat Qt::Test neochat_server
|
||||||
|
TEST_NAME actionstest
|
||||||
|
)
|
||||||
|
|
||||||
|
ecm_add_test(
|
||||||
|
roommanagertest.cpp
|
||||||
|
LINK_LIBRARIES neochat Qt::Test neochat_server
|
||||||
|
TEST_NAME roommanagertest
|
||||||
|
)
|
||||||
|
|||||||
@@ -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"
|
|
||||||
151
autotests/actionstest.cpp
Normal file
151
autotests/actionstest.cpp
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Tobias Fella <tobias.fella@kde.org>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QTest>
|
||||||
|
#include <QSignalSpy>
|
||||||
|
#include <QVariantList>
|
||||||
|
|
||||||
|
#include "accountmanager.h"
|
||||||
|
#include "chatbarcache.h"
|
||||||
|
#include "models/actionsmodel.h"
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
#include "testutils.h"
|
||||||
|
|
||||||
|
using namespace Quotient;
|
||||||
|
|
||||||
|
//TODO: rainbow, rainbowme, plain, spoiler, me, join, knock, j, part, leave, nick, roomnick, myroomnick, ignore, unignore, react, ban, unban, kick
|
||||||
|
|
||||||
|
class ActionsTest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
Connection *connection = nullptr;
|
||||||
|
NeoChatRoom *room = nullptr;
|
||||||
|
|
||||||
|
void expectMessage(const QString &actionName, const QString &args, MessageType::Type type, const QString &message);
|
||||||
|
|
||||||
|
Server server;
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void initTestCase();
|
||||||
|
void testActions();
|
||||||
|
void testActions_data();
|
||||||
|
void testInvite();
|
||||||
|
};
|
||||||
|
|
||||||
|
void ActionsTest::initTestCase()
|
||||||
|
{
|
||||||
|
Connection::setRoomType<NeoChatRoom>();
|
||||||
|
server.start();
|
||||||
|
KLocalizedString::setApplicationDomain(QByteArrayLiteral("neochat"));
|
||||||
|
auto accountManager = new AccountManager(true);
|
||||||
|
QSignalSpy spy(accountManager, &AccountManager::connectionAdded);
|
||||||
|
connection = accountManager->accounts()->front();
|
||||||
|
auto roomId = server.createRoom(u"@user:localhost:1234"_s);
|
||||||
|
server.inviteUser(roomId, u"@invited:example.com"_s);
|
||||||
|
server.banUser(roomId, u"@banned:example.com"_s);
|
||||||
|
server.joinUser(roomId, u"@example:example.com"_s);
|
||||||
|
|
||||||
|
QSignalSpy syncSpy(connection, &Connection::syncDone);
|
||||||
|
// We need to wait for two syncs, as the next one won't have the changes yet
|
||||||
|
QVERIFY(syncSpy.wait());
|
||||||
|
QVERIFY(syncSpy.wait());
|
||||||
|
room = dynamic_cast<NeoChatRoom *>(connection->room(roomId));
|
||||||
|
QVERIFY(room);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionsTest::testActions_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("command");
|
||||||
|
QTest::addColumn<std::optional<QString>>("resultText");
|
||||||
|
QTest::addColumn<std::optional<Quotient::RoomMessageEvent::MsgType>>("type");
|
||||||
|
|
||||||
|
QTest::newRow("shrug") << u"/shrug Hello"_s << std::make_optional(u"¯\\\\_(ツ)_/¯ Hello"_s)
|
||||||
|
<< std::make_optional(Quotient::RoomMessageEvent::MsgType::Text);
|
||||||
|
QTest::newRow("lenny") << u"/lenny Hello"_s << std::make_optional(u"( ͡° ͜ʖ ͡°) Hello"_s) << std::make_optional(Quotient::RoomMessageEvent::MsgType::Text);
|
||||||
|
QTest::newRow("tableflip") << u"/tableflip Hello"_s << std::make_optional(u"(╯°□°)╯︵ ┻━┻ Hello"_s)
|
||||||
|
<< std::make_optional(Quotient::RoomMessageEvent::MsgType::Text);
|
||||||
|
QTest::newRow("unflip") << u"/unflip Hello"_s << std::make_optional(u"┬──┬ ノ( ゜-゜ノ) Hello"_s)
|
||||||
|
<< std::make_optional(Quotient::RoomMessageEvent::MsgType::Text);
|
||||||
|
QTest::newRow("rainbow") << u"/rainbow Hello"_s << std::optional<QString>() << std::optional<Quotient::RoomMessageEvent::MsgType>();
|
||||||
|
QTest::newRow("rainbowme") << u"/rainbowme Hello"_s << std::optional<QString>() << std::optional<Quotient::RoomMessageEvent::MsgType>();
|
||||||
|
QTest::newRow("plain") << u"/plain <b>Hello</b>"_s << std::optional<QString>() << std::optional<Quotient::RoomMessageEvent::MsgType>();
|
||||||
|
QTest::newRow("spoiler") << u"/spoiler Hello"_s << std::optional<QString>() << std::optional<Quotient::RoomMessageEvent::MsgType>();
|
||||||
|
QTest::newRow("me") << u"/me Hello"_s << std::make_optional(u"Hello"_s) << std::make_optional(Quotient::RoomMessageEvent::MsgType::Emote);
|
||||||
|
QTest::newRow("notice") << u"/notice Hello"_s << std::make_optional(u"Hello"_s) << std::make_optional(Quotient::RoomMessageEvent::MsgType::Notice);
|
||||||
|
QTest::newRow("message") << u"Hello"_s << std::make_optional(u"Hello"_s) << std::make_optional(Quotient::RoomMessageEvent::MsgType::Text);
|
||||||
|
QTest::newRow("invite") << u"/invite @foo:example.com"_s << std::optional<QString>() << std::optional<Quotient::RoomMessageEvent::MsgType>();
|
||||||
|
|
||||||
|
//TODO: join, knock, j, part, leave, nick, roomnick, myroomnick, ignore, unignore, react, ban, unban, kick
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionsTest::testActions()
|
||||||
|
{
|
||||||
|
QFETCH(QString, command);
|
||||||
|
QFETCH(std::optional<QString>, resultText);
|
||||||
|
QFETCH(std::optional<Quotient::RoomMessageEvent::MsgType>, type);
|
||||||
|
|
||||||
|
auto cache = new ChatBarCache();
|
||||||
|
cache->setText(command);
|
||||||
|
auto result = ActionsModel::handleAction(room, cache);
|
||||||
|
QCOMPARE(resultText, std::get<std::optional<QString>>(result));
|
||||||
|
QCOMPARE(type, std::get<std::optional<Quotient::RoomMessageEvent::MsgType>>(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ActionsModel::Action findAction(const QString &name)
|
||||||
|
{
|
||||||
|
for (const auto &action : ActionsModel::allActions()) {
|
||||||
|
if (action.prefix == name) {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionsTest::expectMessage(const QString &actionName, const QString &args, MessageType::Type type, const QString &message)
|
||||||
|
{
|
||||||
|
auto action = findAction(actionName);
|
||||||
|
QSignalSpy spy(room, &NeoChatRoom::showMessage);
|
||||||
|
auto result = action.handle(args, room, nullptr);
|
||||||
|
auto expected = QVariantList {type, message};
|
||||||
|
auto signal = spy.takeFirst();
|
||||||
|
QCOMPARE(signal, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionsTest::testInvite()
|
||||||
|
{
|
||||||
|
expectMessage(u"invite"_s, u"foo"_s, MessageType::Error, u"'foo' does not look like a matrix id."_s);
|
||||||
|
expectMessage(u"invite"_s, u"@invited:example.com"_s, MessageType::Information, u"@invited:example.com is already invited to this room."_s);
|
||||||
|
QCOMPARE(room->memberState(u"@invited:example.com"_s), Membership::Invite);
|
||||||
|
expectMessage(u"invite"_s, u"@banned:example.com"_s, MessageType::Information, u"@banned:example.com is banned from this room."_s);
|
||||||
|
QCOMPARE(room->memberState(u"@banned:example.com"_s), Membership::Ban);
|
||||||
|
expectMessage(u"invite"_s, connection->userId(), MessageType::Positive, u"You are already in this room."_s);
|
||||||
|
QCOMPARE(room->memberState(connection->userId()), Membership::Join);
|
||||||
|
expectMessage(u"invite"_s, u"@example:example.com"_s, MessageType::Information, u"@example:example.com is already in this room."_s);
|
||||||
|
QCOMPARE(room->memberState(u"@example:example.com"_s), Membership::Join);
|
||||||
|
|
||||||
|
QCOMPARE(room->memberState(u"@user:example.com"_s), Membership::Leave);
|
||||||
|
expectMessage(u"invite"_s, u"@user:example.com"_s, MessageType::Positive, u"@user:example.com was invited into this room."_s);
|
||||||
|
|
||||||
|
QSignalSpy spy(room, &NeoChatRoom::changed);
|
||||||
|
QVERIFY(spy.wait());
|
||||||
|
|
||||||
|
auto tries = 0;
|
||||||
|
|
||||||
|
while (room->memberState(u"@user:example.com"_s) != Membership::Invite) {
|
||||||
|
QVERIFY(spy.wait());
|
||||||
|
tries += 1;
|
||||||
|
if (tries > 3) {
|
||||||
|
QVERIFY(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QCOMPARE(room->memberState(u"@user:example.com"_s), Membership::Invite);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(ActionsTest)
|
||||||
|
#include "actionstest.moc"
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
|
#include <QSignalSpy>
|
||||||
|
#include <Quotient/roommember.h>
|
||||||
#include <Quotient/syncdata.h>
|
#include <Quotient/syncdata.h>
|
||||||
#include <qtestcase.h>
|
#include <qtestcase.h>
|
||||||
|
|
||||||
@@ -31,14 +33,15 @@ private Q_SLOTS:
|
|||||||
void noRoom();
|
void noRoom();
|
||||||
void badParent();
|
void badParent();
|
||||||
void reply();
|
void reply();
|
||||||
|
void replyMissingUser();
|
||||||
void edit();
|
void edit();
|
||||||
void attachment();
|
void attachment();
|
||||||
};
|
};
|
||||||
|
|
||||||
void ChatBarCacheTest::initTestCase()
|
void ChatBarCacheTest::initTestCase()
|
||||||
{
|
{
|
||||||
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
|
connection = Connection::makeMockConnection(u"@bob:kde.org"_s);
|
||||||
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-min-sync.json"));
|
room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, "test-min-sync.json"_L1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBarCacheTest::empty()
|
void ChatBarCacheTest::empty()
|
||||||
@@ -50,7 +53,7 @@ void ChatBarCacheTest::empty()
|
|||||||
QCOMPARE(chatBarCache->replyId(), QString());
|
QCOMPARE(chatBarCache->replyId(), QString());
|
||||||
QCOMPARE(chatBarCache->isEditing(), false);
|
QCOMPARE(chatBarCache->isEditing(), false);
|
||||||
QCOMPARE(chatBarCache->editId(), QString());
|
QCOMPARE(chatBarCache->editId(), QString());
|
||||||
QCOMPARE(chatBarCache->relationUser(), room->getUser(nullptr));
|
QCOMPARE(chatBarCache->relationAuthor(), room->member(QString()));
|
||||||
QCOMPARE(chatBarCache->relationMessage(), QString());
|
QCOMPARE(chatBarCache->relationMessage(), QString());
|
||||||
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
||||||
}
|
}
|
||||||
@@ -58,13 +61,13 @@ void ChatBarCacheTest::empty()
|
|||||||
void ChatBarCacheTest::noRoom()
|
void ChatBarCacheTest::noRoom()
|
||||||
{
|
{
|
||||||
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache());
|
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache());
|
||||||
chatBarCache->setReplyId(QLatin1String("$153456789:example.org"));
|
chatBarCache->setReplyId(u"$153456789:example.org"_s);
|
||||||
|
|
||||||
// These should return empty even though a reply ID has been set because the
|
// These should return empty even though a reply ID has been set because the
|
||||||
// ChatBarCache has no parent.
|
// ChatBarCache has no parent.
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.");
|
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.");
|
||||||
QCOMPARE(chatBarCache->relationUser(), QVariantMap());
|
QCOMPARE(chatBarCache->relationAuthor(), Quotient::RoomMember());
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.");
|
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.");
|
||||||
QCOMPARE(chatBarCache->relationMessage(), QString());
|
QCOMPARE(chatBarCache->relationMessage(), QString());
|
||||||
@@ -74,13 +77,13 @@ void ChatBarCacheTest::badParent()
|
|||||||
{
|
{
|
||||||
QScopedPointer<QObject> badParent(new QObject());
|
QScopedPointer<QObject> badParent(new QObject());
|
||||||
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(badParent.get()));
|
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(badParent.get()));
|
||||||
chatBarCache->setReplyId(QLatin1String("$153456789:example.org"));
|
chatBarCache->setReplyId(u"$153456789:example.org"_s);
|
||||||
|
|
||||||
// These should return empty even though a reply ID has been set because the
|
// These should return empty even though a reply ID has been set because the
|
||||||
// ChatBarCache has no parent.
|
// ChatBarCache has no parent.
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.");
|
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.");
|
||||||
QCOMPARE(chatBarCache->relationUser(), QVariantMap());
|
QCOMPARE(chatBarCache->relationAuthor(), Quotient::RoomMember());
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.");
|
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.");
|
||||||
QCOMPARE(chatBarCache->relationMessage(), QString());
|
QCOMPARE(chatBarCache->relationMessage(), QString());
|
||||||
@@ -89,52 +92,84 @@ void ChatBarCacheTest::badParent()
|
|||||||
void ChatBarCacheTest::reply()
|
void ChatBarCacheTest::reply()
|
||||||
{
|
{
|
||||||
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
|
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
|
||||||
chatBarCache->setText(QLatin1String("some text"));
|
chatBarCache->setText(u"some text"_s);
|
||||||
chatBarCache->setAttachmentPath(QLatin1String("some/path"));
|
chatBarCache->setAttachmentPath(u"some/path"_s);
|
||||||
chatBarCache->setReplyId(QLatin1String("$153456789:example.org"));
|
chatBarCache->setReplyId(u"$153456789:example.org"_s);
|
||||||
|
|
||||||
QCOMPARE(chatBarCache->text(), QLatin1String("some text"));
|
QCOMPARE(chatBarCache->text(), u"some text"_s);
|
||||||
QCOMPARE(chatBarCache->isReplying(), true);
|
QCOMPARE(chatBarCache->isReplying(), true);
|
||||||
QCOMPARE(chatBarCache->replyId(), QLatin1String("$153456789:example.org"));
|
QCOMPARE(chatBarCache->replyId(), u"$153456789:example.org"_s);
|
||||||
QCOMPARE(chatBarCache->isEditing(), false);
|
QCOMPARE(chatBarCache->isEditing(), false);
|
||||||
QCOMPARE(chatBarCache->editId(), QString());
|
QCOMPARE(chatBarCache->editId(), QString());
|
||||||
QCOMPARE(chatBarCache->relationUser(), room->getUser(room->user(QLatin1String("@example:example.org"))));
|
QCOMPARE(chatBarCache->relationAuthor(), room->member(u"@example:example.org"_s));
|
||||||
QCOMPARE(chatBarCache->relationMessage(), QLatin1String("This is an example\ntext message"));
|
QCOMPARE(chatBarCache->relationMessage(), u"This is an example\ntext message"_s);
|
||||||
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
||||||
|
QCOMPARE(chatBarCache->relationAuthorIsPresent(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatBarCacheTest::replyMissingUser()
|
||||||
|
{
|
||||||
|
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
|
||||||
|
chatBarCache->setText(u"some text"_s);
|
||||||
|
chatBarCache->setAttachmentPath(u"some/path"_s);
|
||||||
|
chatBarCache->setReplyId(u"$153456789:example.org"_s);
|
||||||
|
|
||||||
|
QCOMPARE(chatBarCache->text(), u"some text"_s);
|
||||||
|
QCOMPARE(chatBarCache->isReplying(), true);
|
||||||
|
QCOMPARE(chatBarCache->replyId(), u"$153456789:example.org"_s);
|
||||||
|
QCOMPARE(chatBarCache->isEditing(), false);
|
||||||
|
QCOMPARE(chatBarCache->editId(), QString());
|
||||||
|
QCOMPARE(chatBarCache->relationAuthor(), room->member(u"@example:example.org"_s));
|
||||||
|
QCOMPARE(chatBarCache->relationMessage(), u"This is an example\ntext message"_s);
|
||||||
|
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
||||||
|
QCOMPARE(chatBarCache->relationAuthorIsPresent(), true);
|
||||||
|
|
||||||
|
QSignalSpy relationAuthorIsPresentSpy(chatBarCache.get(), &ChatBarCache::relationAuthorIsPresentChanged);
|
||||||
|
|
||||||
|
// sync again, which will simulate the reply user leaving the room
|
||||||
|
room->syncNewEvents(u"test-min-sync-extra-sync.json"_s);
|
||||||
|
|
||||||
|
QTRY_COMPARE(relationAuthorIsPresentSpy.count(), 1);
|
||||||
|
QCOMPARE(chatBarCache->relationAuthorIsPresent(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBarCacheTest::edit()
|
void ChatBarCacheTest::edit()
|
||||||
{
|
{
|
||||||
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
|
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
|
||||||
chatBarCache->setText(QLatin1String("some text"));
|
|
||||||
chatBarCache->setAttachmentPath(QLatin1String("some/path"));
|
|
||||||
chatBarCache->setEditId(QLatin1String("$153456789:example.org"));
|
|
||||||
|
|
||||||
QCOMPARE(chatBarCache->text(), QLatin1String("some text"));
|
chatBarCache->setText(u"some text"_s);
|
||||||
|
chatBarCache->setAttachmentPath(u"some/path"_s);
|
||||||
|
connect(chatBarCache.get(), &ChatBarCache::relationIdChanged, this, [](const QString &oldEventId, const QString &newEventId) {
|
||||||
|
QCOMPARE(oldEventId, QString());
|
||||||
|
QCOMPARE(newEventId, QString(u"$153456789:example.org"_s));
|
||||||
|
});
|
||||||
|
chatBarCache->setEditId(u"$153456789:example.org"_s);
|
||||||
|
|
||||||
|
QCOMPARE(chatBarCache->text(), u"some text"_s);
|
||||||
QCOMPARE(chatBarCache->isReplying(), false);
|
QCOMPARE(chatBarCache->isReplying(), false);
|
||||||
QCOMPARE(chatBarCache->replyId(), QString());
|
QCOMPARE(chatBarCache->replyId(), QString());
|
||||||
QCOMPARE(chatBarCache->isEditing(), true);
|
QCOMPARE(chatBarCache->isEditing(), true);
|
||||||
QCOMPARE(chatBarCache->editId(), QLatin1String("$153456789:example.org"));
|
QCOMPARE(chatBarCache->editId(), u"$153456789:example.org"_s);
|
||||||
QCOMPARE(chatBarCache->relationUser(), room->getUser(room->user(QLatin1String("@example:example.org"))));
|
QCOMPARE(chatBarCache->relationAuthor(), room->member(u"@example:example.org"_s));
|
||||||
QCOMPARE(chatBarCache->relationMessage(), QLatin1String("This is an example\ntext message"));
|
QCOMPARE(chatBarCache->relationMessage(), u"This is an example\ntext message"_s);
|
||||||
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
QCOMPARE(chatBarCache->attachmentPath(), QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBarCacheTest::attachment()
|
void ChatBarCacheTest::attachment()
|
||||||
{
|
{
|
||||||
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
|
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
|
||||||
chatBarCache->setText(QLatin1String("some text"));
|
chatBarCache->setText(u"some text"_s);
|
||||||
chatBarCache->setEditId(QLatin1String("$153456789:example.org"));
|
chatBarCache->setEditId(u"$153456789:example.org"_s);
|
||||||
chatBarCache->setAttachmentPath(QLatin1String("some/path"));
|
chatBarCache->setAttachmentPath(u"some/path"_s);
|
||||||
|
|
||||||
QCOMPARE(chatBarCache->text(), QLatin1String("some text"));
|
QCOMPARE(chatBarCache->text(), u"some text"_s);
|
||||||
QCOMPARE(chatBarCache->isReplying(), false);
|
QCOMPARE(chatBarCache->isReplying(), false);
|
||||||
QCOMPARE(chatBarCache->replyId(), QString());
|
QCOMPARE(chatBarCache->replyId(), QString());
|
||||||
QCOMPARE(chatBarCache->isEditing(), false);
|
QCOMPARE(chatBarCache->isEditing(), false);
|
||||||
QCOMPARE(chatBarCache->editId(), QString());
|
QCOMPARE(chatBarCache->editId(), QString());
|
||||||
QCOMPARE(chatBarCache->relationUser(), room->getUser(nullptr));
|
QCOMPARE(chatBarCache->relationAuthor(), room->member(QString()));
|
||||||
QCOMPARE(chatBarCache->relationMessage(), QString());
|
QCOMPARE(chatBarCache->relationMessage(), QString());
|
||||||
QCOMPARE(chatBarCache->attachmentPath(), QLatin1String("some/path"));
|
QCOMPARE(chatBarCache->attachmentPath(), u"some/path"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(ChatBarCacheTest)
|
QTEST_MAIN(ChatBarCacheTest)
|
||||||
|
|||||||
20
autotests/data/localhost.crt
Normal file
20
autotests/data/localhost.crt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDNTCCAh2gAwIBAgIUXbyWfTfcvVLrVB1qx36pW/7IkwMwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE
|
||||||
|
CgwTRGVmYXVsdCBDb21wYW55IEx0ZDAgFw0yNDEyMjQxNTAxMDNaGA8yNTcyMDcy
|
||||||
|
NDE1MDEwM1owQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEc
|
||||||
|
MBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||||
|
ggEPADCCAQoCggEBAKlxZ540TQ1uUDAR7ZJ9ue0PzcD2dPmblIIddyekvZS59V7X
|
||||||
|
drhamclXpHE2EelR87Sexst0BaHH/jmrHwxCtwbeXHZ8ueJHkGHJ5DLZCCiwfG+Q
|
||||||
|
gml7wlSXxXz37vie2tdlZh2yJSM8yvLAYceHb2zOskaGvul7ZITIS0JrPc3o6VZk
|
||||||
|
+MYGkYtA2JfUsv3jH4oQbxOf7RXqhWNAXbB+3hlwRBwMIdyoBNK6YS9QSrTeS9jj
|
||||||
|
UqgO5QmaQZOVvpaPf1Y/rHHLd2Qa6+a/cCJ1sr2biagb75AihpQFsK/oy6D1PP70
|
||||||
|
zTe7hPWn/efEpmtCV7CQ8ti4cRu0Kjy0T8grtCsCAwEAAaMhMB8wHQYDVR0OBBYE
|
||||||
|
FIFlylzwADNLfgTDNkhFeFelaEDxMA0GCSqGSIb3DQEBCwUAA4IBAQBQ2rw4GLIU
|
||||||
|
v+GY7Qru9LttkrQPd2bZXKxDMd/jT+wjmMVtqS4MAsCuDYwaYLjU1aWyqy0mN+lY
|
||||||
|
A17kD0VjBNBy45sYqkZveY0ks8mCScBemtrIDmjz2tiueecBIEASwEPBOZgv5/MV
|
||||||
|
cz864FiChF+2r8Zl8bhycGy9DEpRjzYKvIQWSDHQ3zpuh3iBnjfoieLHWX2kKCpk
|
||||||
|
ouS3V6485rHNCWsZT5IcCwfBFQkOuWRJpIazpz4AfwZh1TK9+bgiKA5EyZjSNrKw
|
||||||
|
xGQSpMSTRQMB0/FOCL/AixhN9unVFUViqUcdtSfoHE1VyBHv9kDT/cYms/Xl4B0t
|
||||||
|
/ZSQJ/D/Km1+
|
||||||
|
-----END CERTIFICATE-----
|
||||||
28
autotests/data/localhost.key
Normal file
28
autotests/data/localhost.key
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCpcWeeNE0NblAw
|
||||||
|
Ee2SfbntD83A9nT5m5SCHXcnpL2UufVe13a4WpnJV6RxNhHpUfO0nsbLdAWhx/45
|
||||||
|
qx8MQrcG3lx2fLniR5BhyeQy2QgosHxvkIJpe8JUl8V89+74ntrXZWYdsiUjPMry
|
||||||
|
wGHHh29szrJGhr7pe2SEyEtCaz3N6OlWZPjGBpGLQNiX1LL94x+KEG8Tn+0V6oVj
|
||||||
|
QF2wft4ZcEQcDCHcqATSumEvUEq03kvY41KoDuUJmkGTlb6Wj39WP6xxy3dkGuvm
|
||||||
|
v3AidbK9m4moG++QIoaUBbCv6Mug9Tz+9M03u4T1p/3nxKZrQlewkPLYuHEbtCo8
|
||||||
|
tE/IK7QrAgMBAAECggEAH9qmeKrra2F4KLlOGNKS//qPGz4Z+ozhi95/NpA1Zb7Z
|
||||||
|
3pUSCBFcROo5i2D3WA4kiymoRLpQjrv60puVcCggoWVvK4VCKsR6Y6/hOx/q9T9M
|
||||||
|
fWrE4ZC3FVEc+uPfZJT0nja9TkrdyXSV0LITD8Ap1eI7yJ9vR5R/bqj64QcpLMrU
|
||||||
|
QeoQIy1oTMR+qdjj33duyRwBZU3Yf8FRB2iW6OILZ8hzFo1jngec7dph9a1RK4e0
|
||||||
|
mEPdc9ywsKlDM7P0Y7zdmjar5XtQn87GiwNhz23f1fzCC2axLtOW0Xm4e4Qumehb
|
||||||
|
WrIi6Vfq8IWMglU7QrBJ7iR0Ls+XoKA5GxomV2IJZQKBgQDoIkOl5YGPQ3iGR+WK
|
||||||
|
e5/2Ml4G/uURzYiOlzSsyfoPXyO4EI2BJd5HkH+EvfgRx4xKkxUZRJdzR7llYPl8
|
||||||
|
BFYcFitvhO8SbD0mNAB5YW7f+3v1pgEN2umzoKd389Zx5WqTZ7YB1VG5RN/Q1JJL
|
||||||
|
2JM0Xgamq2vNtx3roRPxDBeW7QKBgQC63R/bmACJbgIzfaVBX4Zie3NQG0/Hf+gF
|
||||||
|
LnBwUmQDZOR7MY+kSiIUVMn3NuZRiCSCFBVwApruyK8r535JCibTVm5PWjvhFddY
|
||||||
|
LgaPOCKGlm9TLScjoH1pErYgG3uJ4nXeRfXhg4mco6EkrC7RzQywrd0VDoqpuc1Y
|
||||||
|
EKfEsYk8dwKBgE+mSh3nNOBKX1V73+f3aTiZqaeu2DyWkG+UtE9BclrJ40Cp9VPG
|
||||||
|
AZH+o7KRWEgJdzqzYv7riSfWCWgesRv7hOxYMwktzLY+i3DLUQpVAy05ZhwwnJX7
|
||||||
|
ckrfKfc/pGoqNLplUI8qecMfPciy14vMwR2r0Y5orTHFzi9mcqg35PQ1AoGAW2LX
|
||||||
|
OLq+0HdHhk0Va8I+450CSRQCUUvhed87SANTPEG0Z/dWC3/h6NWKrGdh/k+5oxAV
|
||||||
|
Z+EuSkdFPBCLt0bKtCKZ8h7sF+lplotz08kdQXsC2MfFU2wiySdIgK1QHp/tCxZl
|
||||||
|
6LM+sqdnoJrAjwRcB3AQJkMlV1ox7ba/hbdZqYMCgYBS6+JUXSSASpm5ZHd32a8m
|
||||||
|
xwryEZ7H6Hek6lvMHdxmwoKat5dCavxw64nrtyeeGZpg1W3zLLyamF9x/8kMyr6y
|
||||||
|
KKvtBfJ5sCvAbt80o9Pbs6R3yDB3AKiD3s3PQK7lol1nhE/8IbsF2r8JEQVcYd/k
|
||||||
|
oBzkl7MrMyLhhaCqSxwqQQ==
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"content": {
|
"content": {
|
||||||
"user_ids": [
|
"user_ids": [
|
||||||
"@alice:matrix.org",
|
"@alice:matrix.org",
|
||||||
"@bob:example.com"
|
"@bob:kde.org"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"content": {
|
"content": {
|
||||||
"$153456789:example.org": {
|
"$153456789:example.org": {
|
||||||
"m.read": {
|
"m.read": {
|
||||||
"@alice:matrix.org": {
|
"@alice:example.org": {
|
||||||
"ts": 1436451550453
|
"ts": 1436451550453
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
"content": {
|
"content": {
|
||||||
"$1532735824654:example.org": {
|
"$1532735824654:example.org": {
|
||||||
"m.read": {
|
"m.read": {
|
||||||
"@bob:example.com": {
|
"@bob:kde.org": {
|
||||||
"ts": 1436451550453
|
"ts": 1436451550453
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,6 +67,18 @@
|
|||||||
},
|
},
|
||||||
"type": "m.receipt"
|
"type": "m.receipt"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"$1532735824654:example.org": {
|
||||||
|
"m.read": {
|
||||||
|
"@tim2:example.com": {
|
||||||
|
"ts": 1436451550454
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "m.receipt"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"content": {
|
"content": {
|
||||||
"$1532735824654:example.org": {
|
"$1532735824654:example.org": {
|
||||||
@@ -136,6 +148,22 @@
|
|||||||
"age": 1234
|
"age": 1234
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||||
|
"displayname": "Bob",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "bob:kde.org",
|
||||||
|
"state_key": "@bob:kde.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"content": {
|
"content": {
|
||||||
"displayname": "Look\nat\nme\nI\nput\nnewlines\nin\nmy\ndisplay name",
|
"displayname": "Look\nat\nme\nI\nput\nnewlines\nin\nmy\ndisplay name",
|
||||||
@@ -156,7 +184,7 @@
|
|||||||
"summary": {
|
"summary": {
|
||||||
"m.heroes": [
|
"m.heroes": [
|
||||||
"@alice:example.com",
|
"@alice:example.com",
|
||||||
"@bob:example.com"
|
"@bob:kde.org"
|
||||||
],
|
],
|
||||||
"m.invited_member_count": 0,
|
"m.invited_member_count": 0,
|
||||||
"m.joined_member_count": 2
|
"m.joined_member_count": 2
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"content": {
|
|
||||||
"body": "https://matrix.to/#/@alice:example.org",
|
|
||||||
"msgtype": "m.text"
|
|
||||||
},
|
|
||||||
"event_id": "$validlink1:example.org",
|
|
||||||
"origin_server_ts": 1432735824654,
|
|
||||||
"room_id": "!test:example.org",
|
|
||||||
"sender": "@example:example.org",
|
|
||||||
"type": "m.room.message",
|
|
||||||
"unsigned": {
|
|
||||||
"age": 1234
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"content": {
|
|
||||||
"body": "mxc://example.org/SEsfnsuifSDFSSEF",
|
|
||||||
"msgtype": "m.text"
|
|
||||||
},
|
|
||||||
"event_id": "$validlink1:example.org",
|
|
||||||
"origin_server_ts": 1432735824654,
|
|
||||||
"room_id": "!test:example.org",
|
|
||||||
"sender": "@example:example.org",
|
|
||||||
"type": "m.room.message",
|
|
||||||
"unsigned": {
|
|
||||||
"age": 1234
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"content": {
|
|
||||||
"body": "testhttps://kde.org",
|
|
||||||
"msgtype": "m.text"
|
|
||||||
},
|
|
||||||
"event_id": "$validlink1:example.org",
|
|
||||||
"origin_server_ts": 1432735824654,
|
|
||||||
"room_id": "!test:example.org",
|
|
||||||
"sender": "@example:example.org",
|
|
||||||
"type": "m.room.message",
|
|
||||||
"unsigned": {
|
|
||||||
"age": 1234
|
|
||||||
}
|
|
||||||
}
|
|
||||||
20
autotests/data/test-min-sync-extra-sync.json
Normal file
20
autotests/data/test-min-sync-extra-sync.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"state": {
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"membership": "leave"
|
||||||
|
},
|
||||||
|
"event_id": "$1432735824666PhrSA:example.org",
|
||||||
|
"origin_server_ts": 1432735824666,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@example:example.org",
|
||||||
|
"state_key": "@example:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"replaces_state": "$143273582443PhrSn:example.org"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,16 +37,59 @@
|
|||||||
"events": [
|
"events": [
|
||||||
{
|
{
|
||||||
"content": {
|
"content": {
|
||||||
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
"displayname": "Example",
|
||||||
"displayname": "Alice Margatroid",
|
"membership": "join"
|
||||||
"membership": "join",
|
|
||||||
"reason": "Looking for support"
|
|
||||||
},
|
},
|
||||||
"event_id": "$143273582443PhrSn:example.org",
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
"origin_server_ts": 1432735824653,
|
"origin_server_ts": 1432735824653,
|
||||||
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
"sender": "@example:example.org",
|
"sender": "@example:example.org",
|
||||||
"state_key": "@alice:example.org",
|
"state_key": "@example:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"displayname": "Bob",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273blorb3PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@bob:kde.org",
|
||||||
|
"state_key": "@bob:kde.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"displayname": "Invited",
|
||||||
|
"membership": "invite"
|
||||||
|
},
|
||||||
|
"event_id": "$asdfpj443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@example:example.org",
|
||||||
|
"state_key": "@invited:example.com",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"displayname": "Banned",
|
||||||
|
"membership": "ban"
|
||||||
|
},
|
||||||
|
"event_id": "$asdfpj443PhrSnasfd:example.org",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@banned:example.com",
|
||||||
|
"state_key": "@banned:example.com",
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"unsigned": {
|
"unsigned": {
|
||||||
"age": 1234
|
"age": 1234
|
||||||
@@ -59,7 +102,7 @@
|
|||||||
"@alice:example.com",
|
"@alice:example.com",
|
||||||
"@bob:example.com"
|
"@bob:example.com"
|
||||||
],
|
],
|
||||||
"m.invited_member_count": 0,
|
"m.invited_member_count": 1,
|
||||||
"m.joined_member_count": 2
|
"m.joined_member_count": 2
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
|
|||||||
@@ -8,14 +8,14 @@
|
|||||||
"answers": [
|
"answers": [
|
||||||
{
|
{
|
||||||
"id": "option1",
|
"id": "option1",
|
||||||
"org.matrix.msc1767.text": "option1"
|
"org.matrix.msc1767.text": "option1text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "option2",
|
"id": "option2",
|
||||||
"org.matrix.msc1767.text": "option2"
|
"org.matrix.msc1767.text": "option2text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"kind": "org.matrix.msc3381.poll.disclosed",
|
"kind": "org.matrix.msc3381.poll.undisclosed",
|
||||||
"max_selections": 1,
|
"max_selections": 1,
|
||||||
"question": {
|
"question": {
|
||||||
"body": "test",
|
"body": "test",
|
||||||
|
|||||||
@@ -130,7 +130,23 @@
|
|||||||
"origin_server_ts": 1432735824653,
|
"origin_server_ts": 1432735824653,
|
||||||
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
"sender": "@example:example.org",
|
"sender": "@example:example.org",
|
||||||
"state_key": "@alice:example.org",
|
"state_key": "@alice:matrix.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||||
|
"displayname": "Bob",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "bob:example.org",
|
||||||
|
"state_key": "@bob:example.org",
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"unsigned": {
|
"unsigned": {
|
||||||
"age": 1234
|
"age": 1234
|
||||||
|
|||||||
@@ -51,6 +51,21 @@
|
|||||||
"unsigned": {
|
"unsigned": {
|
||||||
"age": 1234
|
"age": 1234
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"displayname": "Example",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1432735824653,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@example:example.org",
|
||||||
|
"state_key": "@example:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"content": {
|
|
||||||
"body": "https://kde.org",
|
|
||||||
"msgtype": "m.text"
|
|
||||||
},
|
|
||||||
"event_id": "$validlink1:example.org",
|
|
||||||
"origin_server_ts": 1432735824654,
|
|
||||||
"room_id": "!test:example.org",
|
|
||||||
"sender": "@example:example.org",
|
|
||||||
"type": "m.room.message",
|
|
||||||
"unsigned": {
|
|
||||||
"age": 1234
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"content": {
|
|
||||||
"body": "www.example.org",
|
|
||||||
"msgtype": "m.text"
|
|
||||||
},
|
|
||||||
"event_id": "$validlink1:example.org",
|
|
||||||
"origin_server_ts": 1432735824654,
|
|
||||||
"room_id": "!test:example.org",
|
|
||||||
"sender": "@example:example.org",
|
|
||||||
"type": "m.room.message",
|
|
||||||
"unsigned": {
|
|
||||||
"age": 1234
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"content": {
|
|
||||||
"body": "[Rich Link](https://kde.org)",
|
|
||||||
"format": "org.matrix.custom.html",
|
|
||||||
"formatted_body": "<a href=\"https://kde.org\">Rich Link</a>",
|
|
||||||
"msgtype": "m.text"
|
|
||||||
},
|
|
||||||
"event_id": "$validlink1:example.org",
|
|
||||||
"origin_server_ts": 1432735824654,
|
|
||||||
"room_id": "!test:example.org",
|
|
||||||
"sender": "@example:example.org",
|
|
||||||
"type": "m.room.message",
|
|
||||||
"unsigned": {
|
|
||||||
"age": 1234
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QQuickItem>
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
#include "delegatesizehelper.h"
|
#include "delegatesizehelper.h"
|
||||||
@@ -30,7 +31,7 @@ void DelegateSizeHelperTest::risingPercentage_data()
|
|||||||
QTest::addColumn<int>("currentPercentageWidth");
|
QTest::addColumn<int>("currentPercentageWidth");
|
||||||
QTest::addColumn<qreal>("currentWidth");
|
QTest::addColumn<qreal>("currentWidth");
|
||||||
|
|
||||||
QTest::newRow("zero") << qreal(0) << int(0) << qreal(0);
|
QTest::newRow("zero") << qreal(0) << int(100) << qreal(0);
|
||||||
QTest::newRow("one hundred") << qreal(100) << int(0) << qreal(0);
|
QTest::newRow("one hundred") << qreal(100) << int(0) << qreal(0);
|
||||||
QTest::newRow("one fifty") << qreal(150) << int(50) << qreal(75);
|
QTest::newRow("one fifty") << qreal(150) << int(50) << qreal(75);
|
||||||
QTest::newRow("two hundred") << qreal(200) << int(100) << qreal(200);
|
QTest::newRow("two hundred") << qreal(200) << int(100) << qreal(200);
|
||||||
@@ -43,16 +44,18 @@ void DelegateSizeHelperTest::risingPercentage()
|
|||||||
QFETCH(int, currentPercentageWidth);
|
QFETCH(int, currentPercentageWidth);
|
||||||
QFETCH(qreal, currentWidth);
|
QFETCH(qreal, currentWidth);
|
||||||
|
|
||||||
|
auto item = QQuickItem();
|
||||||
|
item.setWidth(parentWidth);
|
||||||
|
|
||||||
DelegateSizeHelper delegateSizeHelper;
|
DelegateSizeHelper delegateSizeHelper;
|
||||||
|
delegateSizeHelper.setParentItem(&item);
|
||||||
delegateSizeHelper.setStartBreakpoint(100);
|
delegateSizeHelper.setStartBreakpoint(100);
|
||||||
delegateSizeHelper.setEndBreakpoint(200);
|
delegateSizeHelper.setEndBreakpoint(200);
|
||||||
delegateSizeHelper.setStartPercentWidth(0);
|
delegateSizeHelper.setStartPercentWidth(0);
|
||||||
delegateSizeHelper.setEndPercentWidth(100);
|
delegateSizeHelper.setEndPercentWidth(100);
|
||||||
|
|
||||||
delegateSizeHelper.setParentWidth(parentWidth);
|
QCOMPARE(delegateSizeHelper.availablePercentageWidth(), currentPercentageWidth);
|
||||||
|
QCOMPARE(delegateSizeHelper.availableWidth(), currentWidth);
|
||||||
QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth);
|
|
||||||
QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DelegateSizeHelperTest::fallingPercentage_data()
|
void DelegateSizeHelperTest::fallingPercentage_data()
|
||||||
@@ -74,16 +77,18 @@ void DelegateSizeHelperTest::fallingPercentage()
|
|||||||
QFETCH(int, currentPercentageWidth);
|
QFETCH(int, currentPercentageWidth);
|
||||||
QFETCH(qreal, currentWidth);
|
QFETCH(qreal, currentWidth);
|
||||||
|
|
||||||
|
auto item = QQuickItem();
|
||||||
|
item.setWidth(parentWidth);
|
||||||
|
|
||||||
DelegateSizeHelper delegateSizeHelper;
|
DelegateSizeHelper delegateSizeHelper;
|
||||||
|
delegateSizeHelper.setParentItem(&item);
|
||||||
delegateSizeHelper.setStartBreakpoint(100);
|
delegateSizeHelper.setStartBreakpoint(100);
|
||||||
delegateSizeHelper.setEndBreakpoint(200);
|
delegateSizeHelper.setEndBreakpoint(200);
|
||||||
delegateSizeHelper.setStartPercentWidth(100);
|
delegateSizeHelper.setStartPercentWidth(100);
|
||||||
delegateSizeHelper.setEndPercentWidth(0);
|
delegateSizeHelper.setEndPercentWidth(0);
|
||||||
|
|
||||||
delegateSizeHelper.setParentWidth(parentWidth);
|
QCOMPARE(delegateSizeHelper.availablePercentageWidth(), currentPercentageWidth);
|
||||||
|
QCOMPARE(delegateSizeHelper.availableWidth(), currentWidth);
|
||||||
QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth);
|
|
||||||
QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DelegateSizeHelperTest::equalPercentage_data()
|
void DelegateSizeHelperTest::equalPercentage_data()
|
||||||
@@ -105,16 +110,18 @@ void DelegateSizeHelperTest::equalPercentage()
|
|||||||
QFETCH(int, currentPercentageWidth);
|
QFETCH(int, currentPercentageWidth);
|
||||||
QFETCH(qreal, currentWidth);
|
QFETCH(qreal, currentWidth);
|
||||||
|
|
||||||
|
auto item = QQuickItem();
|
||||||
|
item.setWidth(parentWidth);
|
||||||
|
|
||||||
DelegateSizeHelper delegateSizeHelper;
|
DelegateSizeHelper delegateSizeHelper;
|
||||||
|
delegateSizeHelper.setParentItem(&item);
|
||||||
delegateSizeHelper.setStartBreakpoint(100);
|
delegateSizeHelper.setStartBreakpoint(100);
|
||||||
delegateSizeHelper.setEndBreakpoint(200);
|
delegateSizeHelper.setEndBreakpoint(200);
|
||||||
delegateSizeHelper.setStartPercentWidth(50);
|
delegateSizeHelper.setStartPercentWidth(50);
|
||||||
delegateSizeHelper.setEndPercentWidth(50);
|
delegateSizeHelper.setEndPercentWidth(50);
|
||||||
|
|
||||||
delegateSizeHelper.setParentWidth(parentWidth);
|
QCOMPARE(delegateSizeHelper.availablePercentageWidth(), currentPercentageWidth);
|
||||||
|
QCOMPARE(delegateSizeHelper.availableWidth(), currentWidth);
|
||||||
QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth);
|
|
||||||
QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DelegateSizeHelperTest::equalBreakpoint_data()
|
void DelegateSizeHelperTest::equalBreakpoint_data()
|
||||||
@@ -124,13 +131,13 @@ void DelegateSizeHelperTest::equalBreakpoint_data()
|
|||||||
QTest::addColumn<int>("currentPercentageWidth");
|
QTest::addColumn<int>("currentPercentageWidth");
|
||||||
QTest::addColumn<qreal>("currentWidth");
|
QTest::addColumn<qreal>("currentWidth");
|
||||||
|
|
||||||
QTest::newRow("start higher") << int(100) << int(0) << int(-1) << qreal(0);
|
QTest::newRow("start higher") << int(100) << int(0) << int(100) << qreal(1000);
|
||||||
QTest::newRow("equal") << int(50) << int(50) << int(50) << qreal(500);
|
QTest::newRow("equal") << int(50) << int(50) << int(50) << qreal(500);
|
||||||
QTest::newRow("end higher") << int(0) << int(100) << int(-1) << qreal(0);
|
QTest::newRow("end higher") << int(0) << int(100) << int(100) << qreal(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We expect a default return except in the case where the the two percentages are
|
* We expect a default return except in the case where the two percentages are
|
||||||
* equal as that case can be calculated without dividing by zero.
|
* equal as that case can be calculated without dividing by zero.
|
||||||
*/
|
*/
|
||||||
void DelegateSizeHelperTest::equalBreakpoint()
|
void DelegateSizeHelperTest::equalBreakpoint()
|
||||||
@@ -140,16 +147,18 @@ void DelegateSizeHelperTest::equalBreakpoint()
|
|||||||
QFETCH(int, currentPercentageWidth);
|
QFETCH(int, currentPercentageWidth);
|
||||||
QFETCH(qreal, currentWidth);
|
QFETCH(qreal, currentWidth);
|
||||||
|
|
||||||
|
auto item = QQuickItem();
|
||||||
|
item.setWidth(1000);
|
||||||
|
|
||||||
DelegateSizeHelper delegateSizeHelper;
|
DelegateSizeHelper delegateSizeHelper;
|
||||||
|
delegateSizeHelper.setParentItem(&item);
|
||||||
delegateSizeHelper.setStartBreakpoint(100);
|
delegateSizeHelper.setStartBreakpoint(100);
|
||||||
delegateSizeHelper.setEndBreakpoint(100);
|
delegateSizeHelper.setEndBreakpoint(100);
|
||||||
delegateSizeHelper.setStartPercentWidth(startPercentageWidth);
|
delegateSizeHelper.setStartPercentWidth(startPercentageWidth);
|
||||||
delegateSizeHelper.setEndPercentWidth(endPercentageWidth);
|
delegateSizeHelper.setEndPercentWidth(endPercentageWidth);
|
||||||
|
|
||||||
delegateSizeHelper.setParentWidth(1000);
|
QCOMPARE(delegateSizeHelper.availablePercentageWidth(), currentPercentageWidth);
|
||||||
|
QCOMPARE(delegateSizeHelper.availableWidth(), currentWidth);
|
||||||
QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth);
|
|
||||||
QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(DelegateSizeHelperTest)
|
QTEST_GUILESS_MAIN(DelegateSizeHelperTest)
|
||||||
|
|||||||
@@ -11,8 +11,9 @@
|
|||||||
#include <Quotient/connection.h>
|
#include <Quotient/connection.h>
|
||||||
#include <Quotient/quotient_common.h>
|
#include <Quotient/quotient_common.h>
|
||||||
#include <Quotient/syncdata.h>
|
#include <Quotient/syncdata.h>
|
||||||
|
#include <qcbormap.h>
|
||||||
|
#include <qtestcase.h>
|
||||||
|
|
||||||
#include "enums/delegatetype.h"
|
|
||||||
#include "linkpreviewer.h"
|
#include "linkpreviewer.h"
|
||||||
#include "models/reactionmodel.h"
|
#include "models/reactionmodel.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
@@ -29,21 +30,10 @@ class EventHandlerTest : public QObject
|
|||||||
private:
|
private:
|
||||||
Connection *connection = nullptr;
|
Connection *connection = nullptr;
|
||||||
TestUtils::TestRoom *room = nullptr;
|
TestUtils::TestRoom *room = nullptr;
|
||||||
EventHandler eventHandler;
|
|
||||||
EventHandler emptyHandler;
|
|
||||||
EventHandler noEventHandler;
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
|
|
||||||
void nullSetEvent();
|
|
||||||
void eventId();
|
|
||||||
void nullEventId();
|
|
||||||
void delegateType_data();
|
|
||||||
void delegateType();
|
|
||||||
void nullDelegateType();
|
|
||||||
void author();
|
|
||||||
void nullAuthor();
|
|
||||||
void authorDisplayName();
|
void authorDisplayName();
|
||||||
void nullAuthorDisplayName();
|
void nullAuthorDisplayName();
|
||||||
void singleLineSidplayName();
|
void singleLineSidplayName();
|
||||||
@@ -51,7 +41,6 @@ private Q_SLOTS:
|
|||||||
void time();
|
void time();
|
||||||
void nullTime();
|
void nullTime();
|
||||||
void timeString();
|
void timeString();
|
||||||
void nullTimeString();
|
|
||||||
void highlighted();
|
void highlighted();
|
||||||
void nullHighlighted();
|
void nullHighlighted();
|
||||||
void hidden();
|
void hidden();
|
||||||
@@ -62,261 +51,158 @@ private Q_SLOTS:
|
|||||||
void genericBody();
|
void genericBody();
|
||||||
void nullGenericBody();
|
void nullGenericBody();
|
||||||
void markdownBody();
|
void markdownBody();
|
||||||
|
void markdownBodyReply();
|
||||||
void subtitle();
|
void subtitle();
|
||||||
void nullSubtitle();
|
void nullSubtitle();
|
||||||
void mediaInfo();
|
void mediaInfo();
|
||||||
void nullMediaInfo();
|
void nullMediaInfo();
|
||||||
void hasReply();
|
|
||||||
void nullHasReply();
|
|
||||||
void replyId();
|
|
||||||
void nullReplyId();
|
|
||||||
void replyDelegateType();
|
|
||||||
void nullReplyDelegateType();
|
|
||||||
void replyAuthor();
|
void replyAuthor();
|
||||||
void nullReplyAuthor();
|
void nullReplyAuthor();
|
||||||
void replyBody();
|
|
||||||
void nullReplyBody();
|
|
||||||
void replyMediaInfo();
|
|
||||||
void nullReplyMediaInfo();
|
|
||||||
void thread();
|
|
||||||
void nullThread();
|
|
||||||
void location();
|
void location();
|
||||||
void nullLocation();
|
void nullLocation();
|
||||||
void readMarkers();
|
|
||||||
void nullReadMarkers();
|
|
||||||
|
|
||||||
void cleanup();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void EventHandlerTest::initTestCase()
|
void EventHandlerTest::initTestCase()
|
||||||
{
|
{
|
||||||
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
|
connection = Connection::makeMockConnection(u"@bob:kde.org"_s);
|
||||||
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-eventhandler-sync.json"));
|
room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, u"test-eventhandler-sync.json"_s);
|
||||||
|
|
||||||
eventHandler.setRoom(room);
|
|
||||||
noEventHandler.setRoom(room);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::nullSetEvent()
|
|
||||||
{
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "cannot setEvent when m_room is set to nullptr.");
|
|
||||||
emptyHandler.setEvent(room->messageEvents().at(0).get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::eventId()
|
|
||||||
{
|
|
||||||
eventHandler.setEvent(room->messageEvents().at(0).get());
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getId(), QStringLiteral("$153456789:example.org"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::nullEventId()
|
|
||||||
{
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getId called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.getId(), QString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::delegateType_data()
|
|
||||||
{
|
|
||||||
QTest::addColumn<int>("eventNum");
|
|
||||||
QTest::addColumn<DelegateType::Type>("delegateType");
|
|
||||||
|
|
||||||
QTest::newRow("message") << 0 << DelegateType::Message;
|
|
||||||
QTest::newRow("state") << 1 << DelegateType::State;
|
|
||||||
QTest::newRow("message 2") << 2 << DelegateType::Message;
|
|
||||||
QTest::newRow("reaction") << 3 << DelegateType::Other;
|
|
||||||
QTest::newRow("video") << 4 << DelegateType::Video;
|
|
||||||
QTest::newRow("location") << 7 << DelegateType::Location;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::delegateType()
|
|
||||||
{
|
|
||||||
QFETCH(int, eventNum);
|
|
||||||
QFETCH(DelegateType::Type, delegateType);
|
|
||||||
|
|
||||||
eventHandler.setEvent(room->messageEvents().at(eventNum).get());
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getDelegateType(), delegateType);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::nullDelegateType()
|
|
||||||
{
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getDelegateType called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.getDelegateType(), DelegateType::Other);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::author()
|
|
||||||
{
|
|
||||||
auto event = room->messageEvents().at(0).get();
|
|
||||||
auto author = room->user(event->senderId());
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
auto eventHandlerAuthor = eventHandler.getAuthor();
|
|
||||||
|
|
||||||
QCOMPARE(eventHandlerAuthor["isLocalUser"_ls], author->id() == room->localUser()->id());
|
|
||||||
QCOMPARE(eventHandlerAuthor["id"_ls], author->id());
|
|
||||||
QCOMPARE(eventHandlerAuthor["displayName"_ls], author->displayname(room));
|
|
||||||
QCOMPARE(eventHandlerAuthor["avatarSource"_ls], room->avatarForMember(author));
|
|
||||||
QCOMPARE(eventHandlerAuthor["avatarMediaId"_ls], author->avatarMediaId(room));
|
|
||||||
QCOMPARE(eventHandlerAuthor["color"_ls], Utils::getUserColor(author->hueF()));
|
|
||||||
QCOMPARE(eventHandlerAuthor["object"_ls], QVariant::fromValue(author));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::nullAuthor()
|
|
||||||
{
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getAuthor called with m_room set to nullptr.");
|
|
||||||
QCOMPARE(emptyHandler.getAuthor(), QVariantMap());
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getAuthor called with m_event set to nullptr. Returning empty user.");
|
|
||||||
QCOMPARE(noEventHandler.getAuthor(), room->getUser(nullptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::authorDisplayName()
|
void EventHandlerTest::authorDisplayName()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(1).get();
|
QCOMPARE(EventHandler::authorDisplayName(room, room->messageEvents().at(1).get()), u"before"_s);
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getAuthorDisplayName(), QStringLiteral("before"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullAuthorDisplayName()
|
void EventHandlerTest::nullAuthorDisplayName()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_room set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "authorDisplayName called with room set to nullptr.");
|
||||||
QCOMPARE(emptyHandler.getAuthorDisplayName(), QString());
|
QCOMPARE(EventHandler::authorDisplayName(nullptr, nullptr), QString());
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "authorDisplayName called with event set to nullptr.");
|
||||||
QCOMPARE(noEventHandler.getAuthorDisplayName(), QString());
|
QCOMPARE(EventHandler::authorDisplayName(room, nullptr), QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::singleLineSidplayName()
|
void EventHandlerTest::singleLineSidplayName()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(11).get();
|
QCOMPARE(EventHandler::singleLineAuthorDisplayname(room, room->messageEvents().at(11).get()), "Look at me I put newlines in my display name"_L1);
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.singleLineAuthorDisplayname(), QStringLiteral("Look at me I put newlines in my display name"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullSingleLineDisplayName()
|
void EventHandlerTest::nullSingleLineDisplayName()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_room set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "singleLineAuthorDisplayname called with room set to nullptr.");
|
||||||
QCOMPARE(emptyHandler.singleLineAuthorDisplayname(), QString());
|
QCOMPARE(EventHandler::singleLineAuthorDisplayname(nullptr, nullptr), QString());
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "singleLineAuthorDisplayname called with event set to nullptr.");
|
||||||
QCOMPARE(noEventHandler.singleLineAuthorDisplayname(), QString());
|
QCOMPARE(EventHandler::singleLineAuthorDisplayname(room, nullptr), QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::time()
|
void EventHandlerTest::time()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(0).get();
|
const auto event = room->messageEvents().at(0).get();
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getTime(), QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC));
|
QCOMPARE(EventHandler::time(room, event), QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)));
|
||||||
QCOMPARE(eventHandler.getTime(true, QDateTime::fromMSecsSinceEpoch(1234, Qt::UTC)), QDateTime::fromMSecsSinceEpoch(1234, Qt::UTC));
|
|
||||||
|
const auto txID = room->postJson("m.room.message"_L1, event->fullJson());
|
||||||
|
QCOMPARE(room->pendingEvents().size(), 1);
|
||||||
|
const auto pendingIt = room->findPendingEvent(txID);
|
||||||
|
QCOMPARE(EventHandler::time(room, pendingIt->event(), true), pendingIt->lastUpdated());
|
||||||
|
|
||||||
|
room->discardMessage(txID);
|
||||||
|
QCOMPARE(room->pendingEvents().size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullTime()
|
void EventHandlerTest::nullTime()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getTime called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "time called with room set to nullptr.");
|
||||||
QCOMPARE(noEventHandler.getTime(), QDateTime());
|
QCOMPARE(EventHandler::time(nullptr, nullptr), QDateTime());
|
||||||
|
|
||||||
eventHandler.setEvent(room->messageEvents().at(0).get());
|
QTest::ignoreMessage(QtWarningMsg, "time called with event set to nullptr.");
|
||||||
QTest::ignoreMessage(QtWarningMsg, "a value must be provided for lastUpdated for a pending event.");
|
QCOMPARE(EventHandler::time(room, nullptr), QDateTime());
|
||||||
QCOMPARE(eventHandler.getTime(true), QDateTime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::timeString()
|
void EventHandlerTest::timeString()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(0).get();
|
const auto event = room->messageEvents().at(0).get();
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
KFormat format;
|
KFormat format;
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getTimeString(false),
|
QCOMPARE(EventHandler::timeString(room, event, false),
|
||||||
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC).toLocalTime().time(), QLocale::ShortFormat));
|
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)).toLocalTime().time(), QLocale::ShortFormat));
|
||||||
QCOMPARE(eventHandler.getTimeString(true),
|
QCOMPARE(EventHandler::timeString(room, event, true),
|
||||||
format.formatRelativeDate(QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC).toLocalTime().date(), QLocale::ShortFormat));
|
format.formatRelativeDate(QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)).toLocalTime().date(), QLocale::ShortFormat));
|
||||||
QCOMPARE(eventHandler.getTimeString(false, QLocale::ShortFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
|
QCOMPARE(EventHandler::timeString(room, event, u"hh:mm"_s),
|
||||||
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC).toLocalTime().time(), QLocale::ShortFormat));
|
QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::LocalTime)).toString(u"hh:mm"_s));
|
||||||
QCOMPARE(eventHandler.getTimeString(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)),
|
|
||||||
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC).toLocalTime().time(), QLocale::LongFormat));
|
|
||||||
QCOMPARE(eventHandler.getTimeString(true, QLocale::LongFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
|
|
||||||
format.formatRelativeDate(QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC).toLocalTime().date(), QLocale::LongFormat));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::nullTimeString()
|
const auto txID = room->postJson("m.room.message"_L1, event->fullJson());
|
||||||
{
|
QCOMPARE(room->pendingEvents().size(), 1);
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getTimeString called with m_event set to nullptr.");
|
const auto pendingIt = room->findPendingEvent(txID);
|
||||||
QCOMPARE(noEventHandler.getTimeString(false), QString());
|
|
||||||
|
|
||||||
eventHandler.setEvent(room->messageEvents().at(0).get());
|
QCOMPARE(EventHandler::timeString(room, pendingIt->event(), false, QLocale::ShortFormat, true),
|
||||||
QTest::ignoreMessage(QtWarningMsg, "a value must be provided for lastUpdated for a pending event.");
|
QLocale().toString(pendingIt->lastUpdated().toLocalTime().time(), QLocale::ShortFormat));
|
||||||
QCOMPARE(eventHandler.getTimeString(false, QLocale::ShortFormat, true), QString());
|
QCOMPARE(EventHandler::timeString(room, pendingIt->event(), true, QLocale::ShortFormat, true),
|
||||||
|
format.formatRelativeDate(pendingIt->lastUpdated().toLocalTime().date(), QLocale::ShortFormat));
|
||||||
|
QCOMPARE(EventHandler::timeString(room, pendingIt->event(), false, QLocale::LongFormat, true),
|
||||||
|
QLocale().toString(pendingIt->lastUpdated().toLocalTime().time(), QLocale::LongFormat));
|
||||||
|
QCOMPARE(EventHandler::timeString(room, pendingIt->event(), true, QLocale::LongFormat, true),
|
||||||
|
format.formatRelativeDate(pendingIt->lastUpdated().toLocalTime().date(), QLocale::LongFormat));
|
||||||
|
|
||||||
|
room->discardMessage(txID);
|
||||||
|
QCOMPARE(room->pendingEvents().size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::highlighted()
|
void EventHandlerTest::highlighted()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(2).get();
|
QCOMPARE(EventHandler::isHighlighted(room, room->messageEvents().at(2).get()), true);
|
||||||
eventHandler.setEvent(event);
|
QCOMPARE(EventHandler::isHighlighted(room, room->messageEvents().at(0).get()), false);
|
||||||
|
|
||||||
QCOMPARE(eventHandler.isHighlighted(), true);
|
|
||||||
|
|
||||||
event = room->messageEvents().at(0).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.isHighlighted(), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullHighlighted()
|
void EventHandlerTest::nullHighlighted()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "isHighlighted called with m_room set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "isHighlighted called with room set to nullptr.");
|
||||||
QCOMPARE(emptyHandler.isHighlighted(), false);
|
QCOMPARE(EventHandler::isHighlighted(nullptr, nullptr), false);
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "isHighlighted called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "isHighlighted called with event set to nullptr.");
|
||||||
QCOMPARE(noEventHandler.isHighlighted(), false);
|
QCOMPARE(EventHandler::isHighlighted(room, nullptr), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::hidden()
|
void EventHandlerTest::hidden()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(3).get();
|
QCOMPARE(EventHandler::isHidden(room, room->messageEvents().at(3).get()), true);
|
||||||
eventHandler.setEvent(event);
|
QCOMPARE(EventHandler::isHidden(room, room->messageEvents().at(0).get()), false);
|
||||||
|
|
||||||
QCOMPARE(eventHandler.isHidden(), true);
|
|
||||||
|
|
||||||
event = room->messageEvents().at(0).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.isHidden(), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullHidden()
|
void EventHandlerTest::nullHidden()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "isHidden called with m_room set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "isHidden called with room set to nullptr.");
|
||||||
QCOMPARE(emptyHandler.isHidden(), false);
|
QCOMPARE(EventHandler::isHidden(nullptr, nullptr), false);
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "isHidden called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "isHidden called with event set to nullptr.");
|
||||||
QCOMPARE(noEventHandler.isHidden(), false);
|
QCOMPARE(EventHandler::isHidden(room, nullptr), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::body()
|
void EventHandlerTest::body()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(0).get();
|
const auto event = room->messageEvents().at(0).get();
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getRichBody(), QStringLiteral("<b>This is an example<br>text message</b>"));
|
QCOMPARE(EventHandler::richBody(room, event), u"<b>This is an example<br>text message</b>"_s);
|
||||||
QCOMPARE(eventHandler.getRichBody(true), QStringLiteral("<b>This is an example text message</b>"));
|
QCOMPARE(EventHandler::richBody(room, event, true), u"<b>This is an example text message</b>"_s);
|
||||||
QCOMPARE(eventHandler.getPlainBody(), QStringLiteral("This is an example\ntext message"));
|
QCOMPARE(EventHandler::plainBody(room, event), u"This is an example\ntext message"_s);
|
||||||
QCOMPARE(eventHandler.getPlainBody(true), QStringLiteral("This is an example text message"));
|
QCOMPARE(EventHandler::plainBody(room, event, true), u"This is an example text message"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullBody()
|
void EventHandlerTest::nullBody()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getRichBody called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "richBody called with room set to nullptr.");
|
||||||
QCOMPARE(noEventHandler.getRichBody(), QString());
|
QCOMPARE(EventHandler::richBody(nullptr, nullptr), QString());
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getPlainBody called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "richBody called with event set to nullptr.");
|
||||||
QCOMPARE(noEventHandler.getPlainBody(), QString());
|
QCOMPARE(EventHandler::richBody(room, nullptr), 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()
|
void EventHandlerTest::genericBody_data()
|
||||||
@@ -324,11 +210,11 @@ void EventHandlerTest::genericBody_data()
|
|||||||
QTest::addColumn<int>("eventNum");
|
QTest::addColumn<int>("eventNum");
|
||||||
QTest::addColumn<QString>("output");
|
QTest::addColumn<QString>("output");
|
||||||
|
|
||||||
QTest::newRow("message") << 0 << QStringLiteral("sent a message");
|
QTest::newRow("message") << 0 << u"<a href=\"https://matrix.to/#/@example:example.org\">after</a> sent a message"_s;
|
||||||
QTest::newRow("member") << 1 << QStringLiteral("changed their display name and updated their avatar");
|
QTest::newRow("member") << 1 << u"<a href=\"https://matrix.to/#/@example:example.org\">after</a> changed their display name and updated their avatar"_s;
|
||||||
QTest::newRow("message 2") << 2 << QStringLiteral("sent a message");
|
QTest::newRow("message 2") << 2 << u"<a href=\"https://matrix.to/#/@example:example.org\">after</a> sent a message"_s;
|
||||||
QTest::newRow("reaction") << 3 << QStringLiteral("Unknown event");
|
QTest::newRow("reaction") << 3 << u"Unknown event"_s;
|
||||||
QTest::newRow("video") << 4 << QStringLiteral("sent a message");
|
QTest::newRow("video") << 4 << u"<a href=\"https://matrix.to/#/@example:example.org\">after</a> sent a message"_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::genericBody()
|
void EventHandlerTest::genericBody()
|
||||||
@@ -336,333 +222,116 @@ void EventHandlerTest::genericBody()
|
|||||||
QFETCH(int, eventNum);
|
QFETCH(int, eventNum);
|
||||||
QFETCH(QString, output);
|
QFETCH(QString, output);
|
||||||
|
|
||||||
eventHandler.setEvent(room->messageEvents().at(eventNum).get());
|
QCOMPARE(EventHandler::genericBody(room, room->messageEvents().at(eventNum).get()), output);
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getGenericBody(), output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullGenericBody()
|
void EventHandlerTest::nullGenericBody()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getGenericBody called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "genericBody called with room set to nullptr.");
|
||||||
QCOMPARE(noEventHandler.getGenericBody(), QString());
|
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()
|
void EventHandlerTest::markdownBody()
|
||||||
{
|
{
|
||||||
eventHandler.setEvent(room->messageEvents().at(0).get());
|
QCOMPARE(EventHandler::markdownBody(room->messageEvents().at(0).get()), u"This is an example\ntext message"_s);
|
||||||
|
}
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getMarkdownBody(), QStringLiteral("This is an example\ntext message"));
|
void EventHandlerTest::markdownBodyReply()
|
||||||
|
{
|
||||||
|
QCOMPARE(EventHandler::markdownBody(room->messageEvents().at(5).get()), u"reply"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::subtitle()
|
void EventHandlerTest::subtitle()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(0).get();
|
QCOMPARE(EventHandler::subtitleText(room, room->messageEvents().at(0).get()), u"after: This is an example text message"_s);
|
||||||
eventHandler.setEvent(event);
|
QCOMPARE(EventHandler::subtitleText(room, room->messageEvents().at(2).get()),
|
||||||
|
u"after: This is a highlight @bob:kde.org and this is a link https://kde.org"_s);
|
||||||
QCOMPARE(eventHandler.subtitleText(), QStringLiteral("after: This is an example text message"));
|
|
||||||
|
|
||||||
event = room->messageEvents().at(2).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.subtitleText(), QStringLiteral("after: This is a highlight @bob:kde.org and this is a link https://kde.org"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullSubtitle()
|
void EventHandlerTest::nullSubtitle()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "subtitleText called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "subtitleText called with room set to nullptr.");
|
||||||
QCOMPARE(noEventHandler.subtitleText(), QString());
|
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()
|
void EventHandlerTest::mediaInfo()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(4).get();
|
auto event = room->messageEvents().at(4).get();
|
||||||
eventHandler.setEvent(event);
|
auto mediaInfo = EventHandler::mediaInfo(room, event);
|
||||||
|
auto thumbnailInfo = mediaInfo["tempInfo"_L1].toMap();
|
||||||
|
|
||||||
auto mediaInfo = eventHandler.getMediaInfo();
|
QCOMPARE(mediaInfo["source"_L1], room->makeMediaUrl(event->id(), QUrl("mxc://kde.org/1234567"_L1)));
|
||||||
auto thumbnailInfo = mediaInfo["tempInfo"_ls].toMap();
|
QCOMPARE(mediaInfo["mimeType"_L1], u"video/mp4"_s);
|
||||||
|
QCOMPARE(mediaInfo["mimeIcon"_L1], u"video-mp4"_s);
|
||||||
QCOMPARE(mediaInfo["source"_ls], room->makeMediaUrl(event->id(), QUrl("mxc://kde.org/1234567"_ls)));
|
QCOMPARE(mediaInfo["size"_L1], 62650636);
|
||||||
QCOMPARE(mediaInfo["mimeType"_ls], QStringLiteral("video/mp4"));
|
QCOMPARE(mediaInfo["duration"_L1], 10);
|
||||||
QCOMPARE(mediaInfo["mimeIcon"_ls], QStringLiteral("video-mp4"));
|
QCOMPARE(mediaInfo["width"_L1], 1920);
|
||||||
QCOMPARE(mediaInfo["size"_ls], 62650636);
|
QCOMPARE(mediaInfo["height"_L1], 1080);
|
||||||
QCOMPARE(mediaInfo["duration"_ls], 10);
|
QCOMPARE(thumbnailInfo["source"_L1], room->makeMediaUrl(event->id(), QUrl("mxc://kde.org/2234567"_L1)));
|
||||||
QCOMPARE(mediaInfo["width"_ls], 1920);
|
QCOMPARE(thumbnailInfo["mimeType"_L1], u"image/jpeg"_s);
|
||||||
QCOMPARE(mediaInfo["height"_ls], 1080);
|
QCOMPARE(thumbnailInfo["mimeIcon"_L1], u"image-jpeg"_s);
|
||||||
QCOMPARE(thumbnailInfo["source"_ls], room->makeMediaUrl(event->id(), QUrl("mxc://kde.org/2234567"_ls)));
|
QCOMPARE(thumbnailInfo["size"_L1], 382249);
|
||||||
QCOMPARE(thumbnailInfo["mimeType"_ls], QStringLiteral("image/jpeg"));
|
QCOMPARE(thumbnailInfo["width"_L1], 800);
|
||||||
QCOMPARE(thumbnailInfo["mimeIcon"_ls], QStringLiteral("image-jpeg"));
|
QCOMPARE(thumbnailInfo["height"_L1], 450);
|
||||||
QCOMPARE(thumbnailInfo["size"_ls], 382249);
|
|
||||||
QCOMPARE(thumbnailInfo["width"_ls], 800);
|
|
||||||
QCOMPARE(thumbnailInfo["height"_ls], 450);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullMediaInfo()
|
void EventHandlerTest::nullMediaInfo()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getMediaInfo called with m_room set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "mediaInfo called with room set to nullptr.");
|
||||||
QCOMPARE(emptyHandler.getMediaInfo(), QVariantMap());
|
QCOMPARE(EventHandler::mediaInfo(nullptr, nullptr), QVariantMap());
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getMediaInfo called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "mediaInfo called with event set to nullptr.");
|
||||||
QCOMPARE(noEventHandler.getMediaInfo(), QVariantMap());
|
QCOMPARE(EventHandler::mediaInfo(room, nullptr), QVariantMap());
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::hasReply()
|
|
||||||
{
|
|
||||||
auto event = room->messageEvents().at(5).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.hasReply(), true);
|
|
||||||
|
|
||||||
event = room->messageEvents().at(0).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.hasReply(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::nullHasReply()
|
|
||||||
{
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "hasReply called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.hasReply(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::replyId()
|
|
||||||
{
|
|
||||||
auto event = room->messageEvents().at(5).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getReplyId(), QStringLiteral("$153456789:example.org"));
|
|
||||||
|
|
||||||
event = room->messageEvents().at(0).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getReplyId(), QStringLiteral(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::nullReplyId()
|
|
||||||
{
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getReplyId called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.getReplyId(), QString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::replyDelegateType()
|
|
||||||
{
|
|
||||||
auto event = room->messageEvents().at(5).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getReplyDelegateType(), DelegateType::Message);
|
|
||||||
|
|
||||||
event = room->messageEvents().at(0).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getReplyDelegateType(), DelegateType::Other);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::nullReplyDelegateType()
|
|
||||||
{
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getReplyDelegateType called with m_room set to nullptr.");
|
|
||||||
QCOMPARE(emptyHandler.getReplyDelegateType(), DelegateType::Other);
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getReplyDelegateType called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.getReplyDelegateType(), DelegateType::Other);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::replyAuthor()
|
void EventHandlerTest::replyAuthor()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(5).get();
|
|
||||||
auto replyEvent = room->messageEvents().at(0).get();
|
auto replyEvent = room->messageEvents().at(0).get();
|
||||||
auto replyAuthor = room->user(replyEvent->senderId());
|
auto replyAuthor = room->member(replyEvent->senderId());
|
||||||
eventHandler.setEvent(event);
|
auto eventHandlerReplyAuthor = EventHandler::replyAuthor(room, room->messageEvents().at(5).get());
|
||||||
|
|
||||||
auto eventHandlerReplyAuthor = eventHandler.getReplyAuthor();
|
QCOMPARE(eventHandlerReplyAuthor.isLocalMember(), replyAuthor.id() == room->localMember().id());
|
||||||
|
QCOMPARE(eventHandlerReplyAuthor.id(), replyAuthor.id());
|
||||||
|
QCOMPARE(eventHandlerReplyAuthor.displayName(), replyAuthor.displayName());
|
||||||
|
QCOMPARE(eventHandlerReplyAuthor.avatarUrl(), replyAuthor.avatarUrl());
|
||||||
|
QCOMPARE(eventHandlerReplyAuthor.avatarMediaId(), replyAuthor.avatarMediaId());
|
||||||
|
QCOMPARE(eventHandlerReplyAuthor.color(), replyAuthor.color());
|
||||||
|
|
||||||
QCOMPARE(eventHandlerReplyAuthor["isLocalUser"_ls], replyAuthor->id() == room->localUser()->id());
|
QCOMPARE(EventHandler::replyAuthor(room, room->messageEvents().at(0).get()), RoomMember());
|
||||||
QCOMPARE(eventHandlerReplyAuthor["id"_ls], replyAuthor->id());
|
|
||||||
QCOMPARE(eventHandlerReplyAuthor["displayName"_ls], replyAuthor->displayname(room));
|
|
||||||
QCOMPARE(eventHandlerReplyAuthor["avatarSource"_ls], room->avatarForMember(replyAuthor));
|
|
||||||
QCOMPARE(eventHandlerReplyAuthor["avatarMediaId"_ls], replyAuthor->avatarMediaId(room));
|
|
||||||
QCOMPARE(eventHandlerReplyAuthor["color"_ls], Utils::getUserColor(replyAuthor->hueF()));
|
|
||||||
QCOMPARE(eventHandlerReplyAuthor["object"_ls], QVariant::fromValue(replyAuthor));
|
|
||||||
|
|
||||||
event = room->messageEvents().at(0).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getReplyAuthor(), room->getUser(nullptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullReplyAuthor()
|
void EventHandlerTest::nullReplyAuthor()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getReplyAuthor called with m_room set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "replyAuthor called with room set to nullptr.");
|
||||||
QCOMPARE(emptyHandler.getReplyAuthor(), QVariantMap());
|
QCOMPARE(EventHandler::replyAuthor(nullptr, nullptr), RoomMember());
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getReplyAuthor called with m_event set to nullptr. Returning empty user.");
|
QTest::ignoreMessage(QtWarningMsg, "replyAuthor called with event set to nullptr. Returning empty user.");
|
||||||
QCOMPARE(noEventHandler.getReplyAuthor(), room->getUser(nullptr));
|
QCOMPARE(EventHandler::replyAuthor(room, nullptr), RoomMember());
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::replyBody()
|
|
||||||
{
|
|
||||||
auto event = room->messageEvents().at(5).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
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.setEvent(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());
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getReplyMediaInfo called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.getReplyMediaInfo(), QVariantMap());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::thread()
|
|
||||||
{
|
|
||||||
auto event = room->messageEvents().at(0).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.isThreaded(), false);
|
|
||||||
QCOMPARE(eventHandler.threadRoot(), QString());
|
|
||||||
|
|
||||||
event = room->messageEvents().at(9).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.isThreaded(), true);
|
|
||||||
QCOMPARE(eventHandler.threadRoot(), QStringLiteral("$threadroot:example.org"));
|
|
||||||
QCOMPARE(eventHandler.getReplyId(), QStringLiteral("$threadroot:example.org"));
|
|
||||||
|
|
||||||
event = room->messageEvents().at(10).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.isThreaded(), true);
|
|
||||||
QCOMPARE(eventHandler.threadRoot(), QStringLiteral("$threadroot:example.org"));
|
|
||||||
QCOMPARE(eventHandler.getReplyId(), 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, "threadRoot called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.threadRoot(), QString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::location()
|
void EventHandlerTest::location()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(7).get();
|
QCOMPARE(EventHandler::latitude(room->messageEvents().at(7).get()), u"51.7035"_s.toFloat());
|
||||||
eventHandler.setEvent(event);
|
QCOMPARE(EventHandler::longitude(room->messageEvents().at(7).get()), u"-1.14394"_s.toFloat());
|
||||||
|
QCOMPARE(EventHandler::locationAssetType(room->messageEvents().at(7).get()), u"m.pin"_s);
|
||||||
QCOMPARE(eventHandler.getLatitude(), QStringLiteral("51.7035").toFloat());
|
|
||||||
QCOMPARE(eventHandler.getLongitude(), QStringLiteral("-1.14394").toFloat());
|
|
||||||
QCOMPARE(eventHandler.getLocationAssetType(), QStringLiteral("m.pin"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventHandlerTest::nullLocation()
|
void EventHandlerTest::nullLocation()
|
||||||
{
|
{
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getLatitude called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "latitude called with event set to nullptr.");
|
||||||
QCOMPARE(emptyHandler.getLatitude(), -100.0);
|
QCOMPARE(EventHandler::latitude(nullptr), -100.0);
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getLongitude called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "longitude called with event set to nullptr.");
|
||||||
QCOMPARE(emptyHandler.getLongitude(), -200.0);
|
QCOMPARE(EventHandler::longitude(nullptr), -200.0);
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getLocationAssetType called with m_event set to nullptr.");
|
QTest::ignoreMessage(QtWarningMsg, "locationAssetType called with event set to nullptr.");
|
||||||
QCOMPARE(emptyHandler.getLocationAssetType(), QString());
|
QCOMPARE(EventHandler::locationAssetType(nullptr), QString());
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::readMarkers()
|
|
||||||
{
|
|
||||||
auto event = room->messageEvents().at(0).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.hasReadMarkers(), true);
|
|
||||||
|
|
||||||
auto readMarkers = eventHandler.getReadMarkers();
|
|
||||||
|
|
||||||
QCOMPARE(readMarkers.size(), 1);
|
|
||||||
QCOMPARE(readMarkers[0].toMap()["id"_ls], QStringLiteral("@alice:matrix.org"));
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getNumberExcessReadMarkers(), QString());
|
|
||||||
QCOMPARE(eventHandler.getReadMarkersString(), QStringLiteral("1 user: @alice:matrix.org"));
|
|
||||||
|
|
||||||
event = room->messageEvents().at(2).get();
|
|
||||||
eventHandler.setEvent(event);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.hasReadMarkers(), true);
|
|
||||||
|
|
||||||
readMarkers = eventHandler.getReadMarkers();
|
|
||||||
|
|
||||||
QCOMPARE(readMarkers.size(), 5);
|
|
||||||
|
|
||||||
QCOMPARE(eventHandler.getNumberExcessReadMarkers(), QStringLiteral("+ 1"));
|
|
||||||
// There are no guarantees on the order of the users it will be different every time so don't match the whole string.
|
|
||||||
QCOMPARE(eventHandler.getReadMarkersString().startsWith(QStringLiteral("6 users:")), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::nullReadMarkers()
|
|
||||||
{
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "hasReadMarkers called with m_room set to nullptr.");
|
|
||||||
QCOMPARE(emptyHandler.hasReadMarkers(), false);
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getReadMarkers called with m_room set to nullptr.");
|
|
||||||
QCOMPARE(emptyHandler.getReadMarkers(), QVariantList());
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getNumberExcessReadMarkers called with m_room set to nullptr.");
|
|
||||||
QCOMPARE(emptyHandler.getNumberExcessReadMarkers(), QString());
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getReadMarkersString called with m_room set to nullptr.");
|
|
||||||
QCOMPARE(emptyHandler.getReadMarkersString(), QString());
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "hasReadMarkers called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.hasReadMarkers(), false);
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getReadMarkers called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.getReadMarkers(), QVariantList());
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getNumberExcessReadMarkers called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.getNumberExcessReadMarkers(), QString());
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "getReadMarkersString called with m_event set to nullptr.");
|
|
||||||
QCOMPARE(noEventHandler.getReadMarkersString(), QString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventHandlerTest::cleanup()
|
|
||||||
{
|
|
||||||
eventHandler.setEvent(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(EventHandlerTest)
|
QTEST_MAIN(EventHandlerTest)
|
||||||
|
|||||||
@@ -6,12 +6,11 @@
|
|||||||
|
|
||||||
#include "linkpreviewer.h"
|
#include "linkpreviewer.h"
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
#include <Quotient/events/roommessageevent.h>
|
#include <Quotient/events/roommessageevent.h>
|
||||||
#include <Quotient/quotient_common.h>
|
#include <Quotient/quotient_common.h>
|
||||||
#include <Quotient/syncdata.h>
|
#include <Quotient/syncdata.h>
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#include "testutils.h"
|
#include "testutils.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
@@ -30,74 +29,74 @@ private Q_SLOTS:
|
|||||||
void linkPreviewsMatch_data();
|
void linkPreviewsMatch_data();
|
||||||
void linkPreviewsMatch();
|
void linkPreviewsMatch();
|
||||||
|
|
||||||
|
void multipleLinkPreviewsMatch_data();
|
||||||
|
void multipleLinkPreviewsMatch();
|
||||||
|
|
||||||
void linkPreviewsReject_data();
|
void linkPreviewsReject_data();
|
||||||
void linkPreviewsReject();
|
void linkPreviewsReject();
|
||||||
|
|
||||||
void editedLink();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void LinkPreviewerTest::initTestCase()
|
void LinkPreviewerTest::initTestCase()
|
||||||
{
|
{
|
||||||
connection = Connection::makeMockConnection(QStringLiteral("@bob:example.org"));
|
connection = Connection::makeMockConnection(u"@bob:example.org"_s);
|
||||||
room = new TestUtils::TestRoom(connection, QStringLiteral("!test:example.org"));
|
room = new TestUtils::TestRoom(connection, u"!test:example.org"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkPreviewerTest::linkPreviewsMatch_data()
|
void LinkPreviewerTest::linkPreviewsMatch_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("eventSource");
|
QTest::addColumn<QString>("inputString");
|
||||||
QTest::addColumn<QUrl>("testOutputLink");
|
QTest::addColumn<QUrl>("testOutputLink");
|
||||||
|
|
||||||
QTest::newRow("plainHttps") << QStringLiteral("test-validplainlink-event.json") << QUrl("https://kde.org"_ls);
|
QTest::newRow("plainHttps") << u"https://kde.org"_s << QUrl(u"https://kde.org"_s);
|
||||||
QTest::newRow("richHttps") << QStringLiteral("test-validrichlink-event.json") << QUrl("https://kde.org"_ls);
|
QTest::newRow("richHttps") << u"<a href=\"https://kde.org\">Rich Link</a>"_s << QUrl(u"https://kde.org"_s);
|
||||||
QTest::newRow("plainWww") << QStringLiteral("test-validplainwwwlink-event.json") << QUrl("www.example.org"_ls);
|
QTest::newRow("richHttpsLinkDescription") << u"<a href=\"https://kde.org\">https://kde.org</a>"_s << QUrl(u"https://kde.org"_s);
|
||||||
QTest::newRow("multipleHttps") << QStringLiteral("test-multiplelink-event.json") << QUrl("www.example.org"_ls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkPreviewerTest::linkPreviewsMatch()
|
void LinkPreviewerTest::linkPreviewsMatch()
|
||||||
{
|
{
|
||||||
QFETCH(QString, eventSource);
|
QFETCH(QString, inputString);
|
||||||
QFETCH(QUrl, testOutputLink);
|
QFETCH(QUrl, testOutputLink);
|
||||||
|
|
||||||
auto event = TestUtils::loadEventFromFile<RoomMessageEvent>(eventSource);
|
auto link = LinkPreviewer::linkPreviews(inputString)[0];
|
||||||
auto linkPreviewer = LinkPreviewer(room, event.get());
|
|
||||||
|
|
||||||
QCOMPARE(linkPreviewer.empty(), false);
|
QCOMPARE(link, testOutputLink);
|
||||||
QCOMPARE(linkPreviewer.url(), testOutputLink);
|
}
|
||||||
|
|
||||||
|
void LinkPreviewerTest::multipleLinkPreviewsMatch_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("inputString");
|
||||||
|
QTest::addColumn<QList<QUrl>>("testOutputLinks");
|
||||||
|
|
||||||
|
QTest::newRow("multipleHttps") << u"www.example.org https://kde.org"_s << QList{QUrl(u"www.example.org"_s), QUrl(u"https://kde.org"_s)};
|
||||||
|
QTest::newRow("multipleHttps1Invalid") << u"www.example.org mxc://example.org/SEsfnsuifSDFSSEF"_s << QList{QUrl(u"www.example.org"_s)};
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkPreviewerTest::multipleLinkPreviewsMatch()
|
||||||
|
{
|
||||||
|
QFETCH(QString, inputString);
|
||||||
|
QFETCH(QList<QUrl>, testOutputLinks);
|
||||||
|
|
||||||
|
auto links = LinkPreviewer::linkPreviews(inputString);
|
||||||
|
|
||||||
|
QCOMPARE(links, testOutputLinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkPreviewerTest::linkPreviewsReject_data()
|
void LinkPreviewerTest::linkPreviewsReject_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("eventSource");
|
QTest::addColumn<QString>("inputString");
|
||||||
|
|
||||||
QTest::newRow("mxc") << QStringLiteral("test-invalidmxclink-event.json");
|
QTest::newRow("mxc") << u"mxc://example.org/SEsfnsuifSDFSSEF"_s;
|
||||||
QTest::newRow("matrixTo") << QStringLiteral("test-invalidmatrixtolink-event.json");
|
QTest::newRow("matrixTo") << u"https://matrix.to/#/@alice:example.org"_s;
|
||||||
QTest::newRow("noSpace") << QStringLiteral("test-invalidnospacelink-event.json");
|
QTest::newRow("noSpace") << u"testhttps://kde.org"_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkPreviewerTest::linkPreviewsReject()
|
void LinkPreviewerTest::linkPreviewsReject()
|
||||||
{
|
{
|
||||||
QFETCH(QString, eventSource);
|
QFETCH(QString, inputString);
|
||||||
|
|
||||||
auto event = TestUtils::loadEventFromFile<RoomMessageEvent>(eventSource);
|
auto links = LinkPreviewer::linkPreviews(inputString);
|
||||||
auto linkPreviewer = LinkPreviewer(room, event.get());
|
|
||||||
|
|
||||||
QCOMPARE(linkPreviewer.empty(), true);
|
QCOMPARE(links.empty(), true);
|
||||||
QCOMPARE(linkPreviewer.url(), QUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkPreviewerTest::editedLink()
|
|
||||||
{
|
|
||||||
room->syncNewEvents(QStringLiteral("test-linkpreviewerintial-sync.json"));
|
|
||||||
auto event = eventCast<const RoomMessageEvent>(room->messageEvents().at(0).get());
|
|
||||||
auto linkPreviewer = LinkPreviewer(room, event);
|
|
||||||
|
|
||||||
QCOMPARE(linkPreviewer.empty(), false);
|
|
||||||
QCOMPARE(linkPreviewer.url(), QUrl("https://kde.org"_ls));
|
|
||||||
|
|
||||||
room->syncNewEvents(QStringLiteral("test-linkpreviewerreplace-sync.json"));
|
|
||||||
|
|
||||||
QCOMPARE(linkPreviewer.empty(), true);
|
|
||||||
QCOMPARE(linkPreviewer.url(), QUrl());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(LinkPreviewerTest)
|
QTEST_MAIN(LinkPreviewerTest)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ private Q_SLOTS:
|
|||||||
void MediaSizeHelperTest::uninitialized()
|
void MediaSizeHelperTest::uninitialized()
|
||||||
{
|
{
|
||||||
MediaSizeHelper mediasizehelper;
|
MediaSizeHelper mediasizehelper;
|
||||||
|
mediasizehelper.setMaxSize(540, 540);
|
||||||
QCOMPARE(mediasizehelper.currentSize(), QSize(540, qRound(qreal(NeoChatConfig::self()->mediaMaxWidth()) / qreal(16.0) * qreal(9.0))));
|
QCOMPARE(mediasizehelper.currentSize(), QSize(540, qRound(qreal(NeoChatConfig::self()->mediaMaxWidth()) / qreal(16.0) * qreal(9.0))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +61,7 @@ void MediaSizeHelperTest::limits()
|
|||||||
QFETCH(QSize, currentSize);
|
QFETCH(QSize, currentSize);
|
||||||
|
|
||||||
MediaSizeHelper mediasizehelper;
|
MediaSizeHelper mediasizehelper;
|
||||||
|
mediasizehelper.setMaxSize(540, 540);
|
||||||
mediasizehelper.setMediaWidth(mediaWidth);
|
mediasizehelper.setMediaWidth(mediaWidth);
|
||||||
mediasizehelper.setMediaHeight(mediaHeight);
|
mediasizehelper.setMediaHeight(mediaHeight);
|
||||||
mediasizehelper.setContentMaxWidth(contentMaxWidth);
|
mediasizehelper.setContentMaxWidth(contentMaxWidth);
|
||||||
|
|||||||
62
autotests/messagecontentmodeltest.cpp
Normal file
62
autotests/messagecontentmodeltest.cpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// 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/eventmessagecontentmodel.h"
|
||||||
|
|
||||||
|
#include "neochatconnection.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 = new NeoChatConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageContentModelTest::missingEvent()
|
||||||
|
{
|
||||||
|
auto room = new TestUtils::TestRoom(connection, u"#firstRoom:kde.org"_s);
|
||||||
|
auto model1 = EventMessageContentModel(room, u"$153456789:example.org"_s);
|
||||||
|
|
||||||
|
QCOMPARE(model1.rowCount(), 1);
|
||||||
|
QCOMPARE(model1.data(model1.index(0), MessageContentModel::ComponentTypeRole), MessageComponentType::Loading);
|
||||||
|
QCOMPARE(model1.data(model1.index(0), MessageContentModel::DisplayRole), u"Loading"_s);
|
||||||
|
|
||||||
|
auto model2 = EventMessageContentModel(room, u"$153456789:example.org"_s, true);
|
||||||
|
|
||||||
|
QCOMPARE(model2.rowCount(), 1);
|
||||||
|
QCOMPARE(model2.data(model2.index(0), MessageContentModel::ComponentTypeRole), MessageComponentType::Loading);
|
||||||
|
QCOMPARE(model2.data(model2.index(0), MessageContentModel::DisplayRole), u"Loading reply"_s);
|
||||||
|
|
||||||
|
room->syncNewEvents(u"test-min-sync.json"_s);
|
||||||
|
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"
|
||||||
@@ -27,8 +27,8 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
void NeoChatRoomTest::initTestCase()
|
void NeoChatRoomTest::initTestCase()
|
||||||
{
|
{
|
||||||
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
|
connection = Connection::makeMockConnection(u"@bob:kde.org"_s);
|
||||||
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), "test-min-sync.json"_ls);
|
room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, u"test-min-sync.json"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NeoChatRoomTest::eventTest()
|
void NeoChatRoomTest::eventTest()
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
void PollHandlerTest::initTestCase()
|
void PollHandlerTest::initTestCase()
|
||||||
{
|
{
|
||||||
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
|
connection = Connection::makeMockConnection(u"@bob:kde.org"_s);
|
||||||
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), "test-pollhandlerstart-sync.json"_ls);
|
room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, u"test-pollhandlerstart-sync.json"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basically don't crash.
|
// Basically don't crash.
|
||||||
@@ -41,29 +41,32 @@ void PollHandlerTest::nullObject()
|
|||||||
auto pollHandler = PollHandler();
|
auto pollHandler = PollHandler();
|
||||||
|
|
||||||
QCOMPARE(pollHandler.hasEnded(), false);
|
QCOMPARE(pollHandler.hasEnded(), false);
|
||||||
QCOMPARE(pollHandler.answerCount(), 0);
|
QCOMPARE(pollHandler.numAnswers(), 0);
|
||||||
QCOMPARE(pollHandler.question(), QString());
|
QCOMPARE(pollHandler.question(), QString());
|
||||||
QCOMPARE(pollHandler.options(), QJsonArray());
|
QCOMPARE(pollHandler.kind(), PollKind::Disclosed);
|
||||||
QCOMPARE(pollHandler.answers(), QJsonObject());
|
|
||||||
QCOMPARE(pollHandler.counts(), QJsonObject());
|
|
||||||
QCOMPARE(pollHandler.kind(), QString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PollHandlerTest::poll()
|
void PollHandlerTest::poll()
|
||||||
{
|
{
|
||||||
auto startEvent = eventCast<const PollStartEvent>(room->messageEvents().at(0).get());
|
auto startEvent = eventCast<const PollStartEvent>(room->messageEvents().at(0).get());
|
||||||
auto pollHandler = PollHandler(room, startEvent);
|
auto pollHandler = PollHandler(room, startEvent->id());
|
||||||
|
|
||||||
auto options = QJsonArray{QJsonObject{{"id"_ls, "option1"_ls}, {"org.matrix.msc1767.text"_ls, "option1"_ls}},
|
QList<Quotient::EventContent::Answer> options = {EventContent::Answer{"option1"_L1, "option1"_L1}, EventContent::Answer{"option2"_L1, "option2"_L1}};
|
||||||
QJsonObject{{"id"_ls, "option2"_ls}, {"org.matrix.msc1767.text"_ls, "option2"_ls}}};
|
|
||||||
|
|
||||||
|
const auto answer0 = pollHandler.answerAtRow(0);
|
||||||
|
const auto answer1 = pollHandler.answerAtRow(1);
|
||||||
QCOMPARE(pollHandler.hasEnded(), false);
|
QCOMPARE(pollHandler.hasEnded(), false);
|
||||||
QCOMPARE(pollHandler.answerCount(), 0);
|
QCOMPARE(pollHandler.numAnswers(), 2);
|
||||||
QCOMPARE(pollHandler.question(), QStringLiteral("test"));
|
QCOMPARE(pollHandler.question(), u"test"_s);
|
||||||
QCOMPARE(pollHandler.options(), options);
|
QCOMPARE(answer0.id, "option1"_L1);
|
||||||
QCOMPARE(pollHandler.answers(), QJsonObject());
|
QCOMPARE(answer1.id, "option2"_L1);
|
||||||
QCOMPARE(pollHandler.counts(), QJsonObject());
|
QCOMPARE(answer0.text, "option1text"_L1);
|
||||||
QCOMPARE(pollHandler.kind(), QStringLiteral("org.matrix.msc3381.poll.disclosed"));
|
QCOMPARE(answer1.text, "option2text"_L1);
|
||||||
|
QCOMPARE(pollHandler.answerCountAtId(answer0.id), 0);
|
||||||
|
QCOMPARE(pollHandler.answerCountAtId(answer1.id), 0);
|
||||||
|
QCOMPARE(pollHandler.checkMemberSelectedId(connection->userId(), answer0.id), false);
|
||||||
|
QCOMPARE(pollHandler.checkMemberSelectedId(connection->userId(), answer1.id), false);
|
||||||
|
QCOMPARE(pollHandler.kind(), PollKind::Undisclosed);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(PollHandlerTest)
|
QTEST_GUILESS_MAIN(PollHandlerTest)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <Quotient/events/roommessageevent.h>
|
#include <Quotient/events/roommessageevent.h>
|
||||||
|
|
||||||
|
#include "models/eventmessagecontentmodel.h"
|
||||||
#include "testutils.h"
|
#include "testutils.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
@@ -20,61 +21,50 @@ class ReactionModelTest : public QObject
|
|||||||
private:
|
private:
|
||||||
Connection *connection = nullptr;
|
Connection *connection = nullptr;
|
||||||
TestUtils::TestRoom *room = nullptr;
|
TestUtils::TestRoom *room = nullptr;
|
||||||
|
EventMessageContentModel *parentModel;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
|
|
||||||
void nullModel();
|
|
||||||
void basicReaction();
|
void basicReaction();
|
||||||
void newReaction();
|
void newReaction();
|
||||||
};
|
};
|
||||||
|
|
||||||
void ReactionModelTest::initTestCase()
|
void ReactionModelTest::initTestCase()
|
||||||
{
|
{
|
||||||
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
|
connection = Connection::makeMockConnection(u"@bob:kde.org"_s);
|
||||||
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-reactionmodel-sync.json"));
|
room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, u"test-reactionmodel-sync.json"_s);
|
||||||
}
|
parentModel = new EventMessageContentModel(room, "123456"_L1);
|
||||||
|
|
||||||
void ReactionModelTest::nullModel()
|
|
||||||
{
|
|
||||||
auto model = ReactionModel(nullptr, nullptr);
|
|
||||||
|
|
||||||
QCOMPARE(model.rowCount(), 0);
|
|
||||||
QCOMPARE(model.data(model.index(0), ReactionModel::TextContentRole), QVariant());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReactionModelTest::basicReaction()
|
void ReactionModelTest::basicReaction()
|
||||||
{
|
{
|
||||||
auto event = eventCast<const RoomMessageEvent>(room->messageEvents().at(0).get());
|
auto event = eventCast<const RoomMessageEvent>(room->messageEvents().at(0).get());
|
||||||
auto model = ReactionModel(event, room);
|
auto model = ReactionModel(parentModel, event->id(), room);
|
||||||
|
|
||||||
QCOMPARE(model.rowCount(), 1);
|
QCOMPARE(model.rowCount(), 1);
|
||||||
QCOMPARE(model.data(model.index(0), ReactionModel::TextContentRole), QStringLiteral("<span style=\"font-family: 'emoji';\">👍</span>"));
|
QCOMPARE(model.data(model.index(0), ReactionModel::TextContentRole), u"<span style=\"font-family: 'emoji';\">👍</span>"_s);
|
||||||
QCOMPARE(model.data(model.index(0), ReactionModel::ReactionRole), QStringLiteral("👍"));
|
QCOMPARE(model.data(model.index(0), ReactionModel::ReactionRole), u"👍"_s);
|
||||||
QCOMPARE(model.data(model.index(0), ReactionModel::ToolTipRole),
|
QCOMPARE(model.data(model.index(0), ReactionModel::ToolTipRole), u"Alice Margatroid reacted with <span style=\"font-family: 'emoji';\">👍</span>"_s);
|
||||||
QStringLiteral("@alice:matrix.org reacted with <span style=\"font-family: 'emoji';\">👍</span>"));
|
QCOMPARE(model.data(model.index(0), ReactionModel::HasLocalMember), false);
|
||||||
auto authorList = QVariantList{room->getUser(room->user(QStringLiteral("@alice:matrix.org")))};
|
|
||||||
QCOMPARE(model.data(model.index(0), ReactionModel::AuthorsRole), authorList);
|
|
||||||
QCOMPARE(model.data(model.index(0), ReactionModel::HasLocalUser), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReactionModelTest::newReaction()
|
void ReactionModelTest::newReaction()
|
||||||
{
|
{
|
||||||
auto event = eventCast<const RoomMessageEvent>(room->messageEvents().at(0).get());
|
auto event = eventCast<const RoomMessageEvent>(room->messageEvents().at(0).get());
|
||||||
auto model = new ReactionModel(event, room);
|
auto model = new ReactionModel(parentModel, event->id(), room);
|
||||||
|
|
||||||
QCOMPARE(model->rowCount(), 1);
|
QCOMPARE(model->rowCount(), 1);
|
||||||
QCOMPARE(model->data(model->index(0), ReactionModel::ToolTipRole),
|
QCOMPARE(model->data(model->index(0), ReactionModel::ToolTipRole), u"Alice Margatroid reacted with <span style=\"font-family: 'emoji';\">👍</span>"_s);
|
||||||
QStringLiteral("@alice:matrix.org reacted with <span style=\"font-family: 'emoji';\">👍</span>"));
|
|
||||||
|
|
||||||
QSignalSpy spy(model, SIGNAL(modelReset()));
|
QSignalSpy spy(model, SIGNAL(modelReset()));
|
||||||
|
|
||||||
room->syncNewEvents(QLatin1String("test-reactionmodel-extra-sync.json"));
|
room->syncNewEvents(u"test-reactionmodel-extra-sync.json"_s);
|
||||||
QCOMPARE(model->rowCount(), 2);
|
QCOMPARE(model->rowCount(), 2);
|
||||||
QCOMPARE(spy.count(), 2); // Once for each of the 2 new reactions.
|
QCOMPARE(spy.count(), 2); // Once for each of the 2 new reactions.
|
||||||
QCOMPARE(model->data(model->index(1), ReactionModel::ReactionRole), QStringLiteral("😆"));
|
QCOMPARE(model->data(model->index(1), ReactionModel::ReactionRole), u"😆"_s);
|
||||||
QCOMPARE(model->data(model->index(0), ReactionModel::ToolTipRole),
|
QCOMPARE(model->data(model->index(0), ReactionModel::ToolTipRole),
|
||||||
QStringLiteral("@alice:matrix.org and @bob:example.org reacted with <span style=\"font-family: 'emoji';\">👍</span>"));
|
u"Alice Margatroid and Bob reacted with <span style=\"font-family: 'emoji';\">👍</span>"_s);
|
||||||
|
|
||||||
delete model;
|
delete model;
|
||||||
}
|
}
|
||||||
|
|||||||
132
autotests/roommanagertest.cpp
Normal file
132
autotests/roommanagertest.cpp
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Tobias Fella <tobias.fella@kde.org>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSignalSpy>
|
||||||
|
#include <QTest>
|
||||||
|
#include <QVariantList>
|
||||||
|
|
||||||
|
#include "accountmanager.h"
|
||||||
|
#include "models/actionsmodel.h"
|
||||||
|
#include "roommanager.h"
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
#include "testutils.h"
|
||||||
|
|
||||||
|
using namespace Quotient;
|
||||||
|
|
||||||
|
class RoomManagerTest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
NeoChatConnection *connection = nullptr;
|
||||||
|
NeoChatRoom *room = nullptr;
|
||||||
|
|
||||||
|
Server server;
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void initTestCase();
|
||||||
|
void testMaximizeMedia();
|
||||||
|
};
|
||||||
|
|
||||||
|
void RoomManagerTest::initTestCase()
|
||||||
|
{
|
||||||
|
Connection::setRoomType<NeoChatRoom>();
|
||||||
|
server.start();
|
||||||
|
KLocalizedString::setApplicationDomain(QByteArrayLiteral("neochat"));
|
||||||
|
auto accountManager = new AccountManager(true);
|
||||||
|
QSignalSpy spy(accountManager, &AccountManager::connectionAdded);
|
||||||
|
connection = dynamic_cast<NeoChatConnection *>(accountManager->accounts()->front());
|
||||||
|
QVERIFY(connection);
|
||||||
|
auto roomId = server.createRoom(u"@user:localhost:1234"_s);
|
||||||
|
|
||||||
|
QSignalSpy syncSpy(connection, &Connection::syncDone);
|
||||||
|
// We need to wait for two syncs, as the next one won't have the changes yet
|
||||||
|
QVERIFY(syncSpy.wait());
|
||||||
|
QVERIFY(syncSpy.wait());
|
||||||
|
room = dynamic_cast<NeoChatRoom *>(connection->room(roomId));
|
||||||
|
QVERIFY(room);
|
||||||
|
RoomManager::instance().setConnection(connection);
|
||||||
|
QSignalSpy roomSpy(&RoomManager::instance(), &RoomManager::currentRoomChanged);
|
||||||
|
RoomManager::instance().resolveResource(room->id());
|
||||||
|
QVERIFY(roomSpy.size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoomManagerTest::testMaximizeMedia()
|
||||||
|
{
|
||||||
|
QSignalSpy spy(&RoomManager::instance(), &RoomManager::showMaximizedMedia);
|
||||||
|
QSignalSpy syncSpy(connection, &Connection::syncDone);
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtMsgType::QtWarningMsg, "Tried to open media for empty event id");
|
||||||
|
RoomManager::instance().maximizeMedia(QString());
|
||||||
|
QVERIFY(!spy.wait(10));
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtMsgType::QtWarningMsg, "Tried to open media for unknown event id \"Doesn't exist\"");
|
||||||
|
RoomManager::instance().maximizeMedia(u"Doesn't exist"_s);
|
||||||
|
QVERIFY(!spy.wait(10));
|
||||||
|
|
||||||
|
const auto eventWithoutMedia = server.sendEvent(room->id(),
|
||||||
|
u"m.room.message"_s,
|
||||||
|
QJsonObject({
|
||||||
|
{u"body"_s, u"Foo"_s},
|
||||||
|
{u"format"_s, u"org.matrix.custom.html"_s},
|
||||||
|
{u"formatted_body"_s, u"Foo"_s},
|
||||||
|
{u"msgtype"_s, u"m.text"_s},
|
||||||
|
}));
|
||||||
|
QVERIFY(syncSpy.wait());
|
||||||
|
QVERIFY(syncSpy.wait());
|
||||||
|
QTest::ignoreMessage(QtMsgType::QtWarningMsg, u"Tried to open media for unknown event id \"%1\""_s.arg(eventWithoutMedia).toLatin1().data());
|
||||||
|
RoomManager::instance().maximizeMedia(eventWithoutMedia);
|
||||||
|
QVERIFY(!spy.wait(10));
|
||||||
|
|
||||||
|
// NOTE: This is supposed to test that maximizing pending media works correctly. This probably doesn't work in the UI yet, but at least the backend supports
|
||||||
|
// it. If the server ever learns how to process events, this becomes pointless and we need to find a way of preventing *these* events from arriving
|
||||||
|
auto pendingEventWithoutMedia = room->postText(u"Hello"_s);
|
||||||
|
QTest::ignoreMessage(QtMsgType::QtWarningMsg, u"Tried to open media for unknown event id \"%1\""_s.arg(pendingEventWithoutMedia).toLatin1().data());
|
||||||
|
RoomManager::instance().maximizeMedia(pendingEventWithoutMedia);
|
||||||
|
QVERIFY(!spy.wait(10));
|
||||||
|
|
||||||
|
const auto eventWithMedia = server.sendEvent(room->id(),
|
||||||
|
u"m.room.message"_s,
|
||||||
|
QJsonObject({
|
||||||
|
{u"body"_s, u"Foo"_s},
|
||||||
|
{u"filename"_s, u"foo.jpg"_s},
|
||||||
|
{u"info"_s,
|
||||||
|
QJsonObject{
|
||||||
|
{u"h"_s, 1000},
|
||||||
|
{u"w"_s, 2000},
|
||||||
|
{u"size"_s, 10000},
|
||||||
|
{u"mimetype"_s, u"image/png"_s},
|
||||||
|
}},
|
||||||
|
{u"msgtype"_s, u"m.image"_s},
|
||||||
|
{u"url"_s, u"mxc://foo.bar/asdf"_s},
|
||||||
|
}));
|
||||||
|
QVERIFY(syncSpy.wait());
|
||||||
|
QVERIFY(syncSpy.wait());
|
||||||
|
QVERIFY(syncSpy.wait());
|
||||||
|
RoomManager::instance().maximizeMedia(eventWithMedia);
|
||||||
|
QVERIFY(spy.size() == 1);
|
||||||
|
QVERIFY(spy[0][0] == 0);
|
||||||
|
|
||||||
|
auto pendingEventWithMedia = room->postJson(u"m.room.message"_s,
|
||||||
|
QJsonObject({
|
||||||
|
{u"body"_s, u"Foo"_s},
|
||||||
|
{u"filename"_s, u"foo.jpg"_s},
|
||||||
|
{u"info"_s,
|
||||||
|
QJsonObject{
|
||||||
|
{u"h"_s, 1000},
|
||||||
|
{u"w"_s, 2000},
|
||||||
|
{u"size"_s, 10000},
|
||||||
|
{u"mimetype"_s, u"image/png"_s},
|
||||||
|
}},
|
||||||
|
{u"msgtype"_s, u"m.image"_s},
|
||||||
|
{u"url"_s, u"mxc://foo.bar/asdf"_s},
|
||||||
|
}));
|
||||||
|
RoomManager::instance().maximizeMedia(pendingEventWithMedia);
|
||||||
|
QVERIFY(spy.size() == 2);
|
||||||
|
QVERIFY(spy[1][0] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(RoomManagerTest)
|
||||||
|
#include "roommanagertest.moc"
|
||||||
274
autotests/server.cpp
Normal file
274
autotests/server.cpp
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 Tobias Fella <tobias.fella@kde.org>
|
||||||
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QHttpServer>
|
||||||
|
#include <QHttpServerResponder>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QSslCertificate>
|
||||||
|
#include <QSslKey>
|
||||||
|
#include <QSslServer>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
|
#include <Quotient/networkaccessmanager.h>
|
||||||
|
|
||||||
|
using namespace Qt::Literals::StringLiterals;
|
||||||
|
|
||||||
|
QString generateEventId()
|
||||||
|
{
|
||||||
|
return u"$"_s + QString::fromLatin1(QCryptographicHash::hash(QUuid::createUuid().toString().toLatin1(), QCryptographicHash::Sha1).toBase64());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString generateRoomId()
|
||||||
|
{
|
||||||
|
return u"!%1:localhost:1234"_s
|
||||||
|
.arg(QString::fromLatin1(QCryptographicHash::hash(QUuid::createUuid().toString().toLatin1(), QCryptographicHash::Sha1).toBase64()))
|
||||||
|
.replace(u'/', QChar());
|
||||||
|
}
|
||||||
|
|
||||||
|
Server::Server()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::start()
|
||||||
|
{
|
||||||
|
QObject::connect(Quotient::NetworkAccessManager::instance(),
|
||||||
|
&QNetworkAccessManager::sslErrors,
|
||||||
|
Quotient::NetworkAccessManager::instance(),
|
||||||
|
[](QNetworkReply *reply) {
|
||||||
|
reply->ignoreSslErrors();
|
||||||
|
});
|
||||||
|
m_server.route(u"/.well-known/matrix/client"_s, QHttpServerRequest::Method::Get, [](QHttpServerResponder &responder) {
|
||||||
|
responder.write(QJsonDocument(QJsonObject{
|
||||||
|
{u"m.homeserver"_s, QJsonObject{{u"base_url"_s, u"https://localhost:1234"_s}}},
|
||||||
|
}),
|
||||||
|
QHttpServerResponder::StatusCode::Ok);
|
||||||
|
});
|
||||||
|
m_server.route(u"/_matrix/client/versions"_s, QHttpServerRequest::Method::Get, [](QHttpServerResponder &responder) {
|
||||||
|
responder.write(QJsonDocument(QJsonObject{
|
||||||
|
{u"versions"_s,
|
||||||
|
QJsonArray{
|
||||||
|
u"v1.0"_s,
|
||||||
|
u"v1.1"_s,
|
||||||
|
u"v1.2"_s,
|
||||||
|
u"v1.3"_s,
|
||||||
|
u"v1.4"_s,
|
||||||
|
u"v1.5"_s,
|
||||||
|
u"v1.6"_s,
|
||||||
|
u"v1.7"_s,
|
||||||
|
u"v1.8"_s,
|
||||||
|
u"v1.9"_s,
|
||||||
|
u"v1.10"_s,
|
||||||
|
u"v1.11"_s,
|
||||||
|
u"v1.12"_s,
|
||||||
|
u"v1.13"_s,
|
||||||
|
}},
|
||||||
|
}),
|
||||||
|
QHttpServerResponder::StatusCode::Ok);
|
||||||
|
});
|
||||||
|
m_server.route(u"/_matrix/client/v3/capabilities"_s, QHttpServerRequest::Method::Get, [](QHttpServerResponder &responder) {
|
||||||
|
responder.write(
|
||||||
|
QJsonDocument(QJsonObject{{u"capabilities"_s,
|
||||||
|
QJsonObject{
|
||||||
|
{u"m.room_versions"_s, QJsonObject{{u"m.available"_s, QJsonObject{{u"1"_s, u"stable"_s}}}, {u"default"_s, u"1"_s}}},
|
||||||
|
}}}),
|
||||||
|
QHttpServerResponder::StatusCode::Ok);
|
||||||
|
});
|
||||||
|
m_server.route(u"/_matrix/client/v3/account/whoami"_s, QHttpServerRequest::Method::Get, [](QHttpServerResponder &responder) {
|
||||||
|
responder.write(QJsonDocument(QJsonObject{
|
||||||
|
{u"device_id"_s, u"device_id_1234"_s},
|
||||||
|
{u"user_id"_s, u"@user:localhost:1234"_s},
|
||||||
|
}),
|
||||||
|
QHttpServerResponder::StatusCode::Ok);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_server.route(u"/_matrix/client/v3/login"_s, QHttpServerRequest::Method::Post, [](QHttpServerResponder &responder) {
|
||||||
|
// TODO
|
||||||
|
// if data["identifier"]["user"] != "user" or data["password"] != "1234":
|
||||||
|
// abort(403)
|
||||||
|
responder.write(QJsonDocument(QJsonObject{
|
||||||
|
{u"access_token"_s, u"token_login"_s},
|
||||||
|
{u"device_id"_s, u"device_1234"_s},
|
||||||
|
{u"user_id"_s, u"@user:localhost:1234"_s},
|
||||||
|
}),
|
||||||
|
QHttpServerResponder::StatusCode::Ok);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_server.route(u"/_matrix/client/v3/login"_s, QHttpServerRequest::Method::Get, [](QHttpServerResponder &responder) {
|
||||||
|
responder.write(QJsonDocument(QJsonObject{
|
||||||
|
{u"flows"_s, QJsonArray{QJsonObject{{u"type"_s, u"m.login.password"_s}}}},
|
||||||
|
}),
|
||||||
|
QHttpServerResponder::StatusCode::Ok);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_server.route(u"/_matrix/client/v3/rooms/<arg>/invite"_s,
|
||||||
|
QHttpServerRequest::Method::Post,
|
||||||
|
[this](const QString &roomId, QHttpServerResponder &responder, const QHttpServerRequest &request) {
|
||||||
|
m_invitedUsers[roomId] += QJsonDocument::fromJson(request.body()).object()[u"user_id"_s].toString();
|
||||||
|
responder.write(QJsonDocument(QJsonObject{}), QHttpServerResponder::StatusCode::Ok);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_server.route(u"/_matrix/client/r0/sync"_s, QHttpServerRequest::Method::Get, [this](QHttpServerResponder &responder) {
|
||||||
|
QMap<QString, QJsonArray> stateEvents;
|
||||||
|
QMap<QString, QJsonArray> roomAccountData;
|
||||||
|
|
||||||
|
for (const auto &roomData : m_roomsToCreate) {
|
||||||
|
stateEvents[roomData.id] += QJsonObject{
|
||||||
|
{u"content"_s, QJsonObject{{u"room_version"_s, u"11"_s}}},
|
||||||
|
{u"event_id"_s, generateEventId()},
|
||||||
|
{u"origin_server_ts"_s, QDateTime::currentMSecsSinceEpoch()},
|
||||||
|
{u"room_id"_s, roomData.id},
|
||||||
|
{u"sender"_s, roomData.members[0]},
|
||||||
|
{u"state_key"_s, QString()},
|
||||||
|
{u"type"_s, u"m.room.create"_s},
|
||||||
|
{u"unsigned"_s, QJsonObject{{u"age"_s, 1234}}},
|
||||||
|
};
|
||||||
|
for (const auto &member : roomData.members) {
|
||||||
|
stateEvents[roomData.id] += QJsonObject{
|
||||||
|
{u"content"_s, QJsonObject{{u"displayname"_s, u"User"_s}, {u"membership"_s, u"join"_s}}},
|
||||||
|
{u"event_id"_s, generateEventId()},
|
||||||
|
{u"origin_server_ts"_s, QDateTime::currentMSecsSinceEpoch()},
|
||||||
|
{u"room_id"_s, roomData.id},
|
||||||
|
{u"sender"_s, member},
|
||||||
|
{u"state_key"_s, member},
|
||||||
|
{u"type"_s, u"m.room.member"_s},
|
||||||
|
{u"unsigned"_s, QJsonObject{{u"age"_s, 1234}}},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
QJsonObject tags;
|
||||||
|
for (const auto &tag : roomData.tags) {
|
||||||
|
tags[tag] = QJsonObject();
|
||||||
|
}
|
||||||
|
roomAccountData[roomData.id] += QJsonObject{{u"type"_s, u"m.tag"_s}, {u"content"_s, QJsonObject{{u"tags"_s, tags}}}};
|
||||||
|
}
|
||||||
|
m_roomsToCreate.clear();
|
||||||
|
for (const auto &roomId : m_invitedUsers.keys()) {
|
||||||
|
const auto &values = m_invitedUsers[roomId];
|
||||||
|
for (const auto &value : values) {
|
||||||
|
stateEvents[roomId] += QJsonObject{
|
||||||
|
{u"content"_s, QJsonObject{{u"displayname"_s, u"User"_s}, {u"membership"_s, u"invite"_s}}},
|
||||||
|
{u"event_id"_s, generateEventId()},
|
||||||
|
{u"origin_server_ts"_s, QDateTime::currentMSecsSinceEpoch()},
|
||||||
|
{u"room_id"_s, roomId},
|
||||||
|
{u"sender"_s, u"@user:localhost:1234"_s},
|
||||||
|
{u"state_key"_s, value},
|
||||||
|
{u"type"_s, u"m.room.member"_s},
|
||||||
|
{u"unsigned"_s, QJsonObject{{u"age"_s, 1234}}},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_invitedUsers.clear();
|
||||||
|
|
||||||
|
for (const auto &roomId : m_bannedUsers.keys()) {
|
||||||
|
const auto &values = m_bannedUsers[roomId];
|
||||||
|
for (const auto &value : values) {
|
||||||
|
stateEvents[roomId] += QJsonObject{
|
||||||
|
{u"content"_s, QJsonObject{{u"displayname"_s, u"User"_s}, {u"membership"_s, u"ban"_s}}},
|
||||||
|
{u"event_id"_s, generateEventId()},
|
||||||
|
{u"origin_server_ts"_s, QDateTime::currentMSecsSinceEpoch()},
|
||||||
|
{u"room_id"_s, roomId},
|
||||||
|
{u"sender"_s, u"@user:localhost:1234"_s},
|
||||||
|
{u"state_key"_s, value},
|
||||||
|
{u"type"_s, u"m.room.member"_s},
|
||||||
|
{u"unsigned"_s, QJsonObject{{u"age"_s, 1234}}},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_bannedUsers.clear();
|
||||||
|
|
||||||
|
for (const auto &roomId : m_joinedUsers.keys()) {
|
||||||
|
const auto &values = m_joinedUsers[roomId];
|
||||||
|
for (const auto &value : values) {
|
||||||
|
stateEvents[roomId] += QJsonObject{
|
||||||
|
{u"content"_s, QJsonObject{{u"displayname"_s, u"User"_s}, {u"membership"_s, u"join"_s}}},
|
||||||
|
{u"event_id"_s, generateEventId()},
|
||||||
|
{u"origin_server_ts"_s, QDateTime::currentMSecsSinceEpoch()},
|
||||||
|
{u"room_id"_s, roomId},
|
||||||
|
{u"sender"_s, u"@user:localhost:1234"_s},
|
||||||
|
{u"state_key"_s, value},
|
||||||
|
{u"type"_s, u"m.room.member"_s},
|
||||||
|
{u"unsigned"_s, QJsonObject{{u"age"_s, 1234}}},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_joinedUsers.clear();
|
||||||
|
|
||||||
|
QJsonObject rooms;
|
||||||
|
auto keys = stateEvents.keys() + m_events.keys();
|
||||||
|
for (const auto &roomId : QSet(keys.begin(), keys.end())) {
|
||||||
|
rooms[roomId] = QJsonObject{
|
||||||
|
{u"state"_s, QJsonObject{{u"events"_s, stateEvents[roomId]}}},
|
||||||
|
{u"account_data"_s, QJsonObject{{u"events"_s, roomAccountData[roomId]}}},
|
||||||
|
{u"timeline"_s, QJsonObject{{u"events"_s, m_events[roomId]}}},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
m_events.clear();
|
||||||
|
|
||||||
|
auto json = QJsonObject{{u"rooms"_s, QJsonObject{{u"join"_s, rooms}}}};
|
||||||
|
responder.write(QJsonDocument(json), QHttpServerResponder::StatusCode::Ok);
|
||||||
|
});
|
||||||
|
|
||||||
|
QSslConfiguration config;
|
||||||
|
QFile key(QStringLiteral(DATA_DIR) + u"/localhost.key"_s);
|
||||||
|
key.open(QFile::ReadOnly);
|
||||||
|
config.setPrivateKey(QSslKey(&key, QSsl::Rsa));
|
||||||
|
config.setLocalCertificate(QSslCertificate::fromPath(QStringLiteral(DATA_DIR) + u"/localhost.crt"_s).front());
|
||||||
|
m_sslServer.setSslConfiguration(config);
|
||||||
|
if (!m_sslServer.listen(QHostAddress::LocalHost, 1234) || !m_server.bind(&m_sslServer)) {
|
||||||
|
qFatal() << "Server failed to listen on a port.";
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
qWarning() << "Server listening";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Server::createRoom(const QString &matrixId)
|
||||||
|
{
|
||||||
|
auto roomId = generateRoomId();
|
||||||
|
m_roomsToCreate += RoomData{
|
||||||
|
.members = {matrixId},
|
||||||
|
.id = roomId,
|
||||||
|
.tags = {},
|
||||||
|
};
|
||||||
|
return roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::inviteUser(const QString &roomId, const QString &matrixId)
|
||||||
|
{
|
||||||
|
m_invitedUsers[roomId] += matrixId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::banUser(const QString &roomId, const QString &matrixId)
|
||||||
|
{
|
||||||
|
m_bannedUsers[roomId] += matrixId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::joinUser(const QString &roomId, const QString &matrixId)
|
||||||
|
{
|
||||||
|
m_joinedUsers[roomId] += matrixId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Server::createServerNoticesRoom(const QString &matrixId)
|
||||||
|
{
|
||||||
|
auto roomId = createRoom(matrixId);
|
||||||
|
m_roomsToCreate.last().tags = {u"m.server_notice"_s};
|
||||||
|
return roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Server::sendEvent(const QString &roomId, const QString &eventType, const QJsonObject &content)
|
||||||
|
{
|
||||||
|
const auto eventId = generateEventId();
|
||||||
|
m_events[roomId] += QJsonObject{
|
||||||
|
{u"type"_s, eventType},
|
||||||
|
{u"content"_s, content},
|
||||||
|
{u"sender"_s, u"@foo:server.com"_s},
|
||||||
|
{u"event_id"_s, eventId},
|
||||||
|
{u"origin_server_ts"_s, QDateTime::currentMSecsSinceEpoch()},
|
||||||
|
};
|
||||||
|
return eventId;
|
||||||
|
}
|
||||||
46
autotests/server.h
Normal file
46
autotests/server.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 Tobias Fella <tobias.fella@kde.org>
|
||||||
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <QHttpServer>
|
||||||
|
#include <QSslServer>
|
||||||
|
|
||||||
|
struct RoomData {
|
||||||
|
QStringList members;
|
||||||
|
QString id;
|
||||||
|
QStringList tags;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Server
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Server();
|
||||||
|
|
||||||
|
void start();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a room and place the user with id matrixId in it.
|
||||||
|
* Returns the room's id
|
||||||
|
*/
|
||||||
|
QString createRoom(const QString &matrixId);
|
||||||
|
|
||||||
|
void inviteUser(const QString &roomId, const QString &matrixId);
|
||||||
|
void banUser(const QString &roomId, const QString &matrixId);
|
||||||
|
void joinUser(const QString &roomId, const QString &matrixId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a server notices room.
|
||||||
|
*/
|
||||||
|
QString createServerNoticesRoom(const QString &matrixId);
|
||||||
|
QString sendEvent(const QString &roomId, const QString &eventType, const QJsonObject &content);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHttpServer m_server;
|
||||||
|
QSslServer m_sslServer;
|
||||||
|
|
||||||
|
QHash<QString, QList<QString>> m_invitedUsers;
|
||||||
|
QHash<QString, QList<QString>> m_bannedUsers;
|
||||||
|
QHash<QString, QList<QString>> m_joinedUsers;
|
||||||
|
|
||||||
|
QList<RoomData> m_roomsToCreate;
|
||||||
|
QMap<QString, QJsonArray> m_events;
|
||||||
|
};
|
||||||
@@ -31,7 +31,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (!syncFileName.isEmpty()) {
|
if (!syncFileName.isEmpty()) {
|
||||||
QFile testSyncFile;
|
QFile testSyncFile;
|
||||||
testSyncFile.setFileName(QLatin1String(DATA_DIR) + u'/' + syncFileName);
|
testSyncFile.setFileName(QStringLiteral(DATA_DIR) + u'/' + syncFileName);
|
||||||
testSyncFile.open(QIODevice::ReadOnly);
|
testSyncFile.open(QIODevice::ReadOnly);
|
||||||
const auto testSyncJson = QJsonDocument::fromJson(testSyncFile.readAll());
|
const auto testSyncJson = QJsonDocument::fromJson(testSyncFile.readAll());
|
||||||
Quotient::SyncRoomData roomData(id(), Quotient::JoinState::Join, testSyncJson.object());
|
Quotient::SyncRoomData roomData(id(), Quotient::JoinState::Join, testSyncJson.object());
|
||||||
@@ -45,7 +45,7 @@ inline Quotient::event_ptr_tt<EventT> loadEventFromFile(const QString &eventFile
|
|||||||
{
|
{
|
||||||
if (!eventFileName.isEmpty()) {
|
if (!eventFileName.isEmpty()) {
|
||||||
QFile testEventFile;
|
QFile testEventFile;
|
||||||
testEventFile.setFileName(QLatin1String(DATA_DIR) + u'/' + eventFileName);
|
testEventFile.setFileName(QStringLiteral(DATA_DIR) + u'/' + eventFileName);
|
||||||
testEventFile.open(QIODevice::ReadOnly);
|
testEventFile.open(QIODevice::ReadOnly);
|
||||||
auto testSyncJson = QJsonDocument::fromJson(testEventFile.readAll()).object();
|
auto testSyncJson = QJsonDocument::fromJson(testEventFile.readAll()).object();
|
||||||
return Quotient::loadEvent<EventT>(testSyncJson);
|
return Quotient::loadEvent<EventT>(testSyncJson);
|
||||||
|
|||||||
@@ -8,11 +8,12 @@
|
|||||||
|
|
||||||
#include <Quotient/quotient_common.h>
|
#include <Quotient/quotient_common.h>
|
||||||
#include <Quotient/syncdata.h>
|
#include <Quotient/syncdata.h>
|
||||||
#include <qnamespace.h>
|
|
||||||
|
|
||||||
|
#include <Kirigami/Platform/PlatformTheme>
|
||||||
|
|
||||||
|
#include "enums/messagecomponenttype.h"
|
||||||
#include "models/customemojimodel.h"
|
#include "models/customemojimodel.h"
|
||||||
#include "neochatconnection.h"
|
#include "neochatconnection.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#include "testutils.h"
|
#include "testutils.h"
|
||||||
|
|
||||||
@@ -33,7 +34,6 @@ private Q_SLOTS:
|
|||||||
void stripDisallowedTags();
|
void stripDisallowedTags();
|
||||||
void stripDisallowedAttributes();
|
void stripDisallowedAttributes();
|
||||||
void emptyCodeTags();
|
void emptyCodeTags();
|
||||||
void formatBlockQuote();
|
|
||||||
|
|
||||||
void sendSimpleStringCase();
|
void sendSimpleStringCase();
|
||||||
void sendSingleParaMarkup();
|
void sendSingleParaMarkup();
|
||||||
@@ -44,7 +44,10 @@ private Q_SLOTS:
|
|||||||
void sendCustomEmoji();
|
void sendCustomEmoji();
|
||||||
void sendCustomEmojiCode_data();
|
void sendCustomEmojiCode_data();
|
||||||
void sendCustomEmojiCode();
|
void sendCustomEmojiCode();
|
||||||
|
void sendCustomTags_data();
|
||||||
|
void sendCustomTags();
|
||||||
|
|
||||||
|
void receiveSpacelessSelfClosingTag();
|
||||||
void receiveStripReply();
|
void receiveStripReply();
|
||||||
void receivePlainTextIn();
|
void receivePlainTextIn();
|
||||||
|
|
||||||
@@ -58,35 +61,39 @@ private Q_SLOTS:
|
|||||||
void receiveRichStrikethrough();
|
void receiveRichStrikethrough();
|
||||||
void receiveRichtextIn();
|
void receiveRichtextIn();
|
||||||
void receiveRichMxcUrl();
|
void receiveRichMxcUrl();
|
||||||
|
void receiveRichPlainUrl_data();
|
||||||
void receiveRichPlainUrl();
|
void receiveRichPlainUrl();
|
||||||
void receiveRichEmote();
|
|
||||||
void receiveRichEdited_data();
|
void receiveRichEdited_data();
|
||||||
void receiveRichEdited();
|
void receiveRichEdited();
|
||||||
void receiveLineSeparator();
|
void receiveLineSeparator();
|
||||||
void receiveRichCodeUrl();
|
void receiveRichCodeUrl();
|
||||||
|
void receiveRichColor();
|
||||||
|
|
||||||
|
void componentOutput_data();
|
||||||
|
void componentOutput();
|
||||||
};
|
};
|
||||||
|
|
||||||
void TextHandlerTest::initTestCase()
|
void TextHandlerTest::initTestCase()
|
||||||
{
|
{
|
||||||
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
|
connection = Connection::makeMockConnection(u"@bob:kde.org"_s);
|
||||||
connection->setAccountData("im.ponies.user_emotes"_ls,
|
connection->setAccountData(u"im.ponies.user_emotes"_s,
|
||||||
QJsonObject{{"images"_ls,
|
QJsonObject{{"images"_L1,
|
||||||
QJsonObject{{"test"_ls,
|
QJsonObject{{"test"_L1,
|
||||||
QJsonObject{{"body"_ls, "Test custom emoji"_ls},
|
QJsonObject{{"body"_L1, "Test custom emoji"_L1},
|
||||||
{"url"_ls, "mxc://example.org/test"_ls},
|
{"url"_L1, "mxc://example.org/test"_L1},
|
||||||
{"usage"_ls, QJsonArray{"emoticon"_ls}}}}}}});
|
{"usage"_L1, QJsonArray{"emoticon"_L1}}}}}}});
|
||||||
CustomEmojiModel::instance().setConnection(static_cast<NeoChatConnection *>(connection));
|
CustomEmojiModel::instance().setConnection(static_cast<NeoChatConnection *>(connection));
|
||||||
|
|
||||||
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-texthandler-sync.json"));
|
room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, u"test-texthandler-sync.json"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextHandlerTest::allowedAttributes()
|
void TextHandlerTest::allowedAttributes()
|
||||||
{
|
{
|
||||||
const QString testInputString1 = QStringLiteral("<p><span data-mx-spoiler><font color=#FFFFFF>Test</font><span></p>");
|
const QString testInputString1 = u"<span data-mx-spoiler><font color=#FFFFFF>Test</font><span>"_s;
|
||||||
const QString testOutputString1 = QStringLiteral("<p><span data-mx-spoiler><font color=#FFFFFF>Test</font><span></p>");
|
const QString testOutputString1 = u"<span data-mx-spoiler><font color=#FFFFFF>Test</font><span>"_s;
|
||||||
// Handle urls where the href has either single (') or double (") quotes.
|
// 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 testInputString2 = u"<a href=\"https://kde.org\">link</a><a href='https://kde.org'>link</a>"_s;
|
||||||
const QString testOutputString2 = QStringLiteral("<p><a href=\"https://kde.org\">link</a><a href='https://kde.org'>link</a></p>");
|
const QString testOutputString2 = u"<a href=\"https://kde.org\">link</a><a href='https://kde.org'>link</a>"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString1);
|
testTextHandler.setData(testInputString1);
|
||||||
@@ -101,8 +108,8 @@ void TextHandlerTest::allowedAttributes()
|
|||||||
|
|
||||||
void TextHandlerTest::stripDisallowedTags()
|
void TextHandlerTest::stripDisallowedTags()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("<p>Allowed</p> <span>Allowed</span> <body>Disallowed</body>");
|
const QString testInputString = u"<p>Allowed</p> <span>Allowed</span> <body>Disallowed</body>"_s;
|
||||||
const QString testOutputString = QStringLiteral("<p>Allowed</p> <span>Allowed</span> Disallowed");
|
const QString testOutputString = u"<p>Allowed</p> <span>Allowed</span> Disallowed"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -113,8 +120,8 @@ void TextHandlerTest::stripDisallowedTags()
|
|||||||
|
|
||||||
void TextHandlerTest::stripDisallowedAttributes()
|
void TextHandlerTest::stripDisallowedAttributes()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("<p style=\"font-size:50px;\" color=#FFFFFF>Test</p>");
|
const QString testInputString = u"<p style=\"font-size:50px;\" color=#FFFFFF>Test</p>"_s;
|
||||||
const QString testOutputString = QStringLiteral("<p>Test</p>");
|
const QString testOutputString = u"Test"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -129,8 +136,8 @@ void TextHandlerTest::stripDisallowedAttributes()
|
|||||||
*/
|
*/
|
||||||
void TextHandlerTest::emptyCodeTags()
|
void TextHandlerTest::emptyCodeTags()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("<pre><code></code></pre>");
|
const QString testInputString = u"<pre><code></code></pre>"_s;
|
||||||
const QString testOutputString = QStringLiteral("<pre><code></code></pre>");
|
const QString testOutputString = u"<pre><code></code></pre>"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -139,20 +146,10 @@ void TextHandlerTest::emptyCodeTags()
|
|||||||
QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
|
QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextHandlerTest::formatBlockQuote()
|
|
||||||
{
|
|
||||||
auto input = QStringLiteral("<blockquote>\n<p>Lorem Ispum</p>\n</blockquote>");
|
|
||||||
auto expectedOutput = QStringLiteral("<blockquote><table><tr><td>\u201CLorem Ispum\u201D</td></tr></table></blockquote>");
|
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
|
||||||
testTextHandler.setData(input);
|
|
||||||
QCOMPARE(testTextHandler.handleRecieveRichText(), expectedOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextHandlerTest::sendSimpleStringCase()
|
void TextHandlerTest::sendSimpleStringCase()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("This data should just be put in a paragraph.");
|
const QString testInputString = u"This data should just be left alone."_s;
|
||||||
const QString testOutputString = QStringLiteral("<p>This data should just be put in a paragraph.</p>");
|
const QString testOutputString = u"This data should just be left alone."_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -162,11 +159,10 @@ void TextHandlerTest::sendSimpleStringCase()
|
|||||||
|
|
||||||
void TextHandlerTest::sendSingleParaMarkup()
|
void TextHandlerTest::sendSingleParaMarkup()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral(
|
const QString testInputString =
|
||||||
"Text para with **bold**, *italic*, [link](https://kde.org), , `inline code`.");
|
u"Text para with **bold**, *italic*, [link](https://kde.org), , `inline code`."_s;
|
||||||
const QString testOutputString = QStringLiteral(
|
const QString testOutputString =
|
||||||
"<p>Text para with <strong>bold</strong>, <em>italic</em>, <a href=\"https://kde.org\">link</a>, <img "
|
u"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>."_s;
|
||||||
"src=\"mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e\" alt=\"image\">, <code>inline code</code>.</p>");
|
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -177,11 +173,9 @@ void TextHandlerTest::sendSingleParaMarkup()
|
|||||||
void TextHandlerTest::sendMultipleSectionMarkup()
|
void TextHandlerTest::sendMultipleSectionMarkup()
|
||||||
{
|
{
|
||||||
const QString testInputString =
|
const QString testInputString =
|
||||||
QStringLiteral("Text para\n> blockquote\n* List 1\n* List 2\n1. one\n2. two\n# Heading 1\n## Heading 2\nhorizontal rule\n\n---\n```\ncodeblock\n```");
|
u"Text para\n> blockquote\n* List 1\n* List 2\n1. one\n2. two\n# Heading 1\n## Heading 2\nhorizontal rule\n\n---\n```\ncodeblock\n```"_s;
|
||||||
const QString testOutputString = QStringLiteral(
|
const QString testOutputString =
|
||||||
"<p>Text para</p>\n<blockquote>\n<p>blockquote</p>\n</blockquote>\n<ul>\n<li>List 1</li>\n<li>List "
|
u"<p>Text para</p>\n<blockquote>\n<p>blockquote</p>\n</blockquote>\n<ul>\n<li>List 1</li>\n<li>List 2</li>\n</ul>\n<ol>\n<li>one</li>\n<li>two</li>\n</ol>\n<h1>Heading 1</h1>\n<h2>Heading 2</h2>\n<p>horizontal rule</p>\n<hr>\n<pre><code>codeblock\n</code></pre>"_s;
|
||||||
"2</li>\n</ul>\n<ol>\n<li>one</li>\n<li>two</li>\n</ol>\n<h1>Heading 1</h1>\n<h2>Heading 2</h2>\n<p>horizontal "
|
|
||||||
"rule</p>\n<hr>\n<pre><code>codeblock\n</code></pre>");
|
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -191,8 +185,8 @@ void TextHandlerTest::sendMultipleSectionMarkup()
|
|||||||
|
|
||||||
void TextHandlerTest::sendBadLinks()
|
void TextHandlerTest::sendBadLinks()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("[link](kde.org), ");
|
const QString testInputString = u"[link](kde.org), "_s;
|
||||||
const QString testOutputString = QStringLiteral("<p><a>link</a>, <img alt=\"image\"></p>");
|
const QString testOutputString = u"<a>link</a>, <img alt=\"image\">"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -205,9 +199,9 @@ void TextHandlerTest::sendBadLinks()
|
|||||||
*/
|
*/
|
||||||
void TextHandlerTest::sendEscapeCode()
|
void TextHandlerTest::sendEscapeCode()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("```\n<p>Test <span style=\"font-size:50px;\">some</span> code</p>\n```");
|
const QString testInputString = u"```\n<p>Test <span style=\"font-size:50px;\">some</span> code</p>\n```"_s;
|
||||||
const QString testOutputString =
|
const QString testOutputString =
|
||||||
QStringLiteral("<pre><code><p>Test <span style="font-size:50px;">some</span> code</p>\n</code></pre>");
|
u"<pre><code><p>Test <span style="font-size:50px;">some</span> code</p>\n</code></pre>"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -217,8 +211,8 @@ void TextHandlerTest::sendEscapeCode()
|
|||||||
|
|
||||||
void TextHandlerTest::sendCodeClass()
|
void TextHandlerTest::sendCodeClass()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("```html\nsome code\n```\n<pre><code class=\"code-underline\">some more code</code></pre>");
|
const QString testInputString = u"```html\nsome code\n```\n<pre><code class=\"code-underline\">some more code</code></pre>"_s;
|
||||||
const QString testOutputString = QStringLiteral("<pre><code class=\"language-html\">some code\n</code></pre>\n<pre><code>some more code</code></pre>");
|
const QString testOutputString = u"<pre><code class=\"language-html\">some code\n</code></pre>\n<pre><code>some more code</code></pre>"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -228,9 +222,9 @@ void TextHandlerTest::sendCodeClass()
|
|||||||
|
|
||||||
void TextHandlerTest::sendCustomEmoji()
|
void TextHandlerTest::sendCustomEmoji()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral(":test:");
|
const QString testInputString = u":test:"_s;
|
||||||
const QString testOutputString = QStringLiteral(
|
const QString testOutputString =
|
||||||
"<p><img data-mx-emoticon=\"\" src=\"mxc://example.org/test\" alt=\":test:\" title=\":test:\" height=\"32\" vertical-align=\"middle\" /></p>");
|
u"<img data-mx-emoticon=\"\" src=\"mxc://example.org/test\" alt=\":test:\" title=\":test:\" height=\"32\" vertical-align=\"middle\" />"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -243,8 +237,8 @@ void TextHandlerTest::sendCustomEmojiCode_data()
|
|||||||
QTest::addColumn<QString>("testInputString");
|
QTest::addColumn<QString>("testInputString");
|
||||||
QTest::addColumn<QString>("testOutputString");
|
QTest::addColumn<QString>("testOutputString");
|
||||||
|
|
||||||
QTest::newRow("inline") << QStringLiteral("`:test:`") << QStringLiteral("<p><code>:test:</code></p>");
|
QTest::newRow("inline") << u"`:test:`"_s << u"<code>:test:</code>"_s;
|
||||||
QTest::newRow("block") << QStringLiteral("```\n:test:\n```") << QStringLiteral("<pre><code>:test:\n</code></pre>");
|
QTest::newRow("block") << u"```\n:test:\n```"_s << u"<pre><code>:test:\n</code></pre>"_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom emojis in code blocks should be left alone.
|
// Custom emojis in code blocks should be left alone.
|
||||||
@@ -259,12 +253,58 @@ void TextHandlerTest::sendCustomEmojiCode()
|
|||||||
QCOMPARE(testTextHandler.handleSendText(), testOutputString);
|
QCOMPARE(testTextHandler.handleSendText(), testOutputString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextHandlerTest::sendCustomTags_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("testInputString");
|
||||||
|
QTest::addColumn<QString>("testOutputString");
|
||||||
|
|
||||||
|
// spoiler
|
||||||
|
QTest::newRow("incomplete spoiler") << u"||test"_s << u"||test"_s;
|
||||||
|
QTest::newRow("complete spoiler") << u"||test||"_s << u"<span data-mx-spoiler>test</span>"_s;
|
||||||
|
QTest::newRow("multiple spoiler") << u"||apple||banana||pear||"_s << u"<span data-mx-spoiler>apple</span>banana<span data-mx-spoiler>pear</span>"_s;
|
||||||
|
QTest::newRow("inside code block spoiler") << u"```||apple||```"_s << u"<code>||apple||</code>"_s;
|
||||||
|
QTest::newRow("outside code block spoiler") << u"||apple|| ```||banana||``` ||pear||"_s
|
||||||
|
<< u"<span data-mx-spoiler>apple</span> <code>||banana||</code> <span data-mx-spoiler>pear</span>"_s;
|
||||||
|
QTest::newRow("complex spoiler") << u"Between `formFactor == Horizontal||Vertical` and `location == top||left||bottom||right`"_s
|
||||||
|
<< u"Between <code>formFactor == Horizontal||Vertical</code> and <code>location == top||left||bottom||right</code>"_s;
|
||||||
|
|
||||||
|
// strikethrough
|
||||||
|
QTest::newRow("incomplete strikethrough") << u"~~test"_s << u"~~test"_s;
|
||||||
|
QTest::newRow("complete strikethrough") << u"~~test~~"_s << u"<del>test</del>"_s;
|
||||||
|
QTest::newRow("inside code block strikethrough") << u"```~~apple~~```"_s << u"<code>~~apple~~</code>"_s;
|
||||||
|
QTest::newRow("outside code block strikethrough") << u"~~apple~~ ```~~banana~~``` ~~pear~~"_s
|
||||||
|
<< u"<del>apple</del> <code>~~banana~~</code> <del>pear</del>"_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextHandlerTest::sendCustomTags()
|
||||||
|
{
|
||||||
|
QFETCH(QString, testInputString);
|
||||||
|
QFETCH(QString, testOutputString);
|
||||||
|
|
||||||
|
TextHandler testTextHandler;
|
||||||
|
testTextHandler.setData(testInputString);
|
||||||
|
|
||||||
|
QCOMPARE(testTextHandler.handleSendText(), testOutputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextHandlerTest::receiveSpacelessSelfClosingTag()
|
||||||
|
{
|
||||||
|
const QString testInputString = u"Test...<br/>...ing"_s;
|
||||||
|
const QString testRichOutputString = u"Test...<br/>...ing"_s;
|
||||||
|
const QString testPlainOutputString = u"Test...\n...ing"_s;
|
||||||
|
|
||||||
|
TextHandler testTextHandler;
|
||||||
|
testTextHandler.setData(testInputString);
|
||||||
|
|
||||||
|
QCOMPARE(testTextHandler.handleRecieveRichText(), testRichOutputString);
|
||||||
|
QCOMPARE(testTextHandler.handleRecievePlainText(Qt::RichText), testPlainOutputString);
|
||||||
|
}
|
||||||
|
|
||||||
void TextHandlerTest::receiveStripReply()
|
void TextHandlerTest::receiveStripReply()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral(
|
const QString testInputString =
|
||||||
"<mx-reply><blockquote><a href=\"https://matrix.to/#/!somewhere:example.org/$event:example.org\">In reply to</a><a "
|
u"<mx-reply><blockquote><a href=\"https://matrix.to/#/!somewhere:example.org/$event:example.org\">In reply to</a><a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a><br />Message replied to.</blockquote></mx-reply>Reply message."_s;
|
||||||
"href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a><br />Message replied to.</blockquote></mx-reply>Reply message.");
|
const QString testOutputString = u"Reply message."_s;
|
||||||
const QString testOutputString = QStringLiteral("Reply message.");
|
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -278,9 +318,10 @@ void TextHandlerTest::receiveRichInPlainOut_data()
|
|||||||
QTest::addColumn<QString>("testInputString");
|
QTest::addColumn<QString>("testInputString");
|
||||||
QTest::addColumn<QString>("testOutputString");
|
QTest::addColumn<QString>("testOutputString");
|
||||||
|
|
||||||
QTest::newRow("ampersand") << QStringLiteral("a & b") << QStringLiteral("a & b");
|
QTest::newRow("ampersand") << u"a & b"_s << u"a & b"_s;
|
||||||
QTest::newRow("quote") << QStringLiteral(""a and b"") << QStringLiteral("\"a and b\"");
|
QTest::newRow("quote") << u""a and b""_s << u"\"a and b\""_s;
|
||||||
QTest::newRow("new line") << QStringLiteral("new<br>line") << QStringLiteral("new\nline");
|
QTest::newRow("new line") << u"new<br>line"_s << u"new\nline"_s;
|
||||||
|
QTest::newRow("unescape") << u"can't"_s << u"can't"_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextHandlerTest::receiveRichInPlainOut()
|
void TextHandlerTest::receiveRichInPlainOut()
|
||||||
@@ -296,13 +337,13 @@ void TextHandlerTest::receiveRichInPlainOut()
|
|||||||
|
|
||||||
void TextHandlerTest::receivePlainTextIn()
|
void TextHandlerTest::receivePlainTextIn()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("<plain text in tag bracket>\nTest link https://kde.org.");
|
const QString testInputString = u"<plain text in tag bracket>\nTest link https://kde.org."_s;
|
||||||
const QString testOutputStringRich = QStringLiteral("<plain text in tag bracket><br>Test link <a href=\"https://kde.org\">https://kde.org</a>.");
|
const QString testOutputStringRich = u"<plain text in tag bracket><br>Test link <a href=\"https://kde.org\">https://kde.org</a>."_s;
|
||||||
QString testOutputStringPlain = QStringLiteral("<plain text in tag bracket>\nTest link https://kde.org.");
|
QString testOutputStringPlain = u"<plain text in tag bracket>\nTest link https://kde.org."_s;
|
||||||
|
|
||||||
// Make sure quotes are maintained in a plain string.
|
// Make sure quotes are maintained in a plain string.
|
||||||
const QString testInputString2 = QStringLiteral("last line is \"Time to switch to a new topic.\"");
|
const QString testInputString2 = u"last line is \"Time to switch to a new topic.\""_s;
|
||||||
const QString testOutputString2 = QStringLiteral("last line is \"Time to switch to a new topic.\"");
|
const QString testOutputString2 = u"last line is \"Time to switch to a new topic.\""_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -317,12 +358,12 @@ void TextHandlerTest::receivePlainTextIn()
|
|||||||
|
|
||||||
void TextHandlerTest::receiveStripNewlines()
|
void TextHandlerTest::receiveStripNewlines()
|
||||||
{
|
{
|
||||||
const QString testInputStringPlain = QStringLiteral("Test\nmany\nnew\nlines.");
|
const QString testInputStringPlain = u"Test\nmany\nnew\nlines."_s;
|
||||||
const QString testInputStringRich = QStringLiteral("Test<br>many<br />new<br>lines.");
|
const QString testInputStringRich = u"Test<br>many<br />new<br>lines."_s;
|
||||||
const QString testOutputString = QStringLiteral("Test many new lines.");
|
const QString testOutputString = u"Test many new lines."_s;
|
||||||
|
|
||||||
const QString testInputStringPlain2 = QStringLiteral("* List\n* Items");
|
const QString testInputStringPlain2 = u"* List\n* Items"_s;
|
||||||
const QString testOutputString2 = QStringLiteral("List Items");
|
const QString testOutputString2 = u"List Items"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputStringPlain);
|
testTextHandler.setData(testInputStringPlain);
|
||||||
@@ -344,8 +385,8 @@ void TextHandlerTest::receiveStripNewlines()
|
|||||||
*/
|
*/
|
||||||
void TextHandlerTest::receivePlainStripHtml()
|
void TextHandlerTest::receivePlainStripHtml()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("<p>Test</p> <pre><code>Some code <strong>with tags</strong></code></pre>");
|
const QString testInputString = u"<p>Test</p> <pre><code>Some code <strong>with tags</strong></code></pre>"_s;
|
||||||
const QString testOutputString = QStringLiteral("Test Some code <strong>with tags</strong>");
|
const QString testOutputString = u"Test Some code <strong>with tags</strong>"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -355,8 +396,8 @@ void TextHandlerTest::receivePlainStripHtml()
|
|||||||
|
|
||||||
void TextHandlerTest::receivePlainStripMarkup()
|
void TextHandlerTest::receivePlainStripMarkup()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("**bold** `<p>inline code</p>` *italic*");
|
const QString testInputString = u"**bold** `<p>inline code</p>` *italic*"_s;
|
||||||
const QString testOutputString = QStringLiteral("bold <p>inline code</p> italic");
|
const QString testOutputString = u"bold <p>inline code</p> italic"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -366,8 +407,8 @@ void TextHandlerTest::receivePlainStripMarkup()
|
|||||||
|
|
||||||
void TextHandlerTest::receiveRichUserPill()
|
void TextHandlerTest::receiveRichUserPill()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("<p><a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a></p>");
|
const QString testInputString = u"<p><a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a></p>"_s;
|
||||||
const QString testOutputString = QStringLiteral("<p><b><a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a></b></p>");
|
const QString testOutputString = u"<b><a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a></b>"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -377,8 +418,8 @@ void TextHandlerTest::receiveRichUserPill()
|
|||||||
|
|
||||||
void TextHandlerTest::receiveRichStrikethrough()
|
void TextHandlerTest::receiveRichStrikethrough()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("<p><del>Test</del></p>");
|
const QString testInputString = u"<p><del>Test</del></p>"_s;
|
||||||
const QString testOutputString = QStringLiteral("<p><s>Test</s></p>");
|
const QString testOutputString = u"<s>Test</s>"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -388,8 +429,8 @@ void TextHandlerTest::receiveRichStrikethrough()
|
|||||||
|
|
||||||
void TextHandlerTest::receiveRichtextIn()
|
void TextHandlerTest::receiveRichtextIn()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral("<p>Test</p> <pre><code>Some code <strong>with tags</strong></code></pre>");
|
const QString testInputString = u"<p>Test</p> <pre><code>Some code <strong>with tags</strong></code></pre>"_s;
|
||||||
const QString testOutputString = QStringLiteral("<p>Test</p> <pre><code>Some code <strong>with tags</strong></code></pre>");
|
const QString testOutputString = u"<p>Test</p> <pre><code>Some code <strong>with tags</strong></code></pre>"_s;
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -399,15 +440,10 @@ void TextHandlerTest::receiveRichtextIn()
|
|||||||
|
|
||||||
void TextHandlerTest::receiveRichMxcUrl()
|
void TextHandlerTest::receiveRichMxcUrl()
|
||||||
{
|
{
|
||||||
const QString testInputString = QStringLiteral(
|
const QString testInputString =
|
||||||
"<img src=\"mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e\" alt=\"image\"><img src=\"mxc://kde.org/34c3464b3a1bd7f55af2d559e07d2c773c430e73\" "
|
u"<img src=\"mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e\" alt=\"image\"><img src=\"mxc://kde.org/34c3464b3a1bd7f55af2d559e07d2c773c430e73\" alt=\"image\">"_s;
|
||||||
"alt=\"image\">");
|
const QString testOutputString =
|
||||||
const QString testOutputString = QStringLiteral(
|
u"<img src=\"mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e?user_id=@bob:kde.org&room_id=%23myroom:kde.org&event_id=$143273582443PhrSn:example.org\" alt=\"image\"><img src=\"mxc://kde.org/34c3464b3a1bd7f55af2d559e07d2c773c430e73?user_id=@bob:kde.org&room_id=%23myroom:kde.org&event_id=$143273582443PhrSn:example.org\" alt=\"image\">"_s;
|
||||||
"<img "
|
|
||||||
"src=\"mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e?user_id=@bob:kde.org&room_id=%23myroom:kde.org&event_id=$143273582443PhrSn:example.org\" "
|
|
||||||
"alt=\"image\"><img "
|
|
||||||
"src=\"mxc://kde.org/34c3464b3a1bd7f55af2d559e07d2c773c430e73?user_id=@bob:kde.org&room_id=%23myroom:kde.org&event_id=$143273582443PhrSn:example.org\" "
|
|
||||||
"alt=\"image\">");
|
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -415,6 +451,32 @@ void TextHandlerTest::receiveRichMxcUrl()
|
|||||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, room->messageEvents().at(0).get()), testOutputString);
|
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, room->messageEvents().at(0).get()), testOutputString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextHandlerTest::receiveRichPlainUrl_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("input");
|
||||||
|
QTest::addColumn<QString>("output");
|
||||||
|
|
||||||
|
// This is an actual link that caused trouble which is why it's so long. Keeping
|
||||||
|
// so we can confirm consistent behaviour for complex urls.
|
||||||
|
QTest::addRow("link 1")
|
||||||
|
<< u"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im <a href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">Link already rich</a>"_s
|
||||||
|
<< u"<a href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im</a> <a href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">Link already rich</a>"_s;
|
||||||
|
|
||||||
|
// Another real case. The linkification wasn't handling it when a single link
|
||||||
|
// contains what looks like and email. It was broken into 3 but needs to
|
||||||
|
// be just single link.
|
||||||
|
QTest::addRow("link 2")
|
||||||
|
<< u"https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/"_s
|
||||||
|
<< u"<a href=\"https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/\">https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/</a>"_s;
|
||||||
|
|
||||||
|
QTest::addRow("email") << uR"(email@example.com <a href="mailto:email@example.com">Link already rich</a>)"_s
|
||||||
|
<< uR"(<a href="mailto:email@example.com">email@example.com</a> <a href="mailto:email@example.com">Link already rich</a>)"_s;
|
||||||
|
QTest::addRow("mxid")
|
||||||
|
<< u"@user:kde.org <a href=\"https://matrix.to/#/@user:kde.org\">Link already rich</a>"_s
|
||||||
|
<< u"<b><a href=\"https://matrix.to/#/@user:kde.org\">@user:kde.org</a></b> <b><a href=\"https://matrix.to/#/@user:kde.org\">Link already rich</a></b>"_s;
|
||||||
|
QTest::addRow("mxid with prefix") << u"a @user:kde.org b"_s << u"a <b><a href=\"https://matrix.to/#/@user:kde.org\">@user:kde.org</a></b> b"_s;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For when your rich input string has a plain text url left in.
|
* For when your rich input string has a plain text url left in.
|
||||||
*
|
*
|
||||||
@@ -423,67 +485,13 @@ void TextHandlerTest::receiveRichMxcUrl()
|
|||||||
*/
|
*/
|
||||||
void TextHandlerTest::receiveRichPlainUrl()
|
void TextHandlerTest::receiveRichPlainUrl()
|
||||||
{
|
{
|
||||||
// This is an actual link that caused trouble which is why it's so long. Keeping
|
QFETCH(QString, input);
|
||||||
// so we can confirm consistent behaviour for complex urls.
|
QFETCH(QString, output);
|
||||||
const QString testInputStringLink1 = QStringLiteral(
|
|
||||||
"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im "
|
|
||||||
"<a "
|
|
||||||
"href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/"
|
|
||||||
"$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">Link already rich</a>");
|
|
||||||
const QString testOutputStringLink1 = QStringLiteral(
|
|
||||||
"<a "
|
|
||||||
"href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/"
|
|
||||||
"$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">https://matrix.to/#/"
|
|
||||||
"!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im</a> <a "
|
|
||||||
"href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/"
|
|
||||||
"$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&via=matrix.org&via=fedora.im\">Link already rich</a>");
|
|
||||||
|
|
||||||
// Another real case. The linkification wasn't handling it when a single link
|
|
||||||
// contains what looks like and email. It was been broken into 3 but needs to
|
|
||||||
// be just single link.
|
|
||||||
const QString testInputStringLink2 = QStringLiteral("https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/");
|
|
||||||
const QString testOutputStringLink2 = QStringLiteral(
|
|
||||||
"<a "
|
|
||||||
"href=\"https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/\">https://lore.kernel.org/lkml/"
|
|
||||||
"CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/</a>");
|
|
||||||
|
|
||||||
QString testInputStringEmail = QStringLiteral(R"(email@example.com <a href="mailto:email@example.com">Link already rich</a>)");
|
|
||||||
QString testOutputStringEmail =
|
|
||||||
QStringLiteral(R"(<a href="mailto:email@example.com">email@example.com</a> <a href="mailto:email@example.com">Link already rich</a>)");
|
|
||||||
|
|
||||||
QString testInputStringMxId = QStringLiteral("@user:kde.org <a href=\"https://matrix.to/#/@user:kde.org\">Link already rich</a>");
|
|
||||||
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>");
|
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputStringLink1);
|
testTextHandler.setData(input);
|
||||||
|
|
||||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringLink1);
|
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), output);
|
||||||
|
|
||||||
testTextHandler.setData(testInputStringLink2);
|
|
||||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringLink2);
|
|
||||||
|
|
||||||
testTextHandler.setData(testInputStringEmail);
|
|
||||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringEmail);
|
|
||||||
|
|
||||||
testTextHandler.setData(testInputStringMxId);
|
|
||||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringMxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that user pill is add to an emote message.
|
|
||||||
// N.B. The second message in the test timeline is marked as an emote.
|
|
||||||
void TextHandlerTest::receiveRichEmote()
|
|
||||||
{
|
|
||||||
auto event = room->messageEvents().at(1).get();
|
|
||||||
auto author = room->user(event->senderId());
|
|
||||||
const QString testInputString = QStringLiteral("This is an emote.");
|
|
||||||
const QString testOutputString = QStringLiteral("* <a href=\"https://matrix.to/#/@example:example.org\" style=\"color:")
|
|
||||||
+ Utils::getUserColor(author->hueF()).name() + QStringLiteral("\">@example:example.org</a> This is an emote.");
|
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
|
||||||
testTextHandler.setData(testInputString);
|
|
||||||
|
|
||||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, event), testOutputString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextHandlerTest::receiveRichEdited_data()
|
void TextHandlerTest::receiveRichEdited_data()
|
||||||
@@ -491,12 +499,12 @@ void TextHandlerTest::receiveRichEdited_data()
|
|||||||
QTest::addColumn<QString>("testInputString");
|
QTest::addColumn<QString>("testInputString");
|
||||||
QTest::addColumn<QString>("testOutputString");
|
QTest::addColumn<QString>("testOutputString");
|
||||||
|
|
||||||
QTest::newRow("basic") << QStringLiteral("Edited") << QStringLiteral("Edited <span style=\"color:#000000\">(edited)</span>");
|
auto theme = static_cast<Kirigami::Platform::PlatformTheme *>(qmlAttachedPropertiesObject<Kirigami::Platform::PlatformTheme>(this, true));
|
||||||
QTest::newRow("multiple paragraphs") << QStringLiteral("<p>Edited</p>\n<p>Edited</p>")
|
|
||||||
<< QStringLiteral("<p>Edited</p>\n<p>Edited <span style=\"color:#000000\">(edited)</span></p>");
|
QTest::newRow("basic") << u"Edited"_s << u"Edited <span style=\"color:%1\">(edited)</span>"_s.arg(theme ? theme->disabledTextColor().name() : u"#000000"_s);
|
||||||
QTest::newRow("blockquote")
|
QTest::newRow("multiple paragraphs") << u"<p>Edited</p>\n<p>Edited</p>"_s
|
||||||
<< QStringLiteral("<blockquote>Edited</blockquote>")
|
<< u"<p>Edited</p>\n<p>Edited <span style=\"color:%1\">(edited)</span></p>"_s.arg(
|
||||||
<< QStringLiteral("<blockquote><table><tr><td>\u201CEdited\u201D</td></tr></table></blockquote><p> <span style=\"color:#000000\">(edited)</span></p>");
|
theme ? theme->disabledTextColor().name() : u"#000000"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextHandlerTest::receiveRichEdited()
|
void TextHandlerTest::receiveRichEdited()
|
||||||
@@ -507,24 +515,86 @@ void TextHandlerTest::receiveRichEdited()
|
|||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
|
|
||||||
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, room->messageEvents().at(2).get()), testOutputString);
|
const auto event = eventCast<const Quotient::RoomMessageEvent>(room->messageEvents().at(2).get());
|
||||||
|
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, event, false, event->isReplaced()), testOutputString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextHandlerTest::receiveLineSeparator()
|
void TextHandlerTest::receiveLineSeparator()
|
||||||
{
|
{
|
||||||
auto text = QStringLiteral("foo\u2028bar");
|
auto text = u"foo\u2028bar"_s;
|
||||||
TextHandler textHandler;
|
TextHandler textHandler;
|
||||||
textHandler.setData(text);
|
textHandler.setData(text);
|
||||||
QCOMPARE(textHandler.handleRecievePlainText(Qt::PlainText, true), QStringLiteral("foo bar"));
|
QCOMPARE(textHandler.handleRecievePlainText(Qt::PlainText, true), u"foo bar"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextHandlerTest::receiveRichCodeUrl()
|
void TextHandlerTest::receiveRichCodeUrl()
|
||||||
{
|
{
|
||||||
auto input = QStringLiteral("<code>https://kde.org</code>");
|
auto input = u"<code>https://kde.org</code>"_s;
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(input);
|
testTextHandler.setData(input);
|
||||||
QCOMPARE(testTextHandler.handleRecieveRichText(), input);
|
QCOMPARE(testTextHandler.handleRecieveRichText(), input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextHandlerTest::receiveRichColor()
|
||||||
|
{
|
||||||
|
const QString testInputString =
|
||||||
|
u"<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>"_s;
|
||||||
|
const QString testOutputString =
|
||||||
|
u"<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>"_s;
|
||||||
|
|
||||||
|
TextHandler testTextHandler;
|
||||||
|
testTextHandler.setData(testInputString);
|
||||||
|
|
||||||
|
QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextHandlerTest::componentOutput_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("testInputString");
|
||||||
|
QTest::addColumn<QList<MessageComponent>>("testOutputComponents");
|
||||||
|
|
||||||
|
QTest::newRow("multiple paragraphs") << u"<p>Text</p>\n<p>Text</p>"_s
|
||||||
|
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, u"Text"_s, {}},
|
||||||
|
MessageComponent{MessageComponentType::Text, u"Text"_s, {}}};
|
||||||
|
QTest::newRow("code") << u"<p>Text</p>\n<pre><code class=\"language-html\">Some code\n</code></pre>"_s
|
||||||
|
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, u"Text"_s, {}},
|
||||||
|
MessageComponent{MessageComponentType::Code, u"Some code"_s, QVariantMap{{u"class"_s, u"html"_s}}}};
|
||||||
|
QTest::newRow("quote") << u"<p>Text</p>\n<blockquote>\n<p>blockquote</p>\n</blockquote>"_s
|
||||||
|
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, u"Text"_s, {}},
|
||||||
|
MessageComponent{MessageComponentType::Quote, u"“blockquote”"_s, {}}};
|
||||||
|
QTest::newRow("multiple paragraph quote") << u"<blockquote>\n<p>blockquote</p>\n<p>next paragraph</p>\n</blockquote>"_s
|
||||||
|
<< QList<MessageComponent>{
|
||||||
|
MessageComponent{MessageComponentType::Quote, u"<p>“blockquote</p>\n<p>next paragraph”</p>"_s, {}}};
|
||||||
|
QTest::newRow("no tag first paragraph") << u"Text\n<p>Text</p>"_s
|
||||||
|
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, u"Text"_s, {}},
|
||||||
|
MessageComponent{MessageComponentType::Text, u"Text"_s, {}}};
|
||||||
|
QTest::newRow("no tag last paragraph") << u"<p>Text</p>\nText"_s
|
||||||
|
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, u"Text"_s, {}},
|
||||||
|
MessageComponent{MessageComponentType::Text, u"Text"_s, {}}};
|
||||||
|
QTest::newRow("inline code") << u"<p><code>https://kde.org</code></p>\n<p>Text</p>"_s
|
||||||
|
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, u"<code>https://kde.org</code>"_s, {}},
|
||||||
|
MessageComponent{MessageComponentType::Text, u"Text"_s, {}}};
|
||||||
|
QTest::newRow("inline code single block") << u"<code>https://kde.org</code>"_s
|
||||||
|
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, u"<code>https://kde.org</code>"_s, {}}};
|
||||||
|
QTest::newRow("long start tag")
|
||||||
|
<< u"Ah, you mean something like<br/><pre data-md=\"```\"><code class=\"language-qml\"># main.qml\nimport CustomQml\n...\nControls.TextField { id: 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"_s
|
||||||
|
<< QList<MessageComponent>{
|
||||||
|
MessageComponent{MessageComponentType::Text, u"Ah, you mean something like<br/>"_s, {}},
|
||||||
|
MessageComponent{
|
||||||
|
MessageComponentType::Code,
|
||||||
|
u"# main.qml\nimport CustomQml\n...\nControls.TextField { id: someField }\nCustomQml {\n someTextProperty: someField.text\n}"_s,
|
||||||
|
QVariantMap{{u"class"_s, u"qml"_s}}},
|
||||||
|
MessageComponent{MessageComponentType::Text, u"Sure you can, it's still local to the same file where you defined the id"_s, {}}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextHandlerTest::componentOutput()
|
||||||
|
{
|
||||||
|
QFETCH(QString, testInputString);
|
||||||
|
QFETCH(QList<MessageComponent>, testOutputComponents);
|
||||||
|
|
||||||
|
TextHandler testTextHandler;
|
||||||
|
QCOMPARE(testTextHandler.textComponents(testInputString), testOutputComponents);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(TextHandlerTest)
|
QTEST_MAIN(TextHandlerTest)
|
||||||
#include "texthandlertest.moc"
|
#include "texthandlertest.moc"
|
||||||
|
|||||||
@@ -10,20 +10,20 @@
|
|||||||
#include <Quotient/syncdata.h>
|
#include <Quotient/syncdata.h>
|
||||||
|
|
||||||
#include "enums/delegatetype.h"
|
#include "enums/delegatetype.h"
|
||||||
#include "models/messageeventmodel.h"
|
#include "models/timelinemessagemodel.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
|
|
||||||
#include "testutils.h"
|
#include "testutils.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
class MessageEventModelTest : public QObject
|
class TimelineMessageModelTest : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Connection *connection = nullptr;
|
Connection *connection = nullptr;
|
||||||
MessageEventModel *model = nullptr;
|
TimelineMessageModel *model = nullptr;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
@@ -40,71 +40,70 @@ private Q_SLOTS:
|
|||||||
void cleanup();
|
void cleanup();
|
||||||
};
|
};
|
||||||
|
|
||||||
void MessageEventModelTest::initTestCase()
|
void TimelineMessageModelTest::initTestCase()
|
||||||
{
|
{
|
||||||
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
|
connection = Connection::makeMockConnection(u"@bob:kde.org"_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageEventModelTest::init()
|
void TimelineMessageModelTest::init()
|
||||||
{
|
{
|
||||||
QCOMPARE(model, nullptr);
|
QCOMPARE(model, nullptr);
|
||||||
model = new MessageEventModel;
|
model = new TimelineMessageModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that basic empty rooms can be switched without crashing.
|
// Make sure that basic empty rooms can be switched without crashing.
|
||||||
void MessageEventModelTest::switchEmptyRoom()
|
void TimelineMessageModelTest::switchEmptyRoom()
|
||||||
{
|
{
|
||||||
auto firstRoom = new TestUtils::TestRoom(connection, QStringLiteral("#firstRoom:kde.org"));
|
auto firstRoom = new TestUtils::TestRoom(connection, u"#firstRoom:kde.org"_s);
|
||||||
auto secondRoom = new TestUtils::TestRoom(connection, QStringLiteral("#secondRoom:kde.org"));
|
auto secondRoom = new TestUtils::TestRoom(connection, u"#secondRoom:kde.org"_s);
|
||||||
|
|
||||||
QSignalSpy spy(model, SIGNAL(roomChanged()));
|
QSignalSpy spy(model, SIGNAL(roomChanged(NeoChatRoom *, NeoChatRoom *)));
|
||||||
|
|
||||||
QCOMPARE(model->room(), nullptr);
|
QCOMPARE(model->room(), nullptr);
|
||||||
model->setRoom(firstRoom);
|
model->setRoom(firstRoom);
|
||||||
QCOMPARE(spy.count(), 1);
|
QCOMPARE(spy.count(), 1);
|
||||||
QCOMPARE(model->room()->id(), QStringLiteral("#firstRoom:kde.org"));
|
QCOMPARE(model->room()->id(), u"#firstRoom:kde.org"_s);
|
||||||
model->setRoom(secondRoom);
|
model->setRoom(secondRoom);
|
||||||
QCOMPARE(spy.count(), 2);
|
QCOMPARE(spy.count(), 2);
|
||||||
QCOMPARE(model->room()->id(), QStringLiteral("#secondRoom:kde.org"));
|
QCOMPARE(model->room()->id(), u"#secondRoom:kde.org"_s);
|
||||||
model->setRoom(nullptr);
|
model->setRoom(nullptr);
|
||||||
QCOMPARE(spy.count(), 3);
|
QCOMPARE(spy.count(), 3);
|
||||||
QCOMPARE(model->room(), nullptr);
|
QCOMPARE(model->room(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that rooms with some events can be switched without crashing
|
// Make sure that rooms with some events can be switched without crashing
|
||||||
void MessageEventModelTest::switchSyncedRoom()
|
void TimelineMessageModelTest::switchSyncedRoom()
|
||||||
{
|
{
|
||||||
auto firstRoom = new TestUtils::TestRoom(connection, QStringLiteral("#firstRoom:kde.org"), QLatin1String("test-messageventmodel-sync.json"));
|
auto firstRoom = new TestUtils::TestRoom(connection, u"#firstRoom:kde.org"_s, u"test-messageventmodel-sync.json"_s);
|
||||||
auto secondRoom = new TestUtils::TestRoom(connection, QStringLiteral("#secondRoom:kde.org"), QLatin1String("test-messageventmodel-sync.json"));
|
auto secondRoom = new TestUtils::TestRoom(connection, u"#secondRoom:kde.org"_s, u"test-messageventmodel-sync.json"_s);
|
||||||
|
|
||||||
QSignalSpy spy(model, SIGNAL(roomChanged()));
|
QSignalSpy spy(model, SIGNAL(roomChanged(NeoChatRoom *, NeoChatRoom *)));
|
||||||
|
|
||||||
QCOMPARE(model->room(), nullptr);
|
QCOMPARE(model->room(), nullptr);
|
||||||
model->setRoom(firstRoom);
|
model->setRoom(firstRoom);
|
||||||
QCOMPARE(spy.count(), 1);
|
QCOMPARE(spy.count(), 1);
|
||||||
QCOMPARE(model->room()->id(), QStringLiteral("#firstRoom:kde.org"));
|
QCOMPARE(model->room()->id(), u"#firstRoom:kde.org"_s);
|
||||||
model->setRoom(secondRoom);
|
model->setRoom(secondRoom);
|
||||||
QCOMPARE(spy.count(), 2);
|
QCOMPARE(spy.count(), 2);
|
||||||
QCOMPARE(model->room()->id(), QStringLiteral("#secondRoom:kde.org"));
|
QCOMPARE(model->room()->id(), u"#secondRoom:kde.org"_s);
|
||||||
model->setRoom(nullptr);
|
model->setRoom(nullptr);
|
||||||
QCOMPARE(spy.count(), 3);
|
QCOMPARE(spy.count(), 3);
|
||||||
QCOMPARE(model->room(), nullptr);
|
QCOMPARE(model->room(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageEventModelTest::simpleTimeline()
|
void TimelineMessageModelTest::simpleTimeline()
|
||||||
{
|
{
|
||||||
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-messageventmodel-sync.json"));
|
auto room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, u"test-messageventmodel-sync.json"_s);
|
||||||
|
|
||||||
model->setRoom(room);
|
model->setRoom(room);
|
||||||
QCOMPARE(model->rowCount(), 2);
|
QCOMPARE(model->rowCount(), 2);
|
||||||
|
|
||||||
QCOMPARE(model->data(model->index(0), MessageEventModel::DelegateTypeRole), DelegateType::State);
|
QCOMPARE(model->data(model->index(0), TimelineMessageModel::DelegateTypeRole), DelegateType::State);
|
||||||
QCOMPARE(model->data(model->index(0)), QStringLiteral("changed their display name to Example Changed"));
|
QCOMPARE(model->data(model->index(0)), u"changed their display name to Example Changed"_s);
|
||||||
|
|
||||||
QCOMPARE(model->data(model->index(1)), QStringLiteral("<b>This is an example<br>text message</b>"));
|
QCOMPARE(model->data(model->index(1)), u"<b>This is an example<br>text message</b>"_s);
|
||||||
QCOMPARE(model->data(model->index(1), MessageEventModel::DelegateTypeRole), DelegateType::Message);
|
QCOMPARE(model->data(model->index(1), TimelineMessageModel::DelegateTypeRole), DelegateType::Message);
|
||||||
QCOMPARE(model->data(model->index(1), MessageEventModel::PlainText), QStringLiteral("This is an example\ntext message"));
|
QCOMPARE(model->data(model->index(1), TimelineMessageModel::EventIdRole), u"$153456789:example.org"_s);
|
||||||
QCOMPARE(model->data(model->index(1), MessageEventModel::EventIdRole), QStringLiteral("$153456789:example.org"));
|
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "Index QModelIndex(-1,-1,0x0,QObject(0x0)) is not valid (expected valid)");
|
QTest::ignoreMessage(QtWarningMsg, "Index QModelIndex(-1,-1,0x0,QObject(0x0)) is not valid (expected valid)");
|
||||||
QCOMPARE(model->data(model->index(-1)), QVariant());
|
QCOMPARE(model->data(model->index(-1)), QVariant());
|
||||||
@@ -112,33 +111,37 @@ void MessageEventModelTest::simpleTimeline()
|
|||||||
QCOMPARE(model->data(model->index(model->rowCount())), QVariant());
|
QCOMPARE(model->data(model->index(model->rowCount())), QVariant());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync some events into the MessageEventModel's current room and don't crash.
|
// Sync some events into the TimelineMessageModel's current room and don't crash.
|
||||||
void MessageEventModelTest::syncNewEvents()
|
void TimelineMessageModelTest::syncNewEvents()
|
||||||
{
|
{
|
||||||
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"));
|
auto room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s);
|
||||||
QSignalSpy spy(room, SIGNAL(aboutToAddNewMessages(Quotient::RoomEventsRange)));
|
QSignalSpy spy(room, SIGNAL(aboutToAddNewMessages(Quotient::RoomEventsRange)));
|
||||||
|
|
||||||
model->setRoom(room);
|
model->setRoom(room);
|
||||||
QCOMPARE(model->rowCount(), 0);
|
QCOMPARE(model->rowCount(), 0);
|
||||||
|
|
||||||
room->syncNewEvents(QLatin1String("test-messageventmodel-sync.json"));
|
room->syncNewEvents(u"test-messageventmodel-sync.json"_s);
|
||||||
|
|
||||||
QCOMPARE(model->rowCount(), 2);
|
QCOMPARE(model->rowCount(), 2);
|
||||||
QCOMPARE(spy.count(), 1);
|
QCOMPARE(spy.count(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the adding of pending events to the room doesn't cause any issues in the model.
|
// Check the adding of pending events to the room doesn't cause any issues in the model.
|
||||||
void MessageEventModelTest::pendingEvent()
|
void TimelineMessageModelTest::pendingEvent()
|
||||||
{
|
{
|
||||||
QSignalSpy spyInsert(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
|
QSignalSpy spyInsert(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
|
||||||
QSignalSpy spyRemove(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
|
QSignalSpy spyRemove(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
|
||||||
QSignalSpy spyChanged(model, SIGNAL(dataChanged(const QModelIndex, const QModelIndex, const QList<int> &)));
|
QSignalSpy spyChanged(model, SIGNAL(dataChanged(const QModelIndex, const QModelIndex, const QList<int> &)));
|
||||||
|
|
||||||
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"));
|
auto room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s);
|
||||||
model->setRoom(room);
|
model->setRoom(room);
|
||||||
QCOMPARE(model->rowCount(), 0);
|
QCOMPARE(model->rowCount(), 0);
|
||||||
|
|
||||||
auto txnId = room->postPlainText("New plain message"_ls);
|
#if Quotient_VERSION_MINOR > 9
|
||||||
|
auto txnId = room->postText("New plain message"_L1);
|
||||||
|
#else
|
||||||
|
auto txnId = room->postPlainText("New plain message"_L1);
|
||||||
|
#endif
|
||||||
QCOMPARE(model->rowCount(), 1);
|
QCOMPARE(model->rowCount(), 1);
|
||||||
QCOMPARE(spyInsert.count(), 1);
|
QCOMPARE(spyInsert.count(), 1);
|
||||||
|
|
||||||
@@ -146,26 +149,30 @@ void MessageEventModelTest::pendingEvent()
|
|||||||
QCOMPARE(model->rowCount(), 0);
|
QCOMPARE(model->rowCount(), 0);
|
||||||
QCOMPARE(spyRemove.count(), 1);
|
QCOMPARE(spyRemove.count(), 1);
|
||||||
|
|
||||||
txnId = room->postPlainText("New plain message"_ls);
|
#if Quotient_VERSION_MINOR > 9
|
||||||
|
txnId = room->postText("New plain message"_L1);
|
||||||
|
#else
|
||||||
|
txnId = room->postPlainText("New plain message"_L1);
|
||||||
|
#endif
|
||||||
QCOMPARE(model->rowCount(), 1);
|
QCOMPARE(model->rowCount(), 1);
|
||||||
QCOMPARE(spyInsert.count(), 2);
|
QCOMPARE(spyInsert.count(), 2);
|
||||||
|
|
||||||
// We need to manually set the transaction ID of the new message as it will be
|
// We need to manually set the transaction ID of the new message as it will be
|
||||||
// different every time.
|
// different every time.
|
||||||
QFile testSyncFile;
|
QFile testSyncFile;
|
||||||
testSyncFile.setFileName(QLatin1String(DATA_DIR) + u'/' + QLatin1String("test-pending-sync.json"));
|
testSyncFile.setFileName(QStringLiteral(DATA_DIR) + u'/' + u"test-pending-sync.json"_s);
|
||||||
testSyncFile.open(QIODevice::ReadOnly);
|
testSyncFile.open(QIODevice::ReadOnly);
|
||||||
auto testSyncJson = QJsonDocument::fromJson(testSyncFile.readAll());
|
auto testSyncJson = QJsonDocument::fromJson(testSyncFile.readAll());
|
||||||
auto root = testSyncJson.object();
|
auto root = testSyncJson.object();
|
||||||
auto timeline = root["timeline"_ls].toObject();
|
auto timeline = root["timeline"_L1].toObject();
|
||||||
auto events = timeline["events"_ls].toArray();
|
auto events = timeline["events"_L1].toArray();
|
||||||
auto firstEvent = events[0].toObject();
|
auto firstEvent = events[0].toObject();
|
||||||
firstEvent.insert(QLatin1String("unsigned"), QJsonObject{{QLatin1String("transaction_id"), txnId}});
|
firstEvent.insert("unsigned"_L1, QJsonObject{{"transaction_id"_L1, txnId}});
|
||||||
events[0] = firstEvent;
|
events[0] = firstEvent;
|
||||||
timeline.insert("events"_ls, events);
|
timeline.insert("events"_L1, events);
|
||||||
root.insert("timeline"_ls, timeline);
|
root.insert("timeline"_L1, timeline);
|
||||||
testSyncJson.setObject(root);
|
testSyncJson.setObject(root);
|
||||||
SyncRoomData roomData(QStringLiteral("@bob:kde.org"), JoinState::Join, testSyncJson.object());
|
SyncRoomData roomData(u"@bob:kde.org"_s, JoinState::Join, testSyncJson.object());
|
||||||
room->update(std::move(roomData));
|
room->update(std::move(roomData));
|
||||||
|
|
||||||
QCOMPARE(model->rowCount(), 1);
|
QCOMPARE(model->rowCount(), 1);
|
||||||
@@ -175,7 +182,7 @@ void MessageEventModelTest::pendingEvent()
|
|||||||
auto isPendingChanged = false;
|
auto isPendingChanged = false;
|
||||||
for (auto signal : spyChanged) {
|
for (auto signal : spyChanged) {
|
||||||
auto roles = signal.at(2).toList();
|
auto roles = signal.at(2).toList();
|
||||||
if (roles.contains(MessageEventModel::IsPendingRole)) {
|
if (roles.contains(TimelineMessageModel::IsPendingRole)) {
|
||||||
isPendingChanged = true;
|
isPendingChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,33 +190,33 @@ void MessageEventModelTest::pendingEvent()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that the signals are disconnecting correctly when a room is switched.
|
// Make sure that the signals are disconnecting correctly when a room is switched.
|
||||||
void MessageEventModelTest::disconnect()
|
void TimelineMessageModelTest::disconnect()
|
||||||
{
|
{
|
||||||
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"));
|
auto room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s);
|
||||||
model->setRoom(room);
|
model->setRoom(room);
|
||||||
|
|
||||||
QSignalSpy spy(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
|
QSignalSpy spy(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
|
||||||
|
|
||||||
model->setRoom(nullptr);
|
model->setRoom(nullptr);
|
||||||
room->syncNewEvents(QLatin1String("test-messageventmodel-sync.json"));
|
room->syncNewEvents(u"test-messageventmodel-sync.json"_s);
|
||||||
|
|
||||||
QCOMPARE(spy.count(), 0);
|
QCOMPARE(spy.count(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageEventModelTest::idToRow()
|
void TimelineMessageModelTest::idToRow()
|
||||||
{
|
{
|
||||||
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-min-sync.json"));
|
auto room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, u"test-min-sync.json"_s);
|
||||||
model->setRoom(room);
|
model->setRoom(room);
|
||||||
|
|
||||||
QCOMPARE(model->eventIdToRow(QStringLiteral("$153456789:example.org")), 0);
|
QCOMPARE(model->indexforEventId(u"$153456789:example.org"_s).row(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageEventModelTest::cleanup()
|
void TimelineMessageModelTest::cleanup()
|
||||||
{
|
{
|
||||||
delete model;
|
delete model;
|
||||||
model = nullptr;
|
model = nullptr;
|
||||||
QCOMPARE(model, nullptr);
|
QCOMPARE(model, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(MessageEventModelTest)
|
QTEST_MAIN(TimelineMessageModelTest)
|
||||||
#include "messageeventmodeltest.moc"
|
#include "timelinemessagemodeltest.moc"
|
||||||
@@ -17,7 +17,6 @@ class WindowControllerTest : public QObject
|
|||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void nullWindow();
|
void nullWindow();
|
||||||
void geometry();
|
|
||||||
void showAndRaise();
|
void showAndRaise();
|
||||||
void toggle();
|
void toggle();
|
||||||
|
|
||||||
@@ -30,32 +29,10 @@ void WindowControllerTest::nullWindow()
|
|||||||
auto &instance = WindowController::instance();
|
auto &instance = WindowController::instance();
|
||||||
QCOMPARE(instance.window(), nullptr);
|
QCOMPARE(instance.window(), nullptr);
|
||||||
|
|
||||||
instance.restoreGeometry();
|
|
||||||
instance.saveGeometry();
|
|
||||||
instance.showAndRaiseWindow({});
|
instance.showAndRaiseWindow({});
|
||||||
instance.toggleWindow();
|
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()
|
void WindowControllerTest::showAndRaise()
|
||||||
{
|
{
|
||||||
auto &instance = WindowController::instance();
|
auto &instance = WindowController::instance();
|
||||||
|
|||||||
37
memorytests/CMakeLists.txt
Normal file
37
memorytests/CMakeLists.txt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
add_definitions(-DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}" )
|
||||||
|
|
||||||
|
qt_add_executable(timeline-memtest
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(timeline-memtest PRIVATE neochatplugin Timelineplugin)
|
||||||
|
target_link_libraries(timeline-memtest PUBLIC
|
||||||
|
Qt::Core
|
||||||
|
Qt::Quick
|
||||||
|
Qt::Qml
|
||||||
|
Qt::Gui
|
||||||
|
Qt::QuickControls2
|
||||||
|
Qt::Widgets
|
||||||
|
KF6::I18nQml
|
||||||
|
KF6::Kirigami
|
||||||
|
QuotientQt6
|
||||||
|
LibNeoChat
|
||||||
|
Timeline
|
||||||
|
)
|
||||||
|
|
||||||
|
ecm_add_qml_module(timeline-memtest URI org.kde.neochat.timeline-memtest GENERATE_PLUGIN_SOURCE
|
||||||
|
OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/org/kde/timeline-memtest
|
||||||
|
QML_FILES
|
||||||
|
Main.qml
|
||||||
|
SOURCES
|
||||||
|
memtesttimelinemodel.cpp
|
||||||
|
memtesttimelinemodel.h
|
||||||
|
DEPENDENCIES
|
||||||
|
QtCore
|
||||||
|
QtQuick
|
||||||
|
IMPORTS
|
||||||
|
org.kde.neochat.timeline
|
||||||
|
)
|
||||||
34
memorytests/Main.qml
Normal file
34
memorytests/Main.qml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls as QQC2
|
||||||
|
|
||||||
|
import org.kde.kirigami as Kirigami
|
||||||
|
|
||||||
|
import org.kde.neochat
|
||||||
|
|
||||||
|
QQC2.ApplicationWindow {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
title: "Timeline Memory Test"
|
||||||
|
|
||||||
|
minimumWidth: Kirigami.Units.gridUnit * 30
|
||||||
|
minimumHeight: Kirigami.Units.gridUnit * 30
|
||||||
|
|
||||||
|
visible: true
|
||||||
|
|
||||||
|
QQC2.ScrollView {
|
||||||
|
width: root.width
|
||||||
|
height: root.height
|
||||||
|
|
||||||
|
contentItem: ListView {
|
||||||
|
cacheBuffer: 1000000
|
||||||
|
model: messageFilterModel
|
||||||
|
|
||||||
|
delegate: EventDelegate {
|
||||||
|
room: memTestTimelineModel.room
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
memorytests/main.cpp
Normal file
34
memorytests/main.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// 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 <QApplication>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
#include <QQmlContext>
|
||||||
|
|
||||||
|
#include <KLocalizedQmlContext>
|
||||||
|
#include <KLocalizedString>
|
||||||
|
|
||||||
|
#include "memtesttimelinemodel.h"
|
||||||
|
#include "models/messagefiltermodel.h"
|
||||||
|
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
KLocalizedString::setApplicationDomain(QByteArrayLiteral("neochat"));
|
||||||
|
|
||||||
|
QQmlApplicationEngine engine;
|
||||||
|
|
||||||
|
KLocalization::setupLocalizedContext(&engine);
|
||||||
|
|
||||||
|
MemTestTimelineModel *memTestTimelineModel = new MemTestTimelineModel;
|
||||||
|
MessageFilterModel *messageFilterModel = new MessageFilterModel(nullptr, memTestTimelineModel);
|
||||||
|
engine.rootContext()->setContextProperty(u"memTestTimelineModel"_s, memTestTimelineModel);
|
||||||
|
engine.rootContext()->setContextProperty(u"messageFilterModel"_s, messageFilterModel);
|
||||||
|
|
||||||
|
engine.loadFromModule("org.kde.neochat.timeline-memtest", "Main");
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
379
memorytests/memtest-sync.json
Normal file
379
memorytests/memtest-sync.json
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
{
|
||||||
|
"ephemeral": {
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"$1000000000000:example.org": {
|
||||||
|
"m.read": {
|
||||||
|
"@alice:example.org": {
|
||||||
|
"ts": 1000000000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "m.receipt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"$1000000000000:example.org": {
|
||||||
|
"m.read": {
|
||||||
|
"@bob:example.org": {
|
||||||
|
"ts": 1000000000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "m.receipt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"$1000000000003:example.org": {
|
||||||
|
"m.read": {
|
||||||
|
"@tim:example.org": {
|
||||||
|
"ts": 1000000000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "m.receipt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"$1000000000003:example.org": {
|
||||||
|
"m.read": {
|
||||||
|
"@example:example.org": {
|
||||||
|
"ts": 1000000000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "m.receipt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"$1000000000003:example.org": {
|
||||||
|
"m.read": {
|
||||||
|
"@jeff:example.org": {
|
||||||
|
"ts": 1000000000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "m.receipt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"$1000000000003:example.org": {
|
||||||
|
"m.read": {
|
||||||
|
"@tina:example.org": {
|
||||||
|
"ts": 1000000000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "m.receipt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"$1000000000003:example.org": {
|
||||||
|
"m.read": {
|
||||||
|
"@sally:example.org": {
|
||||||
|
"ts": 1000000000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "m.receipt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"$1000000000003:example.org": {
|
||||||
|
"m.read": {
|
||||||
|
"@fred:example.org": {
|
||||||
|
"ts": 1000000000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "m.receipt"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||||
|
"displayname": "Example",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582555PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1000000000000,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "example:example.org",
|
||||||
|
"state_key": "@example:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||||
|
"displayname": "Alice",
|
||||||
|
"membership": "join",
|
||||||
|
"reason": "Looking for support"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1000000000000,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "alice:example.org",
|
||||||
|
"state_key": "@alice:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||||
|
"displayname": "Bob",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1000000000000,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "bob:example.org",
|
||||||
|
"state_key": "@bob:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||||
|
"displayname": "Tim",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1000000000000,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "tim:example.org",
|
||||||
|
"state_key": "@tim:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||||
|
"displayname": "Jeff",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1000000000000,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "jeff:example.org",
|
||||||
|
"state_key": "@jeff:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||||
|
"displayname": "Tina",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1000000000000,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "tina:example.org",
|
||||||
|
"state_key": "@tina:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||||
|
"displayname": "Sally",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1000000000000,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "sally:example.org",
|
||||||
|
"state_key": "@sally:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
||||||
|
"displayname": "Fred",
|
||||||
|
"membership": "join"
|
||||||
|
},
|
||||||
|
"event_id": "$143273582443PhrSn:example.org",
|
||||||
|
"origin_server_ts": 1000000000000,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "fred:example.org",
|
||||||
|
"state_key": "@fred:example.org",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1234
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"timeline": {
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"body": "This is an example text message",
|
||||||
|
"format": "org.matrix.custom.html",
|
||||||
|
"formatted_body": "This is an example<br>text message",
|
||||||
|
"msgtype": "m.text"
|
||||||
|
},
|
||||||
|
"event_id": 0,
|
||||||
|
"origin_server_ts": 1000000000000,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@example:example.org",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1232
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"body": "This is a highlight @bob:example.org",
|
||||||
|
"msgtype": "m.text"
|
||||||
|
},
|
||||||
|
"event_id": 1,
|
||||||
|
"origin_server_ts": 1000000000001,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@example:example.org",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1233
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"m.relates_to": {
|
||||||
|
"event_id": 1,
|
||||||
|
"key": "👍",
|
||||||
|
"rel_type": "m.annotation"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"origin_server_ts": 1000000000002,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@alice:example.org",
|
||||||
|
"type": "m.reaction",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 390159120
|
||||||
|
},
|
||||||
|
"event_id": 2,
|
||||||
|
"age": 390159120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"body": "reply",
|
||||||
|
"format": "org.matrix.custom.html",
|
||||||
|
"formatted_body": "reply",
|
||||||
|
"m.relates_to": {
|
||||||
|
"m.in_reply_to": {
|
||||||
|
"event_id": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"msgtype": "m.text"
|
||||||
|
},
|
||||||
|
"origin_server_ts": 1000000000003,
|
||||||
|
"sender": "@alice:example.org",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 98
|
||||||
|
},
|
||||||
|
"event_id": 3,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"age": 96845207,
|
||||||
|
"content": {
|
||||||
|
"body": "Lat: 51.7035, Lon: -1.14394",
|
||||||
|
"geo_uri": "geo:51.7035,-1.14394",
|
||||||
|
"msgtype": "m.location",
|
||||||
|
"org.matrix.msc1767.text": "Lat: 51.7035, Lon: -1.14394",
|
||||||
|
"org.matrix.msc3488.asset": {
|
||||||
|
"type": "m.pin"
|
||||||
|
},
|
||||||
|
"org.matrix.msc3488.location": {
|
||||||
|
"uri": "geo:51.7035,-1.14394"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"event_id": 4,
|
||||||
|
"origin_server_ts": 1000000000004,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@example:example.org",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 96845207
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"body": "```cpp\nint main(int argc, char **argv)\n{\n QApplication app(argc, argv);\n\n KLocalizedString::setApplicationDomain(QByteArrayLiteral(\"neochat\"));\n\n QQmlApplicationEngine engine;\n engine.loadFromModule(\"org.kde.neochat.timeline-memtest\", \"Main\");\n\n return app.exec();\n}\n```",
|
||||||
|
"format": "org.matrix.custom.html",
|
||||||
|
"formatted_body": "<pre><code class=\"language-cpp\">int main(int argc, char **argv)\n{\n QApplication app(argc, argv);\n\n KLocalizedString::setApplicationDomain(QByteArrayLiteral("neochat"));\n\n QQmlApplicationEngine engine;\n engine.loadFromModule("org.kde.neochat.timeline-memtest", "Main");\n\n return app.exec();\n}\n</code></pre>",
|
||||||
|
"msgtype": "m.text"
|
||||||
|
},
|
||||||
|
"event_id": 5,
|
||||||
|
"origin_server_ts": 1000000000005,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@bob:example.org",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1233
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat. ",
|
||||||
|
"msgtype": "m.text"
|
||||||
|
},
|
||||||
|
"event_id": 6,
|
||||||
|
"origin_server_ts": 1000000000006,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@example:example.org",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1232
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"body": "> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat. ",
|
||||||
|
"format": "org.matrix.custom.html",
|
||||||
|
"formatted_body": "<blockquote>\n<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat.</p>\n</blockquote>",
|
||||||
|
"msgtype": "m.text"
|
||||||
|
},
|
||||||
|
"event_id": 7,
|
||||||
|
"origin_server_ts": 1000000000007,
|
||||||
|
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
|
||||||
|
"sender": "@example:example.org",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"age": 1232
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"limited": true,
|
||||||
|
"prev_batch": "t34-23535_0_0"
|
||||||
|
}
|
||||||
|
}
|
||||||
36
memorytests/memtesttimelinemodel.cpp
Normal file
36
memorytests/memtesttimelinemodel.cpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// 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 "memtesttimelinemodel.h"
|
||||||
|
|
||||||
|
#include <Quotient/events/eventcontent.h>
|
||||||
|
#include <Quotient/events/roommessageevent.h>
|
||||||
|
|
||||||
|
using namespace Quotient;
|
||||||
|
|
||||||
|
MemTestTimelineModel::MemTestTimelineModel(QObject *parent)
|
||||||
|
: MessageModel(parent)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_connection = Connection::makeMockConnection(u"@bob:example.org"_s);
|
||||||
|
m_room = new MemTestRoom(m_connection, u"#memtestroom:example.org"_s, u"memtest-sync.json"_s);
|
||||||
|
|
||||||
|
for (const auto &eventIt : m_room->messageEvents()) {
|
||||||
|
Q_EMIT newEventAdded(eventIt.event());
|
||||||
|
}
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const RoomEvent>> MemTestTimelineModel::getEventForIndex(QModelIndex index) const
|
||||||
|
{
|
||||||
|
return *m_room->messageEvents().at(index.row()).event();
|
||||||
|
}
|
||||||
|
|
||||||
|
int MemTestTimelineModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
return m_room->messageEvents().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_memtesttimelinemodel.cpp"
|
||||||
117
memorytests/memtesttimelinemodel.h
Normal file
117
memorytests/memtesttimelinemodel.h
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QQmlEngine>
|
||||||
|
|
||||||
|
#include <Quotient/events/roomevent.h>
|
||||||
|
#include <Quotient/syncdata.h>
|
||||||
|
|
||||||
|
#include "models/messagemodel.h"
|
||||||
|
|
||||||
|
namespace Quotient
|
||||||
|
{
|
||||||
|
class Connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NeoChatRoom;
|
||||||
|
|
||||||
|
class MemTestRoom : public NeoChatRoom
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MemTestRoom(Quotient::Connection *connection, const QString &roomName, const QString &syncFileName = {})
|
||||||
|
: NeoChatRoom(connection, roomName, Quotient::JoinState::Join)
|
||||||
|
{
|
||||||
|
syncNewEvents(syncFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(Quotient::SyncRoomData &&data, bool fromCache = false)
|
||||||
|
{
|
||||||
|
Room::updateData(std::move(data), fromCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void syncNewEvents(const QString &syncFileName)
|
||||||
|
{
|
||||||
|
if (!syncFileName.isEmpty()) {
|
||||||
|
QFile testSyncFile;
|
||||||
|
testSyncFile.setFileName(QStringLiteral(DATA_DIR) + u'/' + syncFileName);
|
||||||
|
testSyncFile.open(QIODevice::ReadOnly);
|
||||||
|
auto testSyncJson = QJsonDocument::fromJson(testSyncFile.readAll()).object();
|
||||||
|
auto timelineJson = testSyncJson["timeline"_L1].toObject();
|
||||||
|
timelineJson["events"_L1] = multiplyEvents(timelineJson["events"_L1].toArray(), 100);
|
||||||
|
testSyncJson["timeline"_L1] = timelineJson;
|
||||||
|
Quotient::SyncRoomData roomData(id(), Quotient::JoinState::Join, testSyncJson);
|
||||||
|
update(std::move(roomData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray multiplyEvents(QJsonArray events, int factor)
|
||||||
|
{
|
||||||
|
QJsonArray newArray;
|
||||||
|
int eventNum = 0;
|
||||||
|
int ts = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < factor; ++i) {
|
||||||
|
for (const auto &event : events) {
|
||||||
|
auto eventObject = event.toObject();
|
||||||
|
auto contentJson = eventObject["content"_L1].toObject();
|
||||||
|
if (contentJson.contains("m.relates_to"_L1)) {
|
||||||
|
auto relatesToJson = contentJson["m.relates_to"_L1].toObject();
|
||||||
|
if (relatesToJson.contains("m.in_reply_to"_L1)) {
|
||||||
|
auto replyJson = relatesToJson["m.in_reply_to"_L1].toObject();
|
||||||
|
const auto currentId = eventObject["event_id"_L1].toInt();
|
||||||
|
const auto currentReplyId = replyJson["event_id"_L1].toInt();
|
||||||
|
replyJson["event_id"_L1] = "$%1:example.org"_L1.arg(QString::number(eventNum - (currentId - currentReplyId)));
|
||||||
|
relatesToJson["m.in_reply_to"_L1] = replyJson;
|
||||||
|
} else if (relatesToJson.contains("event_id"_L1)) {
|
||||||
|
const auto currentId = eventObject["event_id"_L1].toInt();
|
||||||
|
const auto currentRelationId = relatesToJson["event_id"_L1].toInt();
|
||||||
|
relatesToJson["event_id"_L1] = "$%1:example.org"_L1.arg(QString::number(eventNum - (currentId - currentRelationId)));
|
||||||
|
}
|
||||||
|
contentJson["m.relates_to"_L1] = relatesToJson;
|
||||||
|
eventObject["content"_L1] = contentJson;
|
||||||
|
}
|
||||||
|
eventObject["event_id"_L1] = "$%1:example.org"_L1.arg(QString::number(eventNum));
|
||||||
|
eventObject["origin_server_ts"_L1] = ts;
|
||||||
|
auto unsignedJson = eventObject["unsigned"_L1].toObject();
|
||||||
|
unsignedJson["age"_L1] = ts;
|
||||||
|
eventObject["unsigned"_L1] = unsignedJson;
|
||||||
|
newArray.append(eventObject);
|
||||||
|
++eventNum;
|
||||||
|
++ts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newArray;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class MemTestTimelineModel
|
||||||
|
*
|
||||||
|
* This is a special version of the MessageModel design to load an unchanging set
|
||||||
|
* of events from a json file so that timeline memory optimisations can be measured.
|
||||||
|
*/
|
||||||
|
class MemTestTimelineModel : public MessageModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MemTestTimelineModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of rows in the model.
|
||||||
|
*
|
||||||
|
* @sa QAbstractItemModel::rowCount
|
||||||
|
*/
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPointer<Quotient::Connection> m_connection;
|
||||||
|
|
||||||
|
std::vector<Quotient::RoomEventPtr> m_events;
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const Quotient::RoomEvent>> getEventForIndex(QModelIndex index) const override;
|
||||||
|
};
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
<name xml:lang="fi">NeoChat</name>
|
<name xml:lang="fi">NeoChat</name>
|
||||||
<name xml:lang="fr">NeoChat</name>
|
<name xml:lang="fr">NeoChat</name>
|
||||||
<name xml:lang="gl">NeoChat</name>
|
<name xml:lang="gl">NeoChat</name>
|
||||||
|
<name xml:lang="he">NeoChat</name>
|
||||||
|
<name xml:lang="hi">नियोचैट</name>
|
||||||
<name xml:lang="hu">NeoChat</name>
|
<name xml:lang="hu">NeoChat</name>
|
||||||
<name xml:lang="ia">Neochat</name>
|
<name xml:lang="ia">Neochat</name>
|
||||||
<name xml:lang="id">NeoChat</name>
|
<name xml:lang="id">NeoChat</name>
|
||||||
@@ -32,6 +34,7 @@
|
|||||||
<name xml:lang="it">NeoChat</name>
|
<name xml:lang="it">NeoChat</name>
|
||||||
<name xml:lang="ka">NeoChat</name>
|
<name xml:lang="ka">NeoChat</name>
|
||||||
<name xml:lang="ko">NeoChat</name>
|
<name xml:lang="ko">NeoChat</name>
|
||||||
|
<name xml:lang="lv">NeoChat</name>
|
||||||
<name xml:lang="nl">NeoChat</name>
|
<name xml:lang="nl">NeoChat</name>
|
||||||
<name xml:lang="nn">NeoChat</name>
|
<name xml:lang="nn">NeoChat</name>
|
||||||
<name xml:lang="pa">ਨਿਓ-ਚੈਟ</name>
|
<name xml:lang="pa">ਨਿਓ-ਚੈਟ</name>
|
||||||
@@ -39,6 +42,7 @@
|
|||||||
<name xml:lang="pt">NeoChat</name>
|
<name xml:lang="pt">NeoChat</name>
|
||||||
<name xml:lang="pt-BR">NeoChat</name>
|
<name xml:lang="pt-BR">NeoChat</name>
|
||||||
<name xml:lang="ru">NeoChat</name>
|
<name xml:lang="ru">NeoChat</name>
|
||||||
|
<name xml:lang="sa">नवचैट्</name>
|
||||||
<name xml:lang="sk">NeoChat</name>
|
<name xml:lang="sk">NeoChat</name>
|
||||||
<name xml:lang="sl">NeoChat</name>
|
<name xml:lang="sl">NeoChat</name>
|
||||||
<name xml:lang="sv">NeoChat</name>
|
<name xml:lang="sv">NeoChat</name>
|
||||||
@@ -48,81 +52,101 @@
|
|||||||
<name xml:lang="x-test">xxNeoChatxx</name>
|
<name xml:lang="x-test">xxNeoChatxx</name>
|
||||||
<name xml:lang="zh-CN">NeoChat</name>
|
<name xml:lang="zh-CN">NeoChat</name>
|
||||||
<name xml:lang="zh-TW">NeoChat</name>
|
<name xml:lang="zh-TW">NeoChat</name>
|
||||||
<summary>Chat with your friends on matrix</summary>
|
<summary>Chat on Matrix</summary>
|
||||||
<summary xml:lang="ar">دردش مع أصدقائك على ماتركس</summary>
|
<summary xml:lang="ar">دردش على ماتركس</summary>
|
||||||
<summary xml:lang="ca">Xategeu amb els vostres amics a Matrix</summary>
|
<summary xml:lang="ca">Xat a Matrix</summary>
|
||||||
<summary xml:lang="ca-valencia">Xategeu amb els vostres amics a Matrix</summary>
|
<summary xml:lang="ca-valencia">Xat a Matrix</summary>
|
||||||
<summary xml:lang="cs">Mluvte se svými přáteli na Matrixu</summary>
|
<summary xml:lang="de">Über Matrix unterhalten</summary>
|
||||||
<summary xml:lang="eo">Babilu kun viaj amikoj sur matrix</summary>
|
<summary xml:lang="en-GB">Chat on Matrix</summary>
|
||||||
<summary xml:lang="es">Charle con sus amigos en matrix</summary>
|
<summary xml:lang="eo">Babilo en Matrix</summary>
|
||||||
<summary xml:lang="eu">Berriketan jardun zure lagunekin «Matrix»en</summary>
|
<summary xml:lang="es">Charle en Matrix</summary>
|
||||||
<summary xml:lang="fi">Keskustelu ystäviesi kanssa Matrixissa</summary>
|
<summary xml:lang="eu">Berriketa Matrix-en</summary>
|
||||||
<summary xml:lang="fr">Discuter avec vos ami(e)s sur le réseau Matrix</summary>
|
<summary xml:lang="fi">Keskustelu Matrixissä</summary>
|
||||||
<summary xml:lang="gl">Charle coas súas amizades en Matrix.</summary>
|
<summary xml:lang="fr">Discuter sur Matrix</summary>
|
||||||
<summary xml:lang="hu">Csevegjen barátaival a matrixon</summary>
|
<summary xml:lang="gl">Charlar en Matrix</summary>
|
||||||
<summary xml:lang="ia">Starta Conversation con tu amicos sur matrix</summary>
|
<summary xml:lang="he">התכתבות דרך Matrix</summary>
|
||||||
<summary xml:lang="it">Conversa con i tuoi contatti su matrix</summary>
|
<summary xml:lang="hi">मैट्रिक्स पर चैट करें</summary>
|
||||||
<summary xml:lang="ka">ესაუბრეთ მეგობრებს Matrix-ზე</summary>
|
<summary xml:lang="hu">Csevegés Matrixon</summary>
|
||||||
<summary xml:lang="ko">Matrix를 사용하여 친구들과 대화하기</summary>
|
<summary xml:lang="ia">Conversation en ditecto sur Matrix</summary>
|
||||||
<summary xml:lang="nl">Met uw vrienden chatten op matrix</summary>
|
<summary xml:lang="it">Chat su Matrix</summary>
|
||||||
<summary xml:lang="nn">Prat med vennar på Matrix</summary>
|
<summary xml:lang="ka">ისაუბრეთ Matrix-ზე</summary>
|
||||||
<summary xml:lang="pl">Rozmawiaj ze swoimi znajomymi w Matriksie</summary>
|
<summary xml:lang="ko">Matrix에서 대화하기</summary>
|
||||||
<summary xml:lang="sl">Klepet z vašimi prijatelji na matrixu</summary>
|
<summary xml:lang="lv">Tērzējiet „Matrix“ tīklā</summary>
|
||||||
<summary xml:lang="sv">Chatta med dina vänner på Matrix</summary>
|
<summary xml:lang="nl">Chat op Matrix</summary>
|
||||||
<summary xml:lang="ta">மேட்ரிக்ஸு மூலம் உங்கள் நண்பர்களிடம் பேசலாம்</summary>
|
<summary xml:lang="nn">Prat med via Matrix</summary>
|
||||||
<summary xml:lang="tr">Matrix’te arkadaşlarınızla sohbet edin</summary>
|
<summary xml:lang="pl">Rozmawiaj na Matriksie</summary>
|
||||||
<summary xml:lang="uk">Спілкуйтеся з вашими друзями у matrix</summary>
|
<summary xml:lang="pt-BR">Bate-papo na Matrix</summary>
|
||||||
<summary xml:lang="x-test">xxChat with your friends on matrixxx</summary>
|
<summary xml:lang="ru">Общение в Matrix</summary>
|
||||||
<summary xml:lang="zh-CN">在 Matrix 上与朋友聊天</summary>
|
<summary xml:lang="sa">Matrix इत्यत्र गपशपं कुर्वन्तु</summary>
|
||||||
<summary xml:lang="zh-TW">在 Matrix 上與您的朋友聊天</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>
|
<description>
|
||||||
<p>NeoChat is a client for Matrix, the decentralized communication protocol for instant messaging. It allows you to send text messages, videos and audio files to your family, colleagues and friends. It uses KDE frameworks and most notably Kirigami
|
<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>
|
||||||
to provide a convergent experience across multiple platforms.</p>
|
<p xml:lang="ar">نيوتشات هو تطبيق دردشة يتيح لك الاستفادة الكاملة من شبكة Matrix. فهو يوفر لك طريقة آمنة لإرسال الرسائل النصية ومقاطع الفيديو والملفات الصوتية إلى عائلتك وزملائك وأصدقائك.</p>
|
||||||
<p xml:lang="ar">نيوتشات هو عميل ماتركس Matrix، (ميفاق الاتصال اللامركزي للمراسلة الفورية). يتيح لك نيوتشات إرسال رسائل نصية ومقاطع فيديو وملفات صوتية إلى عائلتك وزملائك وأصدقائك. يستخدم أطر عمل كيدي وأبرزها Kirigami لتوفير تجربة متقاربة عبر منصات متعددة.</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">El NeoChat és un client de Matrix, el protocol descentralitzat de comunicacions de missatgeria instantània. Permet enviar missatges de text, fitxers de vídeo i d'àudio a la família, col·legues i amics. Fa servir els Frameworks de KDE i, sobretot, el Kirigami per a proporcionar una experiència convergent a través de diverses plataformes.</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="ca-valencia">NeoChat és un client de Matrix, el protocol descentralitzat de comunicacions de missatgeria instantània. Permet enviar missatges de text, fitxers de vídeo i d'àudio a la família, col·legues i amics. Utilitza els Frameworks de KDE i, sobretot, Kirigami per a proporcionar una experiència convergent a través de diverses plataformes.</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="en-GB">NeoChat is a client for Matrix, the decentralised communication protocol for instant messaging. It allows you to send text messages, videos and audio files to your family, colleagues and friends. It uses KDE frameworks and most notably Kirigami to provide a convergent experience across multiple platforms.</p>
|
<p xml:lang="el">Το NeoChat είναι μια εφαρμογή συνομιλίας που σας επιτρέπει να εκμεταλλευτείτε πλήρως το δίκτυο Matrix. Σας παρέχει έναν ασφαλή τρόπο να στέλνετε μηνύματα κειμένου, βίντεο και αρχεία ήχου στην οικογένεια, τους συναδέλφους και τους φίλους σας.</p>
|
||||||
<p xml:lang="eo">NeoChat estas kliento por Matrix, la malcentra komunikoprotokolo por tuja mesaĝado. Ĝi ebligas al vi sendi tekstmesaĝojn, filmetojn kaj sondosierojn al via familio, kolegoj kaj amikoj. Ĝi uzas KDE-framojn kaj precipe Kirigami por disponigi konverĝan sperton tra pluraj platformoj.</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="es">NeoChat es un cliente para Matrix, el protocolo de comunicaciones descentralizado para mensajería instantánea. Le permite enviar mensajes de texto, vídeos y archivos de sonido a su familia, compañeros de trabajo y amigos. Usa la infraestructura de KDE y, en particular, Kirigami para proporcionar una experiencia convergente en muchas plataformas.</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="eu">NeoChat «Matrix»erako, bat-bateko mezularitzarako komunikazio deszentralizatuko protokolorako, bezero bat da. Zure sendiari, kide eta lagunei testu mezuak, bideo eta audio fitxategiak bidaltzeko aukera ematen dizu. «KDE Frameworks» eta bereziki «Kirigami» erabiltzen ditu plataforma anitzen artean esperientzia konbergente bat eskaintzeko.</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>
|
||||||
<p xml:lang="fi">NeoChat on asiakassovellus Matrixille, hajautetulle pikaviestinyhteyskäytännölle. Sillä voi lähettää teksti-, video- ja ääniviestejä perheelle, tutuille ja ystäville. Se käyttää KDE-kehystä ja erityisesti Kirigamia tuottaakseen mukautuvan monialustaisen käyttökokemuksen.</p>
|
<p xml:lang="eu">NeoChat, Matrix sarearen abantaila guztiei probetsua ateratzeko aukera ematen dizun berriketa aplikaizo bat da. Zure familiari, kideei eta lagunei testu mezuak, bideoak eta audio fitxategiak era seguruan bidaltzeko aukera ematen dizu.</p>
|
||||||
<p xml:lang="fr">NeoChat est un client pour le protocole Matrix, un protocole décentralisé de communications pour messagerie instantané. Il vous permet d'envoyer des messages de texte, des vidéos et des fichiers audio à votre famille, vos collègues et vos amis. Il utilise les environnements de développement et plus précisément Kirigami pour fournir une expérience convergente sur plusieurs plate-formes. </p>
|
<p xml:lang="fi">NeoChat on keskustelusovellus, jolla Matrix-verkosta saa täyden hyödyn. Se tarjoaa salatun kanavan lähettää perheelle, työkavereille ja ystäville tekstiviestejä sekä video- ja äänitiedostoja.</p>
|
||||||
<p xml:lang="gl">NeoChat é un cliente para Matrix, o protocolo de comunicación descentralizada para mensaxaría instantánea. Podes enviar mensaxes de texto, vídeos e ficheiros de son á túa familia, colegas e amizades. Usas infraestruturas de KDE e principalmente Kirigami para proporcionar unha experiencia de uso converxente para varias plataformas.</p>
|
<p xml:lang="fr">NeoChat est une application de discussions vous permettant de profiter pleinement du réseau Matrix. Elle vous offre un moyen sécurisé d'envoyer des messages de texte, des vidéos et des fichiers audio à votre famille, vos collègues et vos ami(e)s.</p>
|
||||||
<p xml:lang="hu">A NeoChat egy kliens a Matrixhoz, az azonnali üzenetküldés decentralizált komunikációs protokolljához. Szöveges üzeneteket, videókat és hangfájlokat küldhet családjának, kollégáinak és barátainak. A KDE keretrendszert használja, a Kirigaminak köszönhetően konvergens élményt nyújt több platformon is.</p>
|
<p xml:lang="gl">NeoChat é unha aplicación de conversa que lle permite usar todas as funcionalidades da rede Matrix. Fornece unha forma segura de enviar mensaxes de texto e ficheiros de vídeo e son a familiares, amizades ou no traballo.</p>
|
||||||
<p xml:lang="ia">NeoChat es un cliente per Matrix, le protocollo de communication decentralisate per messager instantanee. Illo te permitte inviar messager de texto, files de video e audio a tu familia, collegas e amicos usante. Illo usa KDE frameworks e super toto Kirigamii forni un experientia convergente trans platteforme multiple.</p>
|
<p xml:lang="he">NeoChat הוא יישום התכתבות שמאפשר לך לנצל את רשת Matrix במלואה. הוא מספק דרך מאובטחת לשליחת הודעות כתובות, סרטונים וקובצי שמע למשפחה, לעמיתים לעבודה ולחברים.</p>
|
||||||
<p xml:lang="it">NeoChat è un client per Matrix, il protocollo di comunicazione decentralizzato per la messaggistica istantanea. Ti consente di inviare messaggi di testo, video e file audio a familiari, colleghi e amici. Utilizza i framework KDE e in particolare Kirigami per fornire un'esperienza convergente su più piattaforme.</p>
|
<p xml:lang="hi">नियोचैट एक चैट ऐप है जो आपको मैट्रिक्स नेटवर्क का पूरा लाभ उठाने देता है। यह आपको अपने परिवार, सहकर्मियों और दोस्तों को टेक्स्ट संदेश, वीडियो और ऑडियो फ़ाइलें भेजने का एक सुरक्षित तरीका प्रदान करता है।</p>
|
||||||
<p xml:lang="ka">NeoChat არის Matrix კლიენტი. ის საშუალებას გაძლევთ გაგზავნოთ ტექსტური შეტყობინებები, ვიდეოები და აუდიო ფაილები თქვენს ოჯახს, კოლეგებსა და მეგობრებს მატრიქსის პროტოკოლის გამოყენებით.</p>
|
<p xml:lang="hu">A NeoChat egy olyan csevegőalkalmazás, amellyel teljes mértékben kihasználhatja a Matrix hálózatot. Biztonságos módot biztosít szöveges üzenetek, videók és hangfájlok küldéséhez családtagjainak, kollégáinak és barátainak.</p>
|
||||||
<p xml:lang="ko">NeoChat은 분산형 인스턴트 메시징 통신 프로토콜인 Matrix 클라이언트입니다. 가족, 동료, 친구에게 텍스트 메시지, 동영상, 오디오 파일을 전송할 수 있습니다. KDE 프레임워크와 Kirigami를 사용하여 다양한 플랫폼에서 일관적인 사용자 경험을 제공합니다.</p>
|
<p xml:lang="ia">NeoChat es un app de conversation que te permitte prender avantage plen del rete Matrix. Il te forni un modo secur de inviar messages de texto, videos e files audio a tui familia, collegas e amicos.</p>
|
||||||
<p xml:lang="nl">NeoChat is een client voor Matrix, het gedecentraliseerde communicatieprotocol voor instant messages. Het biedt u het verzenden van tekstberichten, video's en geluidsbestanden naar uw familie, collega's en vrienden. Het gebruik KDE frameworks en het meest opmerkelijk Kirigami om een convergente ervaring te leveren op meerdere platforms.</p>
|
<p xml:lang="it">NeoChat è un'applicazione di chat che ti consente di sfruttare appieno la rete Matrix. Ti fornisce un modo sicuro per inviare messaggi di testo, video e file audio a familiari, colleghi e amici.</p>
|
||||||
<p xml:lang="nn">NeoChat er ein klient for Matrix, ein protokoll for desentralisert kommunikasjon. Du kan utveksla tekst, lyd og videoar med kollegaar, vennar og familie. Programmet brukar KDE Frameworks og Kirigami for å gje ei brukarflate tilpassa ulike plattformer.</p>
|
<p xml:lang="ka">NeoChat ჩატის აპია, რომელიც საშუალება გაძლევთ, Matrix-ის ქსელის საშუალებები ბოლომდე გამოიყენოთ. ის გაძლევთ უსაფრთხო გზას, გააგზავნოთ ტექსტური შეტყობინებები, ვიდეოებ და აუდიოფაილები თქვენს ოჯახთან, კოლეგებთან და მეგობრებთან.</p>
|
||||||
<p xml:lang="pl">NeoChat jest programem do Matriksa, protokołu rozproszonego porozumiewania się w czasie rzeczywistym. Umożliwia wysyłanie wiadomości tekstowych, filmów oraz dźwięku do twojej rodziny, znajomych oraz przyjaciół. Używa szkieletów KDE i głównie Kirigami, aby zapewnić spójne wrażenia na wielu platformach</p>
|
<p xml:lang="ko">NeoChat은 Matrix 네트워크를 사용하는 채팅 앱입니다. 텍스트 메시지, 동영상, 오디오 파일을 가족, 친구, 동료와 안전하게 공유할 수 있습니다.</p>
|
||||||
<p xml:lang="pt">O NeoChat é um cliente do Matrix. O mesmo permite-lhe enviar mensagens de texto, ficheiros de vídeo e áudio para a sua família, colegas e amigos com o protocolo Matrix. Usa as plataformas do KDE, e principalmente o Kirigami, para oferecer uma experiência convergente entre várias plataformas.</p>
|
<p xml:lang="lv">„NeoChat“ ir tērzēšanas programma, kas ļauj pilnvērtīgi izmantot „Matrix“ tīklu. Tā sniedz drošu veidu teksta ziņu, video un audio sūtīšanai ģimenes locekļiem, kolēģiem un draugiem.</p>
|
||||||
<p xml:lang="sl">Neochat je odjemalec za Matrix, decentralizirani komunikacijski protokol za takojšnje sporočanje. Omogoča vam pošiljanje besedilnih sporočil, videoposnetkov in zvočnih datotek svoji družini, sodelavcem in prijateljem. Uporablja okvire ogrodje KDE frameworks in predvsem Kirigami za zagotavljanje konvergentne izkušnje na več platformah.</p>
|
<p xml:lang="nl">NeoChat is een chat-toepassing die u het volledige voordeel van het Matrix-netwerk laat genieten. Het levert u op een veilige manier tekstberichten, video's en geluidsbestanden naar uw familie, collega's en vrienden te verzenden.</p>
|
||||||
<p xml:lang="sv">NeoChat är en klient för Matrix, det decentraliserade kommunikationsprotokollet för direktmeddelanden. Den låter dig skicka textmeddelanden, videor och ljudfiler till din familj, kollegor och vänner. Den använder KDE Ramverk, i synnerhet Kirigami, för att tillhandahålla en konvergent upplevelse på flera plattformar.</p>
|
<p xml:lang="nn">NeoChat er ein prateapp som lèt deg bruka all funksjonalitet i Matrix-nettverket. Du kan utveksla tekst, lyd og videoar med vennar, familie og kollegaar på ein trygg måte.</p>
|
||||||
<p xml:lang="tr">NeoChat, anlık iletileşme için merkezi olmayan iletişim protokolü olan Matrix için bir istemcidir. Ailenize, iş arkadaşlarınıza ve arkadaşlarınıza metin iletiler, videolar ve ses dosyaları göndermenize olanak tanır. Birden çok platformda yakınsak bir deneyim sağlamak için KDE Frameworks ve en önemlilerinden Kirigami'yi kullanır.</p>
|
<p xml:lang="pl">NoeChat to aplikacja do rozmów, która umożliwia wykorzystanie wszystkich możliwości Matriksa. Umożliwia wysyłanie wiadomości tekstowych, filmów i dźwięków w bezpieczny sposób do twojej rodziny, kolegów i przyjaciół.</p>
|
||||||
<p xml:lang="uk">NeoChat — клієнт Matrix, децентралізованого протоколу спілкування для миттєвого обміну повідомленнями. За його допомогою ви можете надсилати текстові повідомлення, відео та звукові файли вашій родин, колегами та друзям. У програмі використано бібліотеки KDE, зокрема Kirigami, для надання однорідного середовища на декількох програмних та апаратних платформах.</p>
|
<p xml:lang="pt-BR">O NeoChat é um aplicativo de bate-papo que permite que você aproveite ao máximo a rede Matrix. Ele oferece uma maneira segura de enviar mensagens de texto, vídeos e arquivos de áudio para sua família, colegas e amigos.</p>
|
||||||
<p xml:lang="x-test">xxNeoChat is a client for Matrix, the decentralized communication protocol for instant messaging. It allows you to send text messages, videos and audio files to your family, colleagues and friends. It uses KDE frameworks and most notably Kirigami to provide a convergent experience across multiple platforms.xx</p>
|
<p xml:lang="ru">NeoChat — приложение для общения, предоставляющее все преимущества сети Matrix. С его помощью можно безопасно отправлять текстовые сообщения, видеозаписи и звуковые файлы родственникам, коллегам и друзьям.</p>
|
||||||
<p xml:lang="zh-TW">NeoChat 是去中心化即時通訊協定 Matrix 的一個用戶端。它讓您可以傳送文字訊息、影片、音訊檔案給您的家人、同事或朋友。NeoChat 使用 KDE frameworks,尤其是 Kirigami,來提供跨平台的響應式體驗。</p>
|
<p xml:lang="sa">NeoChat इति एकं गपशप-अनुप्रयोगं यत् भवान् Matrix-जालस्य पूर्णं लाभं ग्रहीतुं शक्नोति । एतत् भवन्तं भवतः परिवाराय, सहकारिभ्यः, मित्रेभ्यः च पाठसन्देशान्, भिडियो, श्रव्यसञ्चिकाः च प्रेषयितुं सुरक्षितं मार्गं प्रदाति ।</p>
|
||||||
|
<p xml:lang="sl">NeoChat je aplikacija za klepet, ki vam omogoča, da v celoti izkoristite omrežje Matrix. Zagotavlja vam varen način za pošiljanje besedilnih sporočil, videoposnetkov in zvočnih datotek vaši družini, sodelavcem in prijateljem.</p>
|
||||||
|
<p xml:lang="sv">NeoChat är ett chattprogram som låter dig dra full nytta av Matrix-nätverket. Det ger dig ett säkert sätt att skicka textmeddelanden, videor och ljudfiler till din familj, kollegor och vänner.</p>
|
||||||
|
<p xml:lang="tr">NeoChat, Matrix ağının tüm özelliklerini kullanan bir sohbet uygulamasıdır. Ailenize, arkadaşlarınıza ve iş arkadaşlarınıza metin iletileri, ses ve video dosyaları göndermenin kolay bir yolunu sunar.</p>
|
||||||
|
<p xml:lang="uk">NeoChat є програмою для спілкування, за допомогою якої ви можете скористатися усіма перевагами мережі Matrix. За її допомогою ви можете безпечно надсилати текстові повідомлення, відео та звукові файли вашим родичам, колегам та друзям.</p>
|
||||||
|
<p xml:lang="x-test">xxNeoChat 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.xx</p>
|
||||||
|
<p xml:lang="zh-TW">NeoChat 是一個讓您能夠完全利用 Matrix 網路的聊天應用程式。它讓您安全地傳送文字訊息、影片或音訊檔給家人、同事或朋友等等。</p>
|
||||||
<p>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>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="ar">يهدف نيوتشات إلى أن يكون تطبيقًا كامل الميزات لمواصفات ماتركس. على هذا النحو يتم دعم كل شيء في المواصفات المستقرة الحالية مع الاستثناءات الملحوظة لـ VoIP والخيوط وبعض جوانب التشفير من طرف إلى طرف. هناك عدد قليل من الإغفالات الصغيرة الأخرى بسبب حقيقة أن مواصفات ماتركس تتطور باستمرار ، ولكن يبقى الهدف توفير الدعم النهائي للمواصفات بأكملها.</p>
|
<p xml:lang="ar">يهدف نيوتشات إلى أن يكون تطبيقًا كامل الميزات لمواصفات ماتركس. يوفر نيوتشات كل شيء في المواصفات المستقرة الحالية مع الاستثناءات الملحوظة لـ VoIP و تعدد الخيوط وبعض جوانب التشفير من طرف إلى طرف. هناك عدد قليل من الإغفالات الصغيرة الأخرى بسبب حقيقة أن مواصفات ماتركس تتطور باستمرار، ولكن يبقى الهدف توفير الدعم النهائي للمواصفات بأكملها.</p>
|
||||||
<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">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="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="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="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="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="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="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="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="hi">नियोचैट का लक्ष्य मैट्रिक्स विनिर्देश के लिए एक पूर्ण विशेषताओं वाला अनुप्रयोग बनना है। इस प्रकार वर्तमान स्थिर विनिर्देश में वीओआईपी, थ्रेड्स और एंड-टू-एंड एन्क्रिप्शन के कुछ पहलुओं के उल्लेखनीय अपवादों के साथ सब कुछ समर्थित है। मैट्रिक्स विनिर्देश लगातार विकसित हो रहा है, इस तथ्य के कारण कुछ अन्य छोटी चूकें हैं, लेकिन उद्देश्य पूरे विनिर्देश के लिए अंतिम समर्थन प्रदान करना है।</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="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 plenemente 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>
|
<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>
|
||||||
<p xml:lang="it">NeoChat mira ad essere un'applicazione completa per le specifiche Matrix. Pertanto, sono supportati tutti gli elementi dell'attuale specifica stabile con le notevoli eccezioni di VoIP, conversazioni e alcuni aspetti della cifratura end-to-end. Ci sono alcune altre piccole omissioni dovute al fatto che le specifiche Matrix sono in continua evoluzione, ma l'obiettivo rimane quello di fornire un eventuale supporto per l'intera specifica.</p>
|
<p xml:lang="it">NeoChat mira ad essere un'applicazione completa per le specifiche Matrix. Pertanto, sono supportati tutti gli elementi dell'attuale specifica stabile con le notevoli eccezioni di VoIP, conversazioni e alcuni aspetti della cifratura end-to-end. Ci sono alcune altre piccole omissioni dovute al fatto che le specifiche Matrix sono in continua evoluzione, ma l'obiettivo rimane quello di fornire un eventuale supporto per l'intera specifica.</p>
|
||||||
<p xml:lang="ka">NeoChat-ი მიზნად ისახავს Matrix სპეციფიკაციის სრული განხორციელება ჰქონდეს. როგორც ასეთი, ყველაფერი მიმდინარე სპეციფიკაციიდან, VoIP-ის, ძაფებისა და გამჭოლი დაშიფვრის ზოგიერთი ასპექტის გარდა, მხარდაჭერილია. შეძლება ასევე იყოს მცირე ლაფსუსებიც იმის გამო, რომ Matrix-ის სპეციფიკაცია მუდმივად ვითარგდება, მაგრამ ჩვენი მიზანი მისი სრული მხარდაჭერაა.</p>
|
<p xml:lang="ka">NeoChat მიზნად ისახავს Matrix სპეციფიკაციის სრული განხორციელება ჰქონდეს. როგორც ასეთი, ყველაფერი მიმდინარე სპეციფიკაციიდან, VoIP-ის, ძაფებისა და გამჭოლი დაშიფვრის ზოგიერთი ასპექტის გარდა, მხარდაჭერილია. შეძლება ასევე იყოს მცირე ლაფსუსებიც იმის გამო, რომ Matrix-ის სპეციფიკაცია მუდმივად ვითარდება, მაგრამ ჩვენი მიზანი მისი სრული მხარდაჭერაა.</p>
|
||||||
<p xml:lang="ko">NeoChat은 Matrix 표준을 따르는 프로그램을 목표로 합니다. 현재 안정 버전의 표준에서 제공하는 기능의 대부분을 지원하며, VoIP, 스레드, 일부 종단간 암호화와 같은 기능은 아직 지원하지 않습니다. Matrix 표준은 계속하여 진화 중이기 때문에 일부 기능이 빠져 있을 수도 있지만 장기적으로는 전체 표준을 지원하는 것이 목표입니다.</p>
|
<p xml:lang="ko">NeoChat은 Matrix 표준을 따르는 프로그램을 목표로 합니다. 현재 안정 버전의 표준에서 제공하는 기능의 대부분을 지원하며, VoIP, 스레드, 일부 종단간 암호화와 같은 기능은 아직 지원하지 않습니다. Matrix 표준은 계속하여 진화 중이기 때문에 일부 기능이 빠져 있을 수도 있지만 장기적으로는 전체 표준을 지원하는 것이 목표입니다.</p>
|
||||||
|
<p xml:lang="lv">„NeoChat“ mērķis ir piedāvāt plašas iespējas atbilstoši „Matrix“ specifikācijai. Līdz ar to programma atbalsta visu pašreizējā stabilajā specifikācijā, izņemot VoIP, pavedienus un dažos aspektos galšifrēšanu. Pastāv citas atsevišķas sīkas neieviestas daļas, jo „Matrix“ specifikācija nepārtraukti attīstās, tomēr mērķis ir ar laiku nodrošināt atbalstu pilnai specifikācijai.</p>
|
||||||
<p xml:lang="nl">NeoChat richt zich op het volledig bieden van alle mogelijkheden van de Matrix-specificatie. Alles in de huidige stabiele specificatie met merkbare uitzondering van VoIP, gekoppelde discussies en sommige aspecten van eind-tot-eind versleuteling worden ondersteund. Er zijn een paar andere kleinere omissies vanwege het feit dat de Matrix specificatie constant evolueert maar het doel blijft het eventueel bieden van ondersteuning van de gehele specificatie.</p>
|
<p xml:lang="nl">NeoChat richt zich op het volledig bieden van alle mogelijkheden van de Matrix-specificatie. Alles in de huidige stabiele specificatie met merkbare uitzondering van VoIP, gekoppelde discussies en sommige aspecten van eind-tot-eind versleuteling worden ondersteund. Er zijn een paar andere kleinere omissies vanwege het feit dat de Matrix specificatie constant evolueert maar het doel blijft het eventueel bieden van ondersteuning van de gehele specificatie.</p>
|
||||||
<p xml:lang="nn">NeoChat har som mål å støtta all funksjonalitet i Matrix-spesifikasjonen. Førebels er alt i den gjeldande stabile spesifikasjonen støtta, med unntak av VoIP, trådar og nokre delar av ende-til-kryptering. Det finst òg andre småting som ikkje er støtta, sidan Matrix-spesifikasjon er i stadig endring, men målet er altså støtte for alt.</p>
|
<p xml:lang="nn">NeoChat har som mål å støtta all funksjonalitet i Matrix-spesifikasjonen. Førebels er alt i den gjeldande stabile spesifikasjonen støtta, med unntak av VoIP, trådar og nokre delar av ende-til-kryptering. Det finst òg andre småting som ikkje er støtta, sidan Matrix-spesifikasjon er i stadig endring, men målet er altså støtte for alt.</p>
|
||||||
<p xml:lang="pl">NeoChat w zamyśle ma być pełnowartościową aplikacją wg wytycznych Matriksa. Z tego powodu, wszystko, co jest obecnie w stabilnych wytycznych z pominięciem VoIP, wątków i niektórych części szyfrowania Użytkownik-do-Użytkownika są obecnie obsługiwane. Pominięto też kilka mniejszych rzeczy ze względu na ciągły rozwój wytycznych Matriksa, lecz celem nadal jest zapewnienie obsługi wszystkich wytycznych.</p>
|
<p xml:lang="pl">NeoChat w zamyśle ma być pełnowartościową aplikacją wg wytycznych Matriksa. Z tego powodu, wszystko, co jest obecnie w stabilnych wytycznych z pominięciem VoIP, wątków i niektórych części szyfrowania Użytkownik-do-Użytkownika są obecnie obsługiwane. Pominięto też kilka mniejszych rzeczy ze względu na ciągły rozwój wytycznych Matriksa, lecz celem nadal jest zapewnienie obsługi wszystkich wytycznych.</p>
|
||||||
<p xml:lang="pt">O NeoChat pretende ser uma aplicação completa para a especificação do Matrix. Como tal, tudo o que existe na especificação estável actual, com as notáveis excepções do VoIP, tópicos e alguns aspectos da Encriptação Ponto-a-Ponto, são suportados. Existem mais algumas omissões, devido ao facto que a norma do Matrix está em constante evolução, mas o objectivo continua a ser oferecer o suporte eventual para a norma por inteiro.</p>
|
<p xml:lang="pt">O NeoChat pretende ser uma aplicação completa para a especificação do Matrix. Como tal, tudo o que existe na especificação estável actual, com as notáveis excepções do VoIP, tópicos e alguns aspectos da Encriptação Ponto-a-Ponto, são suportados. Existem mais algumas omissões, devido ao facto que a norma do Matrix está em constante evolução, mas o objectivo continua a ser oferecer o suporte eventual para a norma por inteiro.</p>
|
||||||
|
<p xml:lang="pt-BR">O NeoChat pretende ser um aplicativo completo para a especificação Matrix. Dessa forma, tudo na especificação estável atual, com as notáveis exceções de VoIP, tópicos e alguns aspectos da criptografia de ponta a ponta, é suportado. Há algumas outras pequenas omissões devido ao fato de a especificação Matrix estar em constante evolução, mas o objetivo continua sendo fornecer suporte eventual para toda a especificação.</p>
|
||||||
|
<p xml:lang="ru">Целью создания NeoChat является полноценная реализация программы для спецификации Matrix. Как следствие, реализовано всё в текущей стабильной спецификации (за исключением голосовой интернет-связи, потоков и некоторых аспектов сквозного шифрования). Есть также несколько других незначительных пробелов, обусловленных постоянными изменениями спецификации Matrix. Тем не менее, стоит задача в итоге предоставить полную поддержку спецификации.</p>
|
||||||
|
<p xml:lang="sa">NeoChat इत्यस्य उद्देश्यं Matrix विनिर्देशस्य कृते पूर्णतया विशेषतायुक्तः अनुप्रयोगः भवितुम् अस्ति । यथा तथा वर्तमानस्थिरविनिर्देशे सर्वं VoIP इत्यस्य उल्लेखनीयअपवादैः सह, थ्रेड्स तथा च End-to-End Encryption इत्यस्य केचन पक्षाः समर्थिताः सन्ति । अन्ये कतिचन लघु लोपाः सन्ति यतोहि Matrix spec निरन्तरं विकसितः अस्ति परन्तु उद्देश्यं सम्पूर्ण spec कृते अन्ततः समर्थनं प्रदातुं अवशिष्टम् अस्ति</p>
|
||||||
<p xml:lang="sl">Neochat cilja, da bi bila popolna aplikacija po specifikaciji Matrixa. Kot takšna vsebuje vse v trenutni stabilni specifikaciji z pomembnimi izjemami pri VoIP, nitih in nekaterih vidikov šifriranja od konca do konca. Obstaja nekaj drugih manjših opustitev zaradi dejstva, da se specifikacija Matrix nenehno razvija, vendar cilj ostaja zagotoviti morebitno podporo celotni specifikaciji.</p>
|
<p xml:lang="sl">Neochat cilja, da bi bila popolna aplikacija po specifikaciji Matrixa. Kot takšna vsebuje vse v trenutni stabilni specifikaciji z pomembnimi izjemami pri VoIP, nitih in nekaterih vidikov šifriranja od konca do konca. Obstaja nekaj drugih manjših opustitev zaradi dejstva, da se specifikacija Matrix nenehno razvija, vendar cilj ostaja zagotoviti morebitno podporo celotni specifikaciji.</p>
|
||||||
<p xml:lang="sv">NeoChat har som mål att vara ett fullständigt program enligt Matrix-specifikationen. Som sådant stöds allt i den nuvarande stabila specifikationen, med de nämnvärda undantagen VoIP, trådar och några aspekter av kryptering hela vägen. Det finns några ytterligare utelämnanden på grund av att Matrix-specifikationen hela tiden utvecklas, men målet förblir att till slut erbjuda stöd för hela specifikationen.</p>
|
<p xml:lang="sv">NeoChat har som mål att vara ett fullständigt program enligt Matrix-specifikationen. Som sådant stöds allt i den nuvarande stabila specifikationen, med de nämnvärda undantagen VoIP, trådar och några aspekter av kryptering hela vägen. Det finns några ytterligare utelämnanden på grund av att Matrix-specifikationen hela tiden utvecklas, men målet förblir att till slut erbjuda stöd för hela specifikationen.</p>
|
||||||
<p xml:lang="tr">NeoChat, Matrix belirtimi için tam özellikli bir uygulama olmayı hedefler. Bu nedenle; VoIP, ileti zincirleri ve Uçtan Uca Şifreleme’nin bazı yönleri gibi dikkate değer istisnalar dışında var olan kararlı belirtimdeki her şey desteklenir. Matrix belirtiminin sürekli gelişmesi nedeniyle birkaç küçük eksiklik daha var; ancak amaç tüm belirtim için nihai destek sağlamak olmayı sürdürüyor.</p>
|
<p xml:lang="tr">NeoChat, Matrix belirtimi için tam özellikli bir uygulama olmayı hedefler. Bu nedenle; VoIP, ileti zincirleri ve Uçtan Uca Şifreleme’nin bazı yönleri gibi dikkate değer istisnalar dışında var olan kararlı belirtimdeki her şey desteklenir. Matrix belirtiminin sürekli gelişmesi nedeniyle birkaç küçük eksiklik daha var; ancak amaç tüm belirtim için nihai destek sağlamak olmayı sürdürüyor.</p>
|
||||||
@@ -133,6 +157,8 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<p xml:lang="ar">نظرًا لطبيعة تطوير مواصفات ماتركس، يدعم نيوتشات أيضًا العديد من الميزات غير المستقرة وهي:</p>
|
<p xml:lang="ar">نظرًا لطبيعة تطوير مواصفات ماتركس، يدعم نيوتشات أيضًا العديد من الميزات غير المستقرة وهي:</p>
|
||||||
<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">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="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="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="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>
|
<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>
|
||||||
@@ -140,15 +166,21 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<p xml:lang="fi">Matrix-määritelmän kehittyessä NeoChat tukee myös monia epävakaita ominaisuuksia. Tällä hetkellä näitä ovat:</p>
|
<p xml:lang="fi">Matrix-määritelmän kehittyessä NeoChat tukee myös monia epävakaita ominaisuuksia. Tällä hetkellä näitä ovat:</p>
|
||||||
<p xml:lang="fr">En raison de la nature du développement des spécifications du protocole Matrix, NeoChat prend également en charge de nombreuses fonctionnalités instables. Actuellement, ce sont :</p>
|
<p xml:lang="fr">En raison de la nature du développement des spécifications du protocole Matrix, NeoChat prend également en charge de nombreuses fonctionnalités instables. Actuellement, ce sont :</p>
|
||||||
<p xml:lang="gl">Debido á natureza do desenvolvemento da especificación de Matrix, NeoChat tamén inclúe varias funcionalidades non estábeis:</p>
|
<p xml:lang="gl">Debido á natureza do desenvolvemento da especificación de Matrix, NeoChat tamén inclúe varias funcionalidades non estábeis:</p>
|
||||||
|
<p xml:lang="he">מטבע הדברים, הפיתוח של NeoChat תומך במגוון יכולות מפוקפקות כתלות בהתפתחות המפרט הטכני של Matrix. היכולות האלה הן:</p>
|
||||||
|
<p xml:lang="hi">मैट्रिक्स विनिर्देश विकास की प्रकृति के कारण नियोचैट कई अस्थिर सुविधाओं का भी समर्थन करता है। वर्तमान में ये हैं:</p>
|
||||||
<p xml:lang="hu">A Matrix specifikáció fejlesztésének jellegéből adódóan a NeoChat számos instabil funkciót is támogat. Jelenleg a következőket:</p>
|
<p xml:lang="hu">A Matrix specifikáció fejlesztésének jellegéből adódóan a NeoChat számos instabil funkciót is támogat. Jelenleg a következőket:</p>
|
||||||
<p xml:lang="ia">Debite al natura del disveloppamento de specification de Matrix NeoChat tamben supporta numerose characteristicas instabile. Currentemente istes es:</p>
|
<p xml:lang="ia">Debite al natura del disveloppamento de specification de Matrix NeoChat tamben supporta numerose characteristicas instabile. Currentemente istes es:</p>
|
||||||
<p xml:lang="it">A causa della natura dello sviluppo delle specifiche Matrix, NeoChat supporta anche numerose funzionalità instabili. Attualmente queste sono:</p>
|
<p xml:lang="it">A causa della natura dello sviluppo delle specifiche Matrix, NeoChat supporta anche numerose funzionalità instabili. Attualmente queste sono:</p>
|
||||||
<p xml:lang="ka">Matrix-ის სპეციფიკაციის განვითარების ბუნების გამო NeoChat-ს ასევე აქვს უამრავი არასტაბილური ფუნქციაც. ახლა ისინია:</p>
|
<p xml:lang="ka">Matrix-ის სპეციფიკაციის განვითარების ბუნების გამო NeoChat-ს ასევე აქვს უამრავი არასტაბილური ფუნქციაც. ახლა ისინია:</p>
|
||||||
<p xml:lang="ko">Matrix 표준 개발의 특징으로 인하여 NeoChat은 일부 실험적인 기능을 지원합니다. 현재 지원하는 기능은 다음과 같습니다.</p>
|
<p xml:lang="ko">Matrix 표준 개발의 특징으로 인하여 NeoChat은 일부 실험적인 기능을 지원합니다. 현재 지원하는 기능은 다음과 같습니다.</p>
|
||||||
|
<p xml:lang="lv">„Matrix“ specifikācijas veida dēļ „NeoChat“ attīstība atbalsta arī vairākas nestabilas iespējas, šobrīd šādas ir:</p>
|
||||||
<p xml:lang="nl">Vanwege de aard van de ontwikkeling van de Matrix specificatie ondersteunt NeoChat ook talloze onstabiele mogelijkheden. Dit zijn nu:</p>
|
<p xml:lang="nl">Vanwege de aard van de ontwikkeling van de Matrix specificatie ondersteunt NeoChat ook talloze onstabiele mogelijkheden. Dit zijn nu:</p>
|
||||||
<p xml:lang="nn">På grunn av måten Matrix-spesifikasjonen vert utvikla på, støttar NeoChat òg nokre uferdige funksjonar:</p>
|
<p xml:lang="nn">På grunn av måten Matrix-spesifikasjonen vert utvikla på, støttar NeoChat òg nokre uferdige funksjonar:</p>
|
||||||
<p xml:lang="pl">Ze względu na sposób rozwoju Matriksa, NeoChat obsługuje także kilka niestabilnych możliwości. Obecnie są to:</p>
|
<p xml:lang="pl">Ze względu na sposób rozwoju Matriksa, NeoChat obsługuje także kilka niestabilnych możliwości. Obecnie są to:</p>
|
||||||
<p xml:lang="pt">Devido à natureza do desenvolvimento da especificação do Matrix, o NeoChat também suporta diversas funcionalidades instáveis. De momento são:</p>
|
<p xml:lang="pt">Devido à natureza do desenvolvimento da especificação do Matrix, o NeoChat também suporta diversas funcionalidades instáveis. De momento são:</p>
|
||||||
|
<p xml:lang="pt-BR">Devido à natureza do desenvolvimento da especificação Matrix, o NeoChat também suporta diversos recursos instáveis. Atualmente, são eles:</p>
|
||||||
|
<p xml:lang="ru">В силу природы разработки спецификации Matrix в NeoChat тоже предусмотрена поддержка многочисленных нестабильных возможностей. В текущей версии это следующие возможности:</p>
|
||||||
|
<p xml:lang="sa">Matrix विनिर्देशविकासस्य प्रकृतेः कारणात् NeoChat अपि अनेकानाम् अस्थिरविशेषतानां समर्थनं करोति । सम्प्रति एते सन्ति :</p>
|
||||||
<p xml:lang="sl">Zaradi narave razvoja specifikacije Matrixa NeoChat podpira tudi številne nestabilne zmožnosti. Trenutno so to:</p>
|
<p xml:lang="sl">Zaradi narave razvoja specifikacije Matrixa NeoChat podpira tudi številne nestabilne zmožnosti. Trenutno so to:</p>
|
||||||
<p xml:lang="sv">På grund av sättet Matrix-specifikationens utvecklas, stöder NeoChat också ett stor antal instabila funktioner. För närvarande är de:</p>
|
<p xml:lang="sv">På grund av sättet Matrix-specifikationens utvecklas, stöder NeoChat också ett stor antal instabila funktioner. För närvarande är de:</p>
|
||||||
<p xml:lang="ta">மேட்ரிக்ஸு நெறிமுறை வரையறுக்கப்படும் விதத்தின் காரணமாக, பல நிலையற்ற அம்சங்களையும் நியோச்சாட் ஆதரிக்கிறது. தற்போது ஆதரிக்கப்படுபவை:</p>
|
<p xml:lang="ta">மேட்ரிக்ஸு நெறிமுறை வரையறுக்கப்படும் விதத்தின் காரணமாக, பல நிலையற்ற அம்சங்களையும் நியோச்சாட் ஆதரிக்கிறது. தற்போது ஆதரிக்கப்படுபவை:</p>
|
||||||
@@ -159,8 +191,9 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Polls - MSC3381</li>
|
<li>Polls - MSC3381</li>
|
||||||
<li xml:lang="ar">التصويت - MSC3381</li>
|
<li xml:lang="ar">التصويت - MSC3381</li>
|
||||||
<li xml:lang="ca">Enquestes - MSC3381</li>
|
<li xml:lang="ca">Votacions - MSC3381</li>
|
||||||
<li xml:lang="ca-valencia">Enquestes - MSC3381</li>
|
<li xml:lang="ca-valencia">Votacions - MSC3381</li>
|
||||||
|
<li xml:lang="el">Δημοσκοπήσεις - MSC3381</li>
|
||||||
<li xml:lang="en-GB">Polls - MSC3381</li>
|
<li xml:lang="en-GB">Polls - MSC3381</li>
|
||||||
<li xml:lang="eo">Enketoj - MSC3381</li>
|
<li xml:lang="eo">Enketoj - MSC3381</li>
|
||||||
<li xml:lang="es">Encuestas - MSC3381</li>
|
<li xml:lang="es">Encuestas - MSC3381</li>
|
||||||
@@ -168,15 +201,21 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<li xml:lang="fi">Kyselyt – MSC3381</li>
|
<li xml:lang="fi">Kyselyt – MSC3381</li>
|
||||||
<li xml:lang="fr">Sondages - MSC3381</li>
|
<li xml:lang="fr">Sondages - MSC3381</li>
|
||||||
<li xml:lang="gl">Enquisas — MSC3381</li>
|
<li xml:lang="gl">Enquisas — MSC3381</li>
|
||||||
|
<li xml:lang="he">סקרים - MSC3381</li>
|
||||||
|
<li xml:lang="hi">पोल - MSC3381</li>
|
||||||
<li xml:lang="hu">Szavazások - MSC3381</li>
|
<li xml:lang="hu">Szavazások - MSC3381</li>
|
||||||
<li xml:lang="ia">Inquestas - MSC3381</li>
|
<li xml:lang="ia">Inquestas - MSC3381</li>
|
||||||
<li xml:lang="it">Sondaggi - MSC3381</li>
|
<li xml:lang="it">Sondaggi - MSC3381</li>
|
||||||
<li xml:lang="ka">Polls - MSC3381</li>
|
<li xml:lang="ka">Polls - MSC3381</li>
|
||||||
<li xml:lang="ko">투표 - MSC3381</li>
|
<li xml:lang="ko">투표 - MSC3381</li>
|
||||||
|
<li xml:lang="lv">Aptaujas — MSC3381</li>
|
||||||
<li xml:lang="nl">Polls - MSC3381</li>
|
<li xml:lang="nl">Polls - MSC3381</li>
|
||||||
<li xml:lang="nn">Avstemmingar – MSC3381</li>
|
<li xml:lang="nn">Avstemmingar – MSC3381</li>
|
||||||
<li xml:lang="pl">Ankiety - MSC3381</li>
|
<li xml:lang="pl">Ankiety - MSC3381</li>
|
||||||
<li xml:lang="pt">Inquéritos - MSC3381</li>
|
<li xml:lang="pt">Inquéritos - MSC3381</li>
|
||||||
|
<li xml:lang="pt-BR">Enquetes - MSC3381</li>
|
||||||
|
<li xml:lang="ru">Голосования — MSC3381</li>
|
||||||
|
<li xml:lang="sa">मतदान - MSC3381</li>
|
||||||
<li xml:lang="sl">Polls - MSC3381</li>
|
<li xml:lang="sl">Polls - MSC3381</li>
|
||||||
<li xml:lang="sv">Polls - MSC3381</li>
|
<li xml:lang="sv">Polls - MSC3381</li>
|
||||||
<li xml:lang="ta">வாக்கெடுப்புகள் - MSC3381</li>
|
<li xml:lang="ta">வாக்கெடுப்புகள் - MSC3381</li>
|
||||||
@@ -188,6 +227,7 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<li xml:lang="ar">حزم الملصقات - MSC2545</li>
|
<li xml:lang="ar">حزم الملصقات - MSC2545</li>
|
||||||
<li xml:lang="ca">Paquets d'adhesius - MSC2545</li>
|
<li xml:lang="ca">Paquets d'adhesius - MSC2545</li>
|
||||||
<li xml:lang="ca-valencia">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="en-GB">Sticker Packs - MSC2545</li>
|
||||||
<li xml:lang="eo">Glumark-Pakoj - MSC2545</li>
|
<li xml:lang="eo">Glumark-Pakoj - MSC2545</li>
|
||||||
<li xml:lang="es">Paquetes de pegatinas - MSC2545</li>
|
<li xml:lang="es">Paquetes de pegatinas - MSC2545</li>
|
||||||
@@ -195,19 +235,25 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<li xml:lang="fi">Tarrapakkaukset – MSC2545</li>
|
<li xml:lang="fi">Tarrapakkaukset – MSC2545</li>
|
||||||
<li xml:lang="fr">Paquets d'auto-collants - MSC2545</li>
|
<li xml:lang="fr">Paquets d'auto-collants - MSC2545</li>
|
||||||
<li xml:lang="gl">Paquetes de adhesivos — MSC2545</li>
|
<li xml:lang="gl">Paquetes de adhesivos — MSC2545</li>
|
||||||
|
<li xml:lang="he">חבילות מדבקות - MSC2545</li>
|
||||||
|
<li xml:lang="hi">स्टिकर पैक - MSC2545</li>
|
||||||
<li xml:lang="hu">Matricacsomagok - MSC2545</li>
|
<li xml:lang="hu">Matricacsomagok - MSC2545</li>
|
||||||
<li xml:lang="ia">Etiquetta gummate (sticker) -MSC2545</li>
|
<li xml:lang="ia">Etiquetta gummate (sticker) -MSC2545</li>
|
||||||
<li xml:lang="it">Pacchetti di adesivi - MSC2545</li>
|
<li xml:lang="it">Pacchetti di adesivi - MSC2545</li>
|
||||||
<li xml:lang="ka">სტიკერების პაკეტები - MSC2545</li>
|
<li xml:lang="ka">სტიკერების პაკეტები - MSC2545</li>
|
||||||
<li xml:lang="ko">스티커 팩 - MSC2545</li>
|
<li xml:lang="ko">스티커 팩 - MSC2545</li>
|
||||||
|
<li xml:lang="lv">Uzlīmju pakas — MSC2545</li>
|
||||||
<li xml:lang="nl">Sticker Packs - MSC2545</li>
|
<li xml:lang="nl">Sticker Packs - MSC2545</li>
|
||||||
<li xml:lang="nn">Klistremerke-pakkar – MSC2545</li>
|
<li xml:lang="nn">Klistremerke-pakkar – MSC2545</li>
|
||||||
<li xml:lang="pl">Paczki naklejek - MSC2545</li>
|
<li xml:lang="pl">Paczki naklejek - MSC2545</li>
|
||||||
<li xml:lang="pt">Pacotes de Autocolantes - MSC2545</li>
|
<li xml:lang="pt">Pacotes de Autocolantes - MSC2545</li>
|
||||||
|
<li xml:lang="pt-BR">Pacotes de Stickers - MSC2545</li>
|
||||||
|
<li xml:lang="ru">Наборы стикеров — MSC2545</li>
|
||||||
|
<li xml:lang="sa">स्टिकर पैक - MSC2545</li>
|
||||||
<li xml:lang="sl">Sticker Packs - MSC2545</li>
|
<li xml:lang="sl">Sticker Packs - MSC2545</li>
|
||||||
<li xml:lang="sv">Sticker Packs - MSC2545</li>
|
<li xml:lang="sv">Sticker Packs - MSC2545</li>
|
||||||
<li xml:lang="ta">ஒட்டி தொகுப்புகள் - MSC2545</li>
|
<li xml:lang="ta">ஒட்டி தொகுப்புகள் - MSC2545</li>
|
||||||
<li xml:lang="tr">Yapışkan Paketleri — MSC2545</li>
|
<li xml:lang="tr">Çıkartma Paketleri — MSC2545</li>
|
||||||
<li xml:lang="uk">Пакунки наліпок - MSC2545</li>
|
<li xml:lang="uk">Пакунки наліпок - MSC2545</li>
|
||||||
<li xml:lang="x-test">xxSticker Packs - MSC2545xx</li>
|
<li xml:lang="x-test">xxSticker Packs - MSC2545xx</li>
|
||||||
<li xml:lang="zh-TW">貼圖包 - MSC2545</li>
|
<li xml:lang="zh-TW">貼圖包 - MSC2545</li>
|
||||||
@@ -215,6 +261,7 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<li xml:lang="ar">موقع الأحداث - MSC3488</li>
|
<li xml:lang="ar">موقع الأحداث - MSC3488</li>
|
||||||
<li xml:lang="ca">Esdeveniments d'ubicació - MSC3488</li>
|
<li xml:lang="ca">Esdeveniments d'ubicació - MSC3488</li>
|
||||||
<li xml:lang="ca-valencia">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="en-GB">Location Events - MSC3488</li>
|
||||||
<li xml:lang="eo">Lokaj Eventoj - MSC3488</li>
|
<li xml:lang="eo">Lokaj Eventoj - MSC3488</li>
|
||||||
<li xml:lang="es">Eventos de ubicación - MSC3488</li>
|
<li xml:lang="es">Eventos de ubicación - MSC3488</li>
|
||||||
@@ -222,15 +269,21 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<li xml:lang="fi">Sijaintitapahtumat – MSC3488</li>
|
<li xml:lang="fi">Sijaintitapahtumat – MSC3488</li>
|
||||||
<li xml:lang="fr">Événements de lieu - MSC3488</li>
|
<li xml:lang="fr">Événements de lieu - MSC3488</li>
|
||||||
<li xml:lang="gl">Localización de eventos — MSC3488</li>
|
<li xml:lang="gl">Localización de eventos — MSC3488</li>
|
||||||
|
<li xml:lang="he">אירועי מקום - MSC3488</li>
|
||||||
|
<li xml:lang="hi">स्थान घटनाएँ - MSC3488</li>
|
||||||
<li xml:lang="hu">Események helyadatai - MSC3488</li>
|
<li xml:lang="hu">Események helyadatai - MSC3488</li>
|
||||||
<li xml:lang="ia">Eventos de Location - MSC3488</li>
|
<li xml:lang="ia">Eventos de Location - MSC3488</li>
|
||||||
<li xml:lang="it">Località eventi - MSC3488</li>
|
<li xml:lang="it">Località eventi - MSC3488</li>
|
||||||
<li xml:lang="ka">მდებარეობის მოვლენები - MSC3488</li>
|
<li xml:lang="ka">მდებარეობის მოვლენები - MSC3488</li>
|
||||||
<li xml:lang="ko">위치 이벤트 - MSC3488</li>
|
<li xml:lang="ko">위치 이벤트 - MSC3488</li>
|
||||||
|
<li xml:lang="lv">Atrašanās vietas notikumi — MSC3488</li>
|
||||||
<li xml:lang="nl">Locatie gebeurtenissen - MSC3488</li>
|
<li xml:lang="nl">Locatie gebeurtenissen - MSC3488</li>
|
||||||
<li xml:lang="nn">Posisjonshendingar – MSC3488</li>
|
<li xml:lang="nn">Posisjonshendingar – MSC3488</li>
|
||||||
<li xml:lang="pl">Wydarzenia w miejscach - MSC3488</li>
|
<li xml:lang="pl">Wydarzenia w miejscach - MSC3488</li>
|
||||||
<li xml:lang="pt">Eventos com Localizações - MSC3488</li>
|
<li xml:lang="pt">Eventos com Localizações - MSC3488</li>
|
||||||
|
<li xml:lang="pt-BR">Localização de eventos - MSC3488</li>
|
||||||
|
<li xml:lang="ru">События местоположения — MSC3488</li>
|
||||||
|
<li xml:lang="sa">स्थान घटनाएँ - MSC3488</li>
|
||||||
<li xml:lang="sl">Location Events - MSC3488</li>
|
<li xml:lang="sl">Location Events - MSC3488</li>
|
||||||
<li xml:lang="sv">Location Events - MSC3488</li>
|
<li xml:lang="sv">Location Events - MSC3488</li>
|
||||||
<li xml:lang="ta">இட நிகழ்வுகள் - MSC3488</li>
|
<li xml:lang="ta">இட நிகழ்வுகள் - MSC3488</li>
|
||||||
@@ -242,47 +295,21 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
</description>
|
</description>
|
||||||
<url type="homepage">https://apps.kde.org/neochat</url>
|
<url type="homepage">https://apps.kde.org/neochat</url>
|
||||||
<url type="bugtracker">https://bugs.kde.org/enter_bug.cgi?product=NeoChat</url>
|
<url type="bugtracker">https://bugs.kde.org/enter_bug.cgi?product=NeoChat</url>
|
||||||
|
<url type="vcs-browser">https://invent.kde.org/network/neochat</url>
|
||||||
|
<url type="contact">https://go.kde.org/matrix/#/#neochat:kde.org</url>
|
||||||
|
<url type="donation">https://kde.org/community/donations/?app=neochat</url>
|
||||||
|
<url type="contribute">https://community.kde.org/Get_Involved/</url>
|
||||||
<categories>
|
<categories>
|
||||||
<category>Network</category>
|
<category>Network</category>
|
||||||
</categories>
|
</categories>
|
||||||
<developer_name>The KDE Community</developer_name>
|
<keywords>
|
||||||
<developer_name xml:lang="ar">مجتمع كِيدِي</developer_name>
|
<keyword>Matrix</keyword>
|
||||||
<developer_name xml:lang="az">KDE Cəmiyyəti</developer_name>
|
<keyword>Kirigami</keyword>
|
||||||
<developer_name xml:lang="ca">La comunitat KDE</developer_name>
|
</keywords>
|
||||||
<developer_name xml:lang="ca-valencia">La comunitat KDE</developer_name>
|
<developer id="org.kde">
|
||||||
<developer_name xml:lang="cs">Komunita KDE</developer_name>
|
<name translate="no">KDE</name>
|
||||||
<developer_name xml:lang="de">Die KDE-Gemeinschaft</developer_name>
|
<url>https://kde.org</url>
|
||||||
<developer_name xml:lang="el">Η Κοινότητα του KDE</developer_name>
|
</developer>
|
||||||
<developer_name xml:lang="en-GB">The KDE Community</developer_name>
|
|
||||||
<developer_name xml:lang="eo">La KDE-Komunumo</developer_name>
|
|
||||||
<developer_name xml:lang="es">La comunidad KDE</developer_name>
|
|
||||||
<developer_name xml:lang="eu">KDE komunitatea</developer_name>
|
|
||||||
<developer_name xml:lang="fi">KDE-yhteisö</developer_name>
|
|
||||||
<developer_name xml:lang="fr">La communauté de KDE</developer_name>
|
|
||||||
<developer_name xml:lang="gl">A comunidade KDE</developer_name>
|
|
||||||
<developer_name xml:lang="hu">A KDE Közösség</developer_name>
|
|
||||||
<developer_name xml:lang="ia">Le communitate de KDE</developer_name>
|
|
||||||
<developer_name xml:lang="id">Komunitas KDE</developer_name>
|
|
||||||
<developer_name xml:lang="ie">Li comunité de KDE</developer_name>
|
|
||||||
<developer_name xml:lang="it">La comunità KDE</developer_name>
|
|
||||||
<developer_name xml:lang="ka">KDE-ის საზოგადოება</developer_name>
|
|
||||||
<developer_name xml:lang="ko">KDE 커뮤니티</developer_name>
|
|
||||||
<developer_name xml:lang="nl">De KDE gemeenschap</developer_name>
|
|
||||||
<developer_name xml:lang="nn">KDE-fellesskapet</developer_name>
|
|
||||||
<developer_name xml:lang="pa">ਕੇਡੀਈ ਕਮਿਊਨਟੀ</developer_name>
|
|
||||||
<developer_name xml:lang="pl">Społeczność KDE</developer_name>
|
|
||||||
<developer_name xml:lang="pt">A Comunidade do KDE</developer_name>
|
|
||||||
<developer_name xml:lang="pt-BR">A comunidade KDE</developer_name>
|
|
||||||
<developer_name xml:lang="ru">Сообщество KDE</developer_name>
|
|
||||||
<developer_name xml:lang="sk">KDE Komunita</developer_name>
|
|
||||||
<developer_name xml:lang="sl">Skupnost KDE</developer_name>
|
|
||||||
<developer_name xml:lang="sv">KDE-gemenskapen</developer_name>
|
|
||||||
<developer_name xml:lang="ta">கே.டீ.யீ. சமூகம்</developer_name>
|
|
||||||
<developer_name xml:lang="tr">KDE Topluluğu</developer_name>
|
|
||||||
<developer_name xml:lang="uk">Спільнота KDE</developer_name>
|
|
||||||
<developer_name xml:lang="x-test">xxThe KDE Communityxx</developer_name>
|
|
||||||
<developer_name xml:lang="zh-CN">KDE 社区</developer_name>
|
|
||||||
<developer_name xml:lang="zh-TW">KDE 社群</developer_name>
|
|
||||||
<metadata_license>CC0-1.0</metadata_license>
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
<project_license>GPL-3.0</project_license>
|
<project_license>GPL-3.0</project_license>
|
||||||
<custom>
|
<custom>
|
||||||
@@ -293,36 +320,122 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<value key="KDE::windows_store::StoreLogoSquare">https://invent.kde.org/network/neochat/-/raw/master/icons/windows/storelogo-1080x1080.png</value>
|
<value key="KDE::windows_store::StoreLogoSquare">https://invent.kde.org/network/neochat/-/raw/master/icons/windows/storelogo-1080x1080.png</value>
|
||||||
<value key="KDE::windows_store::Icon">https://invent.kde.org/network/neochat/-/raw/master/icons/300-apps-neochat.png</value>
|
<value key="KDE::windows_store::Icon">https://invent.kde.org/network/neochat/-/raw/master/icons/300-apps-neochat.png</value>
|
||||||
<value key="KDE::windows_store::PromotionalArt16x9">https://invent.kde.org/network/neochat/-/raw/master/icons/windows/promoimage-1920x1080.png</value>
|
<value key="KDE::windows_store::PromotionalArt16x9">https://invent.kde.org/network/neochat/-/raw/master/icons/windows/promoimage-1920x1080.png</value>
|
||||||
|
<value key="KDE::supporters">Tanguy Fardet;[dabe](https://freeradical.zone/@dabe);[lengau](https://mastodon.world/@lengau);Joshua Strobl;Stuart Turton</value>
|
||||||
</custom>
|
</custom>
|
||||||
<launchable type="desktop-id">org.kde.neochat.desktop</launchable>
|
<launchable type="desktop-id">org.kde.neochat.desktop</launchable>
|
||||||
<screenshots>
|
<screenshots>
|
||||||
<screenshot type="default">
|
|
||||||
<image>https://cdn.kde.org/screenshots/neochat/application-mobile.png</image>
|
|
||||||
</screenshot>
|
|
||||||
<screenshot type="default">
|
<screenshot type="default">
|
||||||
<image>https://cdn.kde.org/screenshots/neochat/application.png</image>
|
<image>https://cdn.kde.org/screenshots/neochat/application.png</image>
|
||||||
</screenshot>
|
|
||||||
<screenshot environment="windows">
|
|
||||||
<image>https://cdn.kde.org/screenshots/neochat/NeoChat-Windows-Timeline.png</image>
|
|
||||||
<caption>Main view with room list, chat, and room information</caption>
|
<caption>Main view with room list, chat, and room information</caption>
|
||||||
<caption xml:lang="ar">العرض الرئيسة مع قائمة الغرف والدردشات و معلومات الغرفة</caption>
|
<caption xml:lang="ar">العرض الرئيسة مع قائمة الغرف والدردشات و معلومات الغرفة</caption>
|
||||||
<caption xml:lang="ca">Vista principal amb la llista de sales, xats i informació de les sales</caption>
|
<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="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="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>
|
<caption xml:lang="es">Vista principal con la lista de salas, chat e información de la sala</caption>
|
||||||
<caption xml:lang="eu">Ikuspegi nagusia gela-zerrenda, berriketa, eta gelako informazioarekin</caption>
|
<caption xml:lang="eu">Ikuspegi nagusia gela-zerrenda, berriketa, eta gelako informazioarekin</caption>
|
||||||
<caption xml:lang="fi">Päänäkymä, jossa huoneluettelo, keskustelu ja huoneen tiedot</caption>
|
<caption xml:lang="fi">Päänäkymä, jossa huoneluettelo, keskustelu ja huoneen tiedot</caption>
|
||||||
<caption xml:lang="fr">Vue principale avec la liste des salons ainsi que des informations sur les salons et forums de discussions</caption>
|
<caption xml:lang="fr">Vue principale avec la liste des salons ainsi que des informations sur les salons et forums de discussions</caption>
|
||||||
<caption xml:lang="gl">Vista principal coa lista de salas, a charla, e información da sala.</caption>
|
<caption xml:lang="gl">Vista principal coa lista de salas, a charla, e información da sala.</caption>
|
||||||
|
<caption xml:lang="he">תצוגה ראשית עם רשימת חדרים, צ׳אט ופרטי חדר</caption>
|
||||||
|
<caption xml:lang="hi">कमरे की सूची, चैट और कमरे की जानकारी के साथ मुख्य दृश्य</caption>
|
||||||
<caption xml:lang="hu">A fő nézet a szobalistával, csevegéssel és szobainformációkkal</caption>
|
<caption xml:lang="hu">A fő nézet a szobalistával, csevegéssel és szobainformációkkal</caption>
|
||||||
<caption xml:lang="ia">Vista principal con lista de sala, chat e information de sala</caption>
|
<caption xml:lang="ia">Vista principal con lista de sala, chat e information de sala</caption>
|
||||||
<caption xml:lang="it">Vista principale con elenco delle stanze, chat e informazioni sulla stanza</caption>
|
<caption xml:lang="it">Vista principale con elenco delle stanze, chat e informazioni sulla stanza</caption>
|
||||||
<caption xml:lang="ka">მთავარი ხედი სურათების სიით, ჩატით და ოთახის ინფორმაციით</caption>
|
<caption xml:lang="ka">მთავარი ხედი სურათების სიით, ჩატით და ოთახის ინფორმაციით</caption>
|
||||||
<caption xml:lang="ko">대화방 목록, 채팅, 대화방 정보가 표시된 주 보기</caption>
|
<caption xml:lang="ko">대화방 목록, 채팅, 대화방 정보가 표시된 주 보기</caption>
|
||||||
|
<caption xml:lang="lv">Pamata skats ar istabu sarakstu, tērzēšanu un istabas informāciju</caption>
|
||||||
<caption xml:lang="nl">Hoofdweergave met lijst met rooms, chat en roominformatie</caption>
|
<caption xml:lang="nl">Hoofdweergave met lijst met rooms, chat en roominformatie</caption>
|
||||||
<caption xml:lang="nn">Hovudvising med romliste, pratevindauge og rominformasjon</caption>
|
<caption xml:lang="nn">Hovudvising med romliste, pratevindauge og rominformasjon</caption>
|
||||||
<caption xml:lang="pl">Główny widok z wykazem pokojów, rozmowami i szczegółami pokojów</caption>
|
<caption xml:lang="pl">Główny widok z wykazem pokojów, rozmowami i szczegółami pokojów</caption>
|
||||||
<caption xml:lang="pt">A área principal com a lista de salas e com informações sobre a conversa e a sala</caption>
|
<caption xml:lang="pt">A área principal com a lista de salas e com informações sobre a conversa e a sala</caption>
|
||||||
|
<caption xml:lang="pt-BR">Visão principal com lista de salas, bate-papo e informações sobre as salas</caption>
|
||||||
|
<caption xml:lang="ru">Главное окно со списком комнат, чатом и информацией о комнате</caption>
|
||||||
|
<caption xml:lang="sa">कक्षसूची, गपशपः, कक्षसूचना च सह मुख्यदृश्यम्</caption>
|
||||||
|
<caption xml:lang="sl">Glavni pogled s seznamom sob, klepetom in informacijami o sobah</caption>
|
||||||
|
<caption xml:lang="sv">Huvudvy med rumslista, chatt, och rumsinformation</caption>
|
||||||
|
<caption xml:lang="ta">அரங்குப்பட்டியல், உரையாடல், மற்றும் அரங்குவிவரங்களைக் கொண்டுள்ள பிரதான காட்சி</caption>
|
||||||
|
<caption xml:lang="tr">Oda listesini, sohbet penceresini ve oda bilgisini gösteren ana görünüm</caption>
|
||||||
|
<caption xml:lang="uk">Головна панель із списком кімнат, спілкуванням та даними щодо кімнати</caption>
|
||||||
|
<caption xml:lang="x-test">xxMain view with room list, chat, and room informationxx</caption>
|
||||||
|
<caption xml:lang="zh-TW">主頁面,包含聊天室列表、聊天內容,與聊天室資訊</caption>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot type="default">
|
||||||
|
<image>https://cdn.kde.org/screenshots/neochat/spaces.png</image>
|
||||||
|
<caption>Discover new communities with Matrix Spaces</caption>
|
||||||
|
<caption xml:lang="ar">اكتشف مجتمعات جديدة مع فضاءات ماتركس</caption>
|
||||||
|
<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>
|
||||||
|
<caption xml:lang="eu">Ezagutu komunitate berriak Matrixeko Tokiak erabiliz</caption>
|
||||||
|
<caption xml:lang="fi">Löydä uusia yhteisöjä Matrix Spacesillä</caption>
|
||||||
|
<caption xml:lang="fr">Découvrez de nouvelles communautés avec les espaces sous Matrix</caption>
|
||||||
|
<caption xml:lang="gl">Descubra novas comunidades dos espazos de Matrix.</caption>
|
||||||
|
<caption xml:lang="he">אפשר להיחשף לקהילות חדשות דרך Matrix Spaces</caption>
|
||||||
|
<caption xml:lang="hi">मैट्रिक्स स्पेस के साथ नए समुदायों की खोज करें</caption>
|
||||||
|
<caption xml:lang="hu">Fedezzen fel új közösségeket a Matrix Terek segítségével</caption>
|
||||||
|
<caption xml:lang="ia">Discoperi nove communitate con Matrix Spaces (Spatios de Matrix)</caption>
|
||||||
|
<caption xml:lang="it">Scopri nuove comunità con Matrix Spaces</caption>
|
||||||
|
<caption xml:lang="ka">აღმოაჩინეთ ახალი საზოგადოებები Matrix Spaces-თან ერთად</caption>
|
||||||
|
<caption xml:lang="ko">Matrix 스페이스에서 새로운 커뮤니티 탐험</caption>
|
||||||
|
<caption xml:lang="lv">Atklājiet jaunas kopienas ar „Matrix“ telpām</caption>
|
||||||
|
<caption xml:lang="nl">Ontdek nieuwe gemeenschappen met Matrix-ruimten</caption>
|
||||||
|
<caption xml:lang="nn">Oppdag nye fellesskap med Matrix Spaces</caption>
|
||||||
|
<caption xml:lang="pl">Odkrywaj nowe społeczności w Przestrzeniach Matriksa</caption>
|
||||||
|
<caption xml:lang="pt-BR">Descubra novas comunidades com os Espaços Matrix</caption>
|
||||||
|
<caption xml:lang="ru">Поиск новых сообществ с помощью Matrix Spaces</caption>
|
||||||
|
<caption xml:lang="sa">Matrix Spaces इत्यनेन सह नूतनानां समुदायानाम् अन्वेषणं कुर्वन्तु</caption>
|
||||||
|
<caption xml:lang="sl">Odkrijte nove skupnosti z Matrix Spaces</caption>
|
||||||
|
<caption xml:lang="sv">Upptäck nya gemenskaper med Matrix Spaces</caption>
|
||||||
|
<caption xml:lang="ta">மேட்ரிக்ஸு இடங்களின் மூலம் புதிய சமூகங்களைக் கண்டுபிடிக்கலாம்</caption>
|
||||||
|
<caption xml:lang="tr">Matrix Alanlar ile yeni topluluklar keşfedin</caption>
|
||||||
|
<caption xml:lang="uk">Пошук нових спільнот за допомогою Matrix Spaces</caption>
|
||||||
|
<caption xml:lang="x-test">xxDiscover new communities with Matrix Spacesxx</caption>
|
||||||
|
<caption xml:lang="zh-TW">利用 Matrix 聊天空間發現新的社群</caption>
|
||||||
|
</screenshot>
|
||||||
|
<!--
|
||||||
|
Currently invalid. See https://github.com/ximion/appstream/issues/611
|
||||||
|
<screenshot type="default" environment="plasma-mobile">
|
||||||
|
<image>https://cdn.kde.org/screenshots/neochat/neochat-1.png</image>
|
||||||
|
<caption>List of chats on mobile</caption>
|
||||||
|
</screenshot>
|
||||||
|
-->
|
||||||
|
<screenshot environment="windows">
|
||||||
|
<image>https://cdn.kde.org/screenshots/neochat/NeoChat-Windows-Timeline.png</image>
|
||||||
|
<caption>Main view with room list, chat, and room information</caption>
|
||||||
|
<caption xml:lang="ar">العرض الرئيسة مع قائمة الغرف والدردشات و معلومات الغرفة</caption>
|
||||||
|
<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>
|
||||||
|
<caption xml:lang="eu">Ikuspegi nagusia gela-zerrenda, berriketa, eta gelako informazioarekin</caption>
|
||||||
|
<caption xml:lang="fi">Päänäkymä, jossa huoneluettelo, keskustelu ja huoneen tiedot</caption>
|
||||||
|
<caption xml:lang="fr">Vue principale avec la liste des salons ainsi que des informations sur les salons et forums de discussions</caption>
|
||||||
|
<caption xml:lang="gl">Vista principal coa lista de salas, a charla, e información da sala.</caption>
|
||||||
|
<caption xml:lang="he">תצוגה ראשית עם רשימת חדרים, צ׳אט ופרטי חדר</caption>
|
||||||
|
<caption xml:lang="hi">कमरे की सूची, चैट और कमरे की जानकारी के साथ मुख्य दृश्य</caption>
|
||||||
|
<caption xml:lang="hu">A fő nézet a szobalistával, csevegéssel és szobainformációkkal</caption>
|
||||||
|
<caption xml:lang="ia">Vista principal con lista de sala, chat e information de sala</caption>
|
||||||
|
<caption xml:lang="it">Vista principale con elenco delle stanze, chat e informazioni sulla stanza</caption>
|
||||||
|
<caption xml:lang="ka">მთავარი ხედი სურათების სიით, ჩატით და ოთახის ინფორმაციით</caption>
|
||||||
|
<caption xml:lang="ko">대화방 목록, 채팅, 대화방 정보가 표시된 주 보기</caption>
|
||||||
|
<caption xml:lang="lv">Pamata skats ar istabu sarakstu, tērzēšanu un istabas informāciju</caption>
|
||||||
|
<caption xml:lang="nl">Hoofdweergave met lijst met rooms, chat en roominformatie</caption>
|
||||||
|
<caption xml:lang="nn">Hovudvising med romliste, pratevindauge og rominformasjon</caption>
|
||||||
|
<caption xml:lang="pl">Główny widok z wykazem pokojów, rozmowami i szczegółami pokojów</caption>
|
||||||
|
<caption xml:lang="pt">A área principal com a lista de salas e com informações sobre a conversa e a sala</caption>
|
||||||
|
<caption xml:lang="pt-BR">Visão principal com lista de salas, bate-papo e informações sobre as salas</caption>
|
||||||
|
<caption xml:lang="ru">Главное окно со списком комнат, чатом и информацией о комнате</caption>
|
||||||
|
<caption xml:lang="sa">कक्षसूची, गपशपः, कक्षसूचना च सह मुख्यदृश्यम्</caption>
|
||||||
<caption xml:lang="sl">Glavni pogled s seznamom sob, klepetom in informacijami o sobah</caption>
|
<caption xml:lang="sl">Glavni pogled s seznamom sob, klepetom in informacijami o sobah</caption>
|
||||||
<caption xml:lang="sv">Huvudvy med rumslista, chatt, och rumsinformation</caption>
|
<caption xml:lang="sv">Huvudvy med rumslista, chatt, och rumsinformation</caption>
|
||||||
<caption xml:lang="ta">அரங்குப்பட்டியல், உரையாடல், மற்றும் அரங்குவிவரங்களைக் கொண்டுள்ள பிரதான காட்சி</caption>
|
<caption xml:lang="ta">அரங்குப்பட்டியல், உரையாடல், மற்றும் அரங்குவிவரங்களைக் கொண்டுள்ள பிரதான காட்சி</caption>
|
||||||
@@ -338,21 +451,30 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<caption xml:lang="ca">Pantalla d'inici de sessió</caption>
|
<caption xml:lang="ca">Pantalla d'inici de sessió</caption>
|
||||||
<caption xml:lang="ca-valencia">Pantalla d'inici de sessió</caption>
|
<caption xml:lang="ca-valencia">Pantalla d'inici de sessió</caption>
|
||||||
<caption xml:lang="cs">Přihlašovací obrazovka</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="eo">Ensaluta ekrano</caption>
|
||||||
<caption xml:lang="es">Pantalla de inicio de sesión</caption>
|
<caption xml:lang="es">Pantalla de inicio de sesión</caption>
|
||||||
<caption xml:lang="eu">Saio-hasteko pantaila</caption>
|
<caption xml:lang="eu">Saio-hasteko pantaila</caption>
|
||||||
<caption xml:lang="fi">Kirjautumisnäkymä</caption>
|
<caption xml:lang="fi">Kirjautumisnäkymä</caption>
|
||||||
<caption xml:lang="fr">Écran de connexion</caption>
|
<caption xml:lang="fr">Écran de connexion</caption>
|
||||||
<caption xml:lang="gl">Pantalla de identificación.</caption>
|
<caption xml:lang="gl">Pantalla de identificación.</caption>
|
||||||
|
<caption xml:lang="he">מסך כניסה</caption>
|
||||||
|
<caption xml:lang="hi">लॉगिन स्क्रीन</caption>
|
||||||
<caption xml:lang="hu">Bejelentkező képernyő</caption>
|
<caption xml:lang="hu">Bejelentkező képernyő</caption>
|
||||||
<caption xml:lang="ia">Schermo de accesso</caption>
|
<caption xml:lang="ia">Schermo de accesso</caption>
|
||||||
<caption xml:lang="it">Schermata di accesso</caption>
|
<caption xml:lang="it">Schermata di accesso</caption>
|
||||||
<caption xml:lang="ka">შესვლის ეკრანი</caption>
|
<caption xml:lang="ka">შესვლის ეკრანი</caption>
|
||||||
<caption xml:lang="ko">로그인 화면</caption>
|
<caption xml:lang="ko">로그인 화면</caption>
|
||||||
|
<caption xml:lang="lv">Ierakstīšanās logs</caption>
|
||||||
<caption xml:lang="nl">Aanmeldscherm</caption>
|
<caption xml:lang="nl">Aanmeldscherm</caption>
|
||||||
<caption xml:lang="nn">Innloggingsbilete</caption>
|
<caption xml:lang="nn">Innloggingsbilete</caption>
|
||||||
<caption xml:lang="pl">Ekran logowania</caption>
|
<caption xml:lang="pl">Ekran logowania</caption>
|
||||||
<caption xml:lang="pt">Ecrã de autenticação</caption>
|
<caption xml:lang="pt">Ecrã de autenticação</caption>
|
||||||
|
<caption xml:lang="pt-BR">Tela de login</caption>
|
||||||
|
<caption xml:lang="ru">Окно входа</caption>
|
||||||
|
<caption xml:lang="sa">लॉगिन् स्क्रीन</caption>
|
||||||
<caption xml:lang="sl">Prijavni zaslon</caption>
|
<caption xml:lang="sl">Prijavni zaslon</caption>
|
||||||
<caption xml:lang="sv">Inloggningsfönster</caption>
|
<caption xml:lang="sv">Inloggningsfönster</caption>
|
||||||
<caption xml:lang="ta">நுழைவுத் திரை</caption>
|
<caption xml:lang="ta">நுழைவுத் திரை</caption>
|
||||||
@@ -366,6 +488,22 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<content_attribute id="social-chat">intense</content_attribute>
|
<content_attribute id="social-chat">intense</content_attribute>
|
||||||
</content_rating>
|
</content_rating>
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="25.08.0" date="2025-08-14"/>
|
||||||
|
<release version="25.04.3" date="2025-07-03"/>
|
||||||
|
<release version="25.04.2" date="2025-06-05"/>
|
||||||
|
<release version="25.04.1" date="2025-05-08"/>
|
||||||
|
<release version="25.04.0" date="2025-04-17"/>
|
||||||
|
<release version="24.12.3" date="2025-03-06"/>
|
||||||
|
<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"/>
|
||||||
|
<release version="24.08.0" date="2024-08-22"/>
|
||||||
|
<release version="24.05.2" date="2024-07-04"/>
|
||||||
|
<release version="24.05.1" date="2024-06-13"/>
|
||||||
|
<release version="24.05.0" date="2024-05-23"/>
|
||||||
<release version="24.02.2" date="2024-04-11"/>
|
<release version="24.02.2" date="2024-04-11"/>
|
||||||
<release version="24.02.1" date="2024-03-21"/>
|
<release version="24.02.1" date="2024-03-21"/>
|
||||||
<release version="24.02.0" date="2024-02-28">
|
<release version="24.02.0" date="2024-02-28">
|
||||||
@@ -533,4 +671,11 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<url>https://carlschwan.eu/2020/12/23/announcing-neochat-1.0-the-kde-matrix-client/</url>
|
<url>https://carlschwan.eu/2020/12/23/announcing-neochat-1.0-the-kde-matrix-client/</url>
|
||||||
</release>
|
</release>
|
||||||
</releases>
|
</releases>
|
||||||
|
<requires>
|
||||||
|
<display_length compare="ge">360</display_length>
|
||||||
|
</requires>
|
||||||
|
<branding>
|
||||||
|
<color type="primary" scheme_preference="light">#a6e4f3</color>
|
||||||
|
<color type="primary" scheme_preference="dark">#235670</color>
|
||||||
|
</branding>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ Name[eu]=NeoChat
|
|||||||
Name[fi]=NeoChat
|
Name[fi]=NeoChat
|
||||||
Name[fr]=NeoChat
|
Name[fr]=NeoChat
|
||||||
Name[gl]=NeoChat
|
Name[gl]=NeoChat
|
||||||
|
Name[he]=NeoChat
|
||||||
|
Name[hi]=नियोचैट
|
||||||
Name[hu]=NeoChat
|
Name[hu]=NeoChat
|
||||||
Name[ia]=Neochat
|
Name[ia]=Neochat
|
||||||
Name[id]=NeoChat
|
Name[id]=NeoChat
|
||||||
@@ -26,6 +28,7 @@ Name[it]=NeoChat
|
|||||||
Name[ka]=NeoChat
|
Name[ka]=NeoChat
|
||||||
Name[ko]=NeoChat
|
Name[ko]=NeoChat
|
||||||
Name[lt]=NeoChat
|
Name[lt]=NeoChat
|
||||||
|
Name[lv]=NeoChat
|
||||||
Name[nl]=NeoChat
|
Name[nl]=NeoChat
|
||||||
Name[nn]=NeoChat
|
Name[nn]=NeoChat
|
||||||
Name[pa]=ਨਿਓ-ਚੈਟ
|
Name[pa]=ਨਿਓ-ਚੈਟ
|
||||||
@@ -34,6 +37,7 @@ Name[pt]=NeoChat
|
|||||||
Name[pt_BR]=NeoChat
|
Name[pt_BR]=NeoChat
|
||||||
Name[ro]=NeoChat
|
Name[ro]=NeoChat
|
||||||
Name[ru]=NeoChat
|
Name[ru]=NeoChat
|
||||||
|
Name[sa]=नवचैट्
|
||||||
Name[sk]=NeoChat
|
Name[sk]=NeoChat
|
||||||
Name[sl]=NeoChat
|
Name[sl]=NeoChat
|
||||||
Name[sv]=NeoChat
|
Name[sv]=NeoChat
|
||||||
@@ -58,6 +62,8 @@ GenericName[eu]=Matrix bezeroa
|
|||||||
GenericName[fi]=Matrix-asiakas
|
GenericName[fi]=Matrix-asiakas
|
||||||
GenericName[fr]=Client « Matrix »
|
GenericName[fr]=Client « Matrix »
|
||||||
GenericName[gl]=Cliente de Matrix
|
GenericName[gl]=Cliente de Matrix
|
||||||
|
GenericName[he]=לקוח Matrix
|
||||||
|
GenericName[hi]=मैट्रिक्स क्लाइंट
|
||||||
GenericName[hu]=Matrix kliens
|
GenericName[hu]=Matrix kliens
|
||||||
GenericName[ia]=Cliente de Matrice
|
GenericName[ia]=Cliente de Matrice
|
||||||
GenericName[id]=Klien Matrix
|
GenericName[id]=Klien Matrix
|
||||||
@@ -65,7 +71,8 @@ GenericName[ie]=Cliente de Matrix
|
|||||||
GenericName[it]=Client Matrix
|
GenericName[it]=Client Matrix
|
||||||
GenericName[ka]=Matrix -ის კლიენტი
|
GenericName[ka]=Matrix -ის კლიენტი
|
||||||
GenericName[ko]=Matrix 클라이언트
|
GenericName[ko]=Matrix 클라이언트
|
||||||
GenericName[lt]=Matrix kliento programą
|
GenericName[lt]=Matrix kliento programa
|
||||||
|
GenericName[lv]=„Matrix“ klients
|
||||||
GenericName[nl]=Matrix-client
|
GenericName[nl]=Matrix-client
|
||||||
GenericName[nn]=Matrix-klient
|
GenericName[nn]=Matrix-klient
|
||||||
GenericName[pa]=ਮੈਟਰਿਕਸ ਕਲਾਈਂਟ
|
GenericName[pa]=ਮੈਟਰਿਕਸ ਕਲਾਈਂਟ
|
||||||
@@ -74,6 +81,7 @@ GenericName[pt]=Cliente de Matrix
|
|||||||
GenericName[pt_BR]=Cliente Matrix
|
GenericName[pt_BR]=Cliente Matrix
|
||||||
GenericName[ro]=Client Matrix
|
GenericName[ro]=Client Matrix
|
||||||
GenericName[ru]=Клиент Matrix
|
GenericName[ru]=Клиент Matrix
|
||||||
|
GenericName[sa]=मैट्रिक्स क्लाइंट
|
||||||
GenericName[sk]=Matrix Client
|
GenericName[sk]=Matrix Client
|
||||||
GenericName[sl]=Odjemalec Matrix
|
GenericName[sl]=Odjemalec Matrix
|
||||||
GenericName[sv]=Matrix-klient
|
GenericName[sv]=Matrix-klient
|
||||||
@@ -83,45 +91,39 @@ GenericName[uk]=Клієнт Matrix
|
|||||||
GenericName[x-test]=xxMatrix Clientxx
|
GenericName[x-test]=xxMatrix Clientxx
|
||||||
GenericName[zh_CN]=Matrix 客户端
|
GenericName[zh_CN]=Matrix 客户端
|
||||||
GenericName[zh_TW]=Matrix 用戶端
|
GenericName[zh_TW]=Matrix 用戶端
|
||||||
Comment=Client for the Matrix protocol
|
Comment=Chat on Matrix
|
||||||
Comment[ar]=عميل لميفاق ماتركس
|
Comment[ar]=دردش على ماتركس
|
||||||
Comment[az]=Matrix protokolu üçün müştəri
|
Comment[ca]=Xat a Matrix
|
||||||
Comment[ca]=Client per al protocol Matrix
|
Comment[ca@valencia]=Xat a Matrix
|
||||||
Comment[ca@valencia]=Client per al protocol Matrix
|
Comment[de]=Über Matrix unterhalten
|
||||||
Comment[de]=Programm für das Matrix-Protokoll
|
Comment[en_GB]=Chat on Matrix
|
||||||
Comment[el]=Πελάτης για το πρωτόκολλο Matrix
|
Comment[eo]=Babilo en Matrix
|
||||||
Comment[en_GB]=Client for the Matrix protocol
|
Comment[es]=Chat en Matrix
|
||||||
Comment[eo]=Kliento por la Matrix-protokolo
|
Comment[eu]=Berriketa Matrix-en
|
||||||
Comment[es]=Cliente para el protocolo Matrix
|
Comment[fi]=Keskustele Matrixissä
|
||||||
Comment[eu]=Matrix protokolorako bezeroa
|
Comment[fr]=Clavarder sur Matrix
|
||||||
Comment[fi]=Asiakas Matrix-yhteyskäytännölle
|
Comment[gl]=Charle en Matrix
|
||||||
Comment[fr]=Client pour le protocole « Matrix »
|
Comment[he]=התכתבות דרך Matrix
|
||||||
Comment[gl]=Cliente para o protocolo Matrix.
|
Comment[hi]=मैट्रिक्स पर चैट करें
|
||||||
Comment[hu]=Kliens a Matrix protokollhoz
|
Comment[hu]=Csevegés Matrixon
|
||||||
Comment[ia]=Cliente per le protocollo de Matrix
|
Comment[ia]=Conversation en ditecto sur Matrix
|
||||||
Comment[id]=Klien untuk protokol Matrix
|
Comment[it]= su Matrix
|
||||||
Comment[ie]=Un cliente del protocol Matrix
|
Comment[ka]=ჩატი Matrix-ზე
|
||||||
Comment[it]=Client per il protocollo Matrix
|
Comment[ko]=Matrix에서 대화하기
|
||||||
Comment[ka]=კლიენტი Matrix-ის პროტოკოლისთვის
|
Comment[lv]=Tērzējiet „Matrix“ tīklā
|
||||||
Comment[ko]=Matrix 프로토콜용 클라이언트
|
Comment[nl]=Chat op Matrix
|
||||||
Comment[lt]=Matrix protokolo kliento programa
|
Comment[pl]=Rozmawiaj na Matriksie
|
||||||
Comment[nl]=Client voor het Matrix-protocol
|
Comment[pt_BR]=Bate papo na Matrix
|
||||||
Comment[nn]=Klient for Matrix-protokollen
|
Comment[ru]=Общение в Matrix
|
||||||
Comment[pa]=ਮੈਟਰਿਕਸ ਪਰੋਟੋਕਾਲ ਲਈ ਕਲਾਈਂਟ ਹੈ
|
Comment[sa]=Matrix इत्यत्र गपशपं कुर्वन्तु
|
||||||
Comment[pl]=Program obsługi protokołu Matriksa
|
Comment[sl]=Klepet na Matrixu
|
||||||
Comment[pt]=Cliente para o protocolo Matrix
|
Comment[sv]=Chatta på Matrix
|
||||||
Comment[pt_BR]=Cliente para o protocolo Matrix
|
Comment[ta]=மேட்ரிக்ஸில் உரையாட உதவும்
|
||||||
Comment[ro]=Client pentru protocolul Matrix
|
Comment[tr]=Matrix üzerinde sohbet edin
|
||||||
Comment[ru]=Клиент для протокола Matrix
|
Comment[uk]=Спілкування у Matrix
|
||||||
Comment[sk]=Klient protokolu Matrix
|
Comment[x-test]=xxChat on Matrixxx
|
||||||
Comment[sl]=Odjemalec za protokol Matrix
|
Comment[zh_CN]=在 Matrix 上聊天
|
||||||
Comment[sv]=Klient för protokollet Matrix
|
Comment[zh_TW]=在 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 通訊協定的用戶端
|
|
||||||
MimeType=x-scheme-handler/matrix;
|
MimeType=x-scheme-handler/matrix;
|
||||||
Exec=neochat %u
|
Exec=neochat %u
|
||||||
Terminal=false
|
Terminal=false
|
||||||
|
|||||||
10602
po/ar/neochat.po
10602
po/ar/neochat.po
File diff suppressed because it is too large
Load Diff
9664
po/ast/neochat.po
9664
po/ast/neochat.po
File diff suppressed because it is too large
Load Diff
11604
po/az/neochat.po
11604
po/az/neochat.po
File diff suppressed because it is too large
Load Diff
@@ -77,7 +77,7 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
|||||||
></term>
|
></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para
|
<para
|
||||||
>L'URI de Matrix per a un usuari o una sala. P. ex. matrix:u/usuari:exemple.org o matrix:r/root:exemple.org. Això farà que el NeoChat intenti obrir la sala o conversa indicada. </para>
|
>L'URI de Matrix per a un usuari o una sala. P. ex. matrix:u/usuari:example.org o matrix:r/root:example.org. Això farà que el NeoChat intenti obrir la sala o conversa indicada. </para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|||||||
10084
po/ca/neochat.po
10084
po/ca/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
10203
po/cs/neochat.po
10203
po/cs/neochat.po
File diff suppressed because it is too large
Load Diff
10372
po/da/neochat.po
10372
po/da/neochat.po
File diff suppressed because it is too large
Load Diff
11237
po/de/neochat.po
11237
po/de/neochat.po
File diff suppressed because it is too large
Load Diff
11366
po/el/neochat.po
11366
po/el/neochat.po
File diff suppressed because it is too large
Load Diff
11167
po/en_GB/neochat.po
11167
po/en_GB/neochat.po
File diff suppressed because it is too large
Load Diff
9236
po/eo/neochat.po
9236
po/eo/neochat.po
File diff suppressed because it is too large
Load Diff
10437
po/es/neochat.po
10437
po/es/neochat.po
File diff suppressed because it is too large
Load Diff
9406
po/eu/neochat.po
9406
po/eu/neochat.po
File diff suppressed because it is too large
Load Diff
9576
po/fi/neochat.po
9576
po/fi/neochat.po
File diff suppressed because it is too large
Load Diff
10789
po/fr/neochat.po
10789
po/fr/neochat.po
File diff suppressed because it is too large
Load Diff
7170
po/gl/neochat.po
Normal file
7170
po/gl/neochat.po
Normal file
File diff suppressed because it is too large
Load Diff
6835
po/he/neochat.po
Normal file
6835
po/he/neochat.po
Normal file
File diff suppressed because it is too large
Load Diff
7120
po/hi/neochat.po
Normal file
7120
po/hi/neochat.po
Normal file
File diff suppressed because it is too large
Load Diff
10740
po/hu/neochat.po
10740
po/hu/neochat.po
File diff suppressed because it is too large
Load Diff
10746
po/ia/neochat.po
10746
po/ia/neochat.po
File diff suppressed because it is too large
Load Diff
11439
po/id/neochat.po
11439
po/id/neochat.po
File diff suppressed because it is too large
Load Diff
11109
po/ie/neochat.po
11109
po/ie/neochat.po
File diff suppressed because it is too large
Load Diff
10701
po/it/neochat.po
10701
po/it/neochat.po
File diff suppressed because it is too large
Load Diff
9644
po/ja/neochat.po
9644
po/ja/neochat.po
File diff suppressed because it is too large
Load Diff
9319
po/ka/neochat.po
9319
po/ka/neochat.po
File diff suppressed because it is too large
Load Diff
9040
po/ko/neochat.po
9040
po/ko/neochat.po
File diff suppressed because it is too large
Load Diff
9695
po/lt/neochat.po
9695
po/lt/neochat.po
File diff suppressed because it is too large
Load Diff
7319
po/lv/neochat.po
Normal file
7319
po/lv/neochat.po
Normal file
File diff suppressed because it is too large
Load Diff
10593
po/nl/neochat.po
10593
po/nl/neochat.po
File diff suppressed because it is too large
Load Diff
9972
po/nn/neochat.po
9972
po/nn/neochat.po
File diff suppressed because it is too large
Load Diff
11421
po/pa/neochat.po
11421
po/pa/neochat.po
File diff suppressed because it is too large
Load Diff
10871
po/pl/neochat.po
10871
po/pl/neochat.po
File diff suppressed because it is too large
Load Diff
11406
po/pt/neochat.po
11406
po/pt/neochat.po
File diff suppressed because it is too large
Load Diff
10921
po/pt_BR/neochat.po
10921
po/pt_BR/neochat.po
File diff suppressed because it is too large
Load Diff
122
po/ru/docs/neochat/man-neochat.1.docbook
Normal file
122
po/ru/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 % Russian "INCLUDE">
|
||||||
|
]>
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
|
||||||
|
SPDX-License-Identifier: CC-BY-SA-4.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
<refentry lang="&language;">
|
||||||
|
<refentryinfo>
|
||||||
|
<title
|
||||||
|
>Руководство пользователя NeoChat</title>
|
||||||
|
<author
|
||||||
|
><firstname
|
||||||
|
>Carl</firstname
|
||||||
|
><surname
|
||||||
|
>Schwan</surname
|
||||||
|
> <contrib
|
||||||
|
>man-страница NeoChat.</contrib
|
||||||
|
> <email
|
||||||
|
>carl@carlschwan.eu</email
|
||||||
|
></author>
|
||||||
|
<date
|
||||||
|
>2022-11-01</date>
|
||||||
|
<releaseinfo
|
||||||
|
>22.09</releaseinfo>
|
||||||
|
<productname
|
||||||
|
>NeoChat</productname>
|
||||||
|
</refentryinfo>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>
|
||||||
|
<command
|
||||||
|
>neochat</command>
|
||||||
|
</refentrytitle>
|
||||||
|
<manvolnum
|
||||||
|
>1</manvolnum>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname
|
||||||
|
>neochat</refname>
|
||||||
|
<refpurpose
|
||||||
|
>Клиент для взаимодействия с протоколом обмена сообщениями Matrix</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
<!-- body begins here -->
|
||||||
|
<refsynopsisdiv id='synopsis'>
|
||||||
|
<cmdsynopsis
|
||||||
|
><command
|
||||||
|
>neochat</command
|
||||||
|
> <arg choice="opt"
|
||||||
|
><replaceable
|
||||||
|
>URI</replaceable
|
||||||
|
></arg
|
||||||
|
> </cmdsynopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1 id="description">
|
||||||
|
<title
|
||||||
|
>Описание</title>
|
||||||
|
<para
|
||||||
|
><command
|
||||||
|
>neochat</command
|
||||||
|
> — приложение для настольных и мобильных устройств, позволяющее общаться в чатах с помощью протокола Matrix. </para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="options"
|
||||||
|
><title
|
||||||
|
>Параметры</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term
|
||||||
|
><option
|
||||||
|
>URI</option
|
||||||
|
></term>
|
||||||
|
<listitem>
|
||||||
|
<para
|
||||||
|
>URI-адрес пользователя или комнаты в Matrix, например: matrix:u/user:example.org и matrix:r/root:example.org. NeoChat попытается открыть указанную комнату или беседу. </para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="bug">
|
||||||
|
<title
|
||||||
|
>Отчёты об ошибках</title>
|
||||||
|
<para
|
||||||
|
>Сообщать об ошибках и отправлять предложения по улучшению можно по адресу <ulink url="https://bugs.kde.org/enter_bug.cgi?product=NeoChat&component=General"
|
||||||
|
>https://bugs.kde.org/enter_bug.cgi?product=NeoChat&component=General</ulink
|
||||||
|
></para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title
|
||||||
|
>Смотрите также</title>
|
||||||
|
<simplelist>
|
||||||
|
<member
|
||||||
|
>Список наиболее часто задаваемых вопросов о Matrix <ulink url="https://matrix.org/faq/"
|
||||||
|
>https://matrix.org/faq/</ulink
|
||||||
|
> </member>
|
||||||
|
<member
|
||||||
|
>kf5options(7)</member>
|
||||||
|
<member
|
||||||
|
>qt5options(7)</member>
|
||||||
|
</simplelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="copyright"
|
||||||
|
><title
|
||||||
|
>Авторские права</title>
|
||||||
|
<para
|
||||||
|
>Авторские права © Tobias Fella, 2020–2022 </para>
|
||||||
|
<para
|
||||||
|
>Авторские права © Carl Schwan, 2020–2022 </para>
|
||||||
|
<para
|
||||||
|
>Лицензия: стандартная общественная лицензия GNU версии 3 или любой более поздней версии <<ulink url="https://www.gnu.org/licenses/gpl-3.0.html"
|
||||||
|
>https://www.gnu.org/licenses/gpl-3.0.html</ulink
|
||||||
|
>></para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
10627
po/ru/neochat.po
10627
po/ru/neochat.po
File diff suppressed because it is too large
Load Diff
7093
po/sa/neochat.po
Normal file
7093
po/sa/neochat.po
Normal file
File diff suppressed because it is too large
Load Diff
11625
po/sk/neochat.po
11625
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>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user