Compare commits

...

1069 Commits

Author SHA1 Message Date
l10n daemon script
96a477f91c GIT_SILENT Sync po/docbooks with svn 2024-01-10 02:13:57 +00:00
Tobias Fella
5a6b0f756d Remove broken network error checks
Fixes #529
2024-01-09 19:59:23 +01:00
l10n daemon script
dbbf975f7a GIT_SILENT Sync po/docbooks with svn 2024-01-09 02:10:55 +00:00
l10n daemon script
e06c2d2f93 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-01-09 02:06:01 +00:00
Albert Astals Cid
5dea17b616 GIT_SILENT Upgrade release service version to 24.01.90. 2024-01-09 00:47:19 +01:00
Tobias Fella
63b6d7ebe0 Remove unused includes 2024-01-08 20:41:59 +01:00
l10n daemon script
652106e6a1 GIT_SILENT Sync po/docbooks with svn 2024-01-08 02:16:01 +00:00
Joshua Goins
3e158b3e60 Stop log spam because subtitleText was called without a valid event
It's up to the call site to check if the event is valid before calling
this function, and it prevents tons of log spam because we didn't check
yet.
2024-01-07 21:43:26 +00:00
Tobias Fella
b9ec33dd94 Remove activeConnection from Config
It's not used anymore
2024-01-07 21:25:55 +01:00
Tobias Fella
69bd1202ba Remove another comment 2024-01-07 21:20:04 +01:00
Tobias Fella
f75c09e130 Remove comment 2024-01-07 21:19:25 +01:00
Tobias Fella
683d216f44 Mark ReactionModel as uncreatable 2024-01-07 19:47:19 +01:00
Tobias Fella
c10bcf1764 Move userConsentRequired to NeoChatConnection 2024-01-07 19:44:37 +01:00
Tobias Fella
9e2bf0da26 Port away from Controller::saveWindowGeometry 2024-01-07 19:39:18 +01:00
James Graham
51f7de117d Refactor LinkPreviewer
Refactor `LinkPreviewer` to take an event and put the functions for getting the link in the class itself. This means the functions in `EventHandler` are no longer required.

This mr also sets up `LinkPreviewer` so that it is automatically updated when an event is edited. This includes changing the link if edited, and it can handle a message having a previous link removed or a one added when one didn't exist before.

Also adds test suite.
2024-01-07 18:07:13 +00:00
Tobias Fella
f361f4e2d8 Don't always html-escape user-specified input when serializing a state event body
We don't want this for the room list subtitle
2024-01-07 16:12:45 +00:00
l10n daemon script
acfb5ab834 GIT_SILENT Sync po/docbooks with svn 2024-01-07 02:42:26 +00:00
James Graham
8bc4500ce1 Fix by allowing RoomPage to access the interactive property of the timeline 2024-01-06 19:49:20 +00:00
Joshua Goins
b96d3dde46 Remove useless interactive set when maximizing images
This doesn't seem to do anything, and it's not easy to turn it back when
the popup is closed
2024-01-06 19:49:20 +00:00
James Graham
fad381c36f Refactor reactions
Currently we effectively create the reactions list in EventHandler then pass that data into a model. This reworks the model so that we just pass in a room and an event and it grabs it's own data. This means that:
- the functions in event handler are no longer required
- the model can update itself to add/remove reactions so no need to handle that in MessageEventModel
- MessageEventModel only needs to create new ReactionModels or remove old ones when no reactions exist anymore

A basic test suite has also been created for the ReactionModel
2024-01-06 17:50:32 +00:00
Tobias Fella
ad083f64b1 Ensure that only one RoomManager exists 2024-01-06 17:46:28 +01:00
Tobias Fella
5c78b23cc2 Slightly fix QML formatting 2024-01-06 17:34:56 +01:00
Tobias Fella
2202063641 Remove stray console log 2024-01-06 17:34:10 +01:00
Tobias Fella
5be15ffa6a Show user display names as plaintext in InviteUserPage 2024-01-06 17:33:39 +01:00
Tobias Fella
a0bafe53a0 Use Plaintext for user displaynames in startchatpage 2024-01-06 17:31:57 +01:00
l10n daemon script
1a39ce9585 GIT_SILENT Sync po/docbooks with svn 2024-01-06 02:11:50 +00:00
Tobias Fella
4a809d57f7 Fix crash when accepting/declining already accepted/declined invite
BUG: 475502
2024-01-05 14:16:21 +01:00
l10n daemon script
c01e42c972 GIT_SILENT Sync po/docbooks with svn 2024-01-05 02:13:27 +00:00
l10n daemon script
6c56f7f4ef GIT_SILENT Sync po/docbooks with svn 2024-01-04 02:16:55 +00:00
l10n daemon script
6d8d5a82c2 GIT_SILENT Sync po/docbooks with svn 2024-01-03 02:14:00 +00:00
Nicolas Fella
daa27b0333 Fix Android build 2024-01-03 01:40:14 +01:00
Nicolas Fella
f6edf0e4cc Add missing include 2024-01-03 01:29:07 +01:00
James Graham
356e8eefe0 Refactor PollHandler
Refactor PollHandler to make it more reliable. This ended up with much more code than I expected as the original intent was just to stop a crash when switching rooms.
- Using a event string was flaky, changing to using an event reference is more reliable.
- Since we're only creating them from NeoChatRoom there is no need to to be able to set properties from QML so only read properties.
- Pass from the MessageEventModel rather than an invokable method.
- Create a basic test suite
- Create properties in PollHandler to remove the need to use content in PollDelegate, this means content is no longer a required role.
2024-01-02 21:22:08 +00:00
Laurent Montel
7ad362225f Use --socket=fallback-x11 in .flatpak-manifest.json 2024-01-02 17:59:31 +01:00
Tobias Fella
d623a8c826 Don't HTML-escape invite notification title 2024-01-02 07:48:52 +00:00
l10n daemon script
b3f0d110d9 GIT_SILENT Sync po/docbooks with svn 2024-01-02 02:09:10 +00:00
James Graham
612b5d7f47 Move all the enums for push rules into their own header file 2024-01-01 16:15:40 +00:00
James Graham
7e9f206348 Clear the emoji picker search when the dialog is closed
Clear the emoji picker search when the dialog is closed

BUG: 472873
2024-01-01 16:15:29 +00:00
l10n daemon script
d5f4a3dd64 GIT_SILENT Sync po/docbooks with svn 2024-01-01 02:13:41 +00:00
James Graham
e807ad9908 Improve the unread marker behaviour
The fixes include:
- improving the timer to make it more reliable
- making sure a read marker is added when changin rooms, this is needed when the messages have already been loaded.
- increase the default timer to 10s to avoid the read marker disappearing and being re-added when a message arrive in quick succession. 

BUG: 465300
2023-12-31 17:47:27 +00:00
Tobias Fella
2d8ad834a7 Fix showing stickers 2023-12-31 18:15:43 +01:00
l10n daemon script
d82dfc7a5b GIT_SILENT Sync po/docbooks with svn 2023-12-31 02:43:10 +00:00
l10n daemon script
1e1e54d4bd SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-12-31 02:27:14 +00:00
l10n daemon script
9043b1c7a1 GIT_SILENT made messages (after extraction) 2023-12-31 01:54:25 +00:00
Tobias Fella
0739f4c661 Re-Enable Flatpak CI 2023-12-27 22:00:29 +00:00
James Graham
29321aeaf3 WindowController test
Create a WindowController test suite.

Also make sure that the class handles m_window being nullptr.
2023-12-24 15:37:56 +00:00
l10n daemon script
9fe44515a7 GIT_SILENT Sync po/docbooks with svn 2023-12-24 02:48:11 +00:00
Tobias Fella
4c3d7ab011 Move Controller::toggleWindow to WindowController 2023-12-23 14:50:36 +00:00
Tobias Fella
d02eee6daa Port away from and remove Controller::initiated 2023-12-23 13:39:41 +00:00
Tobias Fella
a613baa148 Don't crash when invited room doesn't have member state for the current room
This smells illegal, but nothing stops a server from sending that to us so we shouldn't crash.

BUG: 478903
2023-12-23 11:55:22 +00:00
James Graham
4e141e05f0 Cleanup leftover issues from moving ReplyComponent away from GridLayout
Cleanup leftover issues from moving ReplyComponent away from GridLayout.
- Remove leftover GridLayout properties or references to them or convert as required
- Remove unneeded Item wrapper
2023-12-23 11:37:01 +00:00
l10n daemon script
134f1d2ae5 GIT_SILENT Sync po/docbooks with svn 2023-12-23 02:30:01 +00:00
Tobias Fella
9ec3e5b2cc Remove more unused signals 2023-12-23 00:45:00 +01:00
Tobias Fella
15d066b3ed Remove unused variable 2023-12-23 00:39:08 +01:00
Tobias Fella
7694f6c464 Remove unused signal 2023-12-23 00:36:53 +01:00
Marius P
46da4f9777 org.kde.neochat.appdata.xml use https://bugs.kde.org/enter_bug.cgi?product=NeoChat
https://github.com/ximion/appstream/docs/xml/metainfo-component.xml says
"bugtracker - Should point to the software's bug tracking system,
for users to report new bugs.".
2023-12-22 13:10:55 +00:00
l10n daemon script
44e0ef43ac GIT_SILENT Sync po/docbooks with svn 2023-12-22 02:23:21 +00:00
l10n daemon script
5b79371c0a GIT_SILENT made messages (after extraction) 2023-12-22 01:39:20 +00:00
Joshua Goins
3caa5ad2ed Prevent KUnifiedPush-activated daemon from sticking around forever
Erroneous activations of the D-Bus service could cause the daemon to be
launched without any messageReceived signals being called (which then
hooks up the notifications to quit the app.) Now there's a five-second
timeout to prevent it from living too long.
2023-12-21 19:41:41 +00:00
l10n daemon script
a74d78439c GIT_SILENT Sync po/docbooks with svn 2023-12-21 02:47:51 +00:00
l10n daemon script
0b82aeb5cc GIT_SILENT Sync po/docbooks with svn 2023-12-19 02:13:10 +00:00
Albert Astals Cid
bc7aa4e272 GIT_SILENT Upgrade release service version to 24.01.85. 2023-12-18 23:19:45 +01:00
Akseli Lahtinen
d1f421994d Add config import to ReactionDelegate
Forgot to add this in https://invent.kde.org/network/neochat/-/merge_requests/1484
2023-12-18 21:16:47 +00:00
Carl Schwan
b043cbedc9 Make BanSheet frameless
Similar to https://invent.kde.org/network/neochat/-/merge_requests/1487
2023-12-18 19:24:31 +00:00
Carl Schwan
5a469ed126 Make ReportSheet frameless
Similar to https://invent.kde.org/network/neochat/-/merge_requests/1487
2023-12-18 16:45:34 +00:00
Akseli Lahtinen
8d209a5424 Make it easier to spot reaction buttons
In dark themes it can be very hard to spot the reaction
buttons when using compact mode. 

Before:

![image](/uploads/f499f5fd16be353c5fef9b1a08e99522/image.png)

After:

![image](https://invent.kde.org/network/neochat/uploads/86e6cecc546d73481dff79debdcadc3f/image.png)

Also this uses the given colorscheme so it will work everywhere 😄
2023-12-18 16:23:00 +00:00
l10n daemon script
a0937bdcac GIT_SILENT Sync po/docbooks with svn 2023-12-18 02:46:11 +00:00
Carl Schwan
df4eba0191 Make the RemoveSheet frameless 2023-12-17 22:26:05 +00:00
l10n daemon script
9f83cf1c52 GIT_SILENT Sync po/docbooks with svn 2023-12-17 02:11:31 +00:00
James Graham
ddc0bfe786 Make sure that a nullptr connection is not accessed in AccountEmoticonModel
I don't think it possible to open settings without an account connected anymore, however just to make sure I've made sure that a nullptr connection is handled in `AccountEmoticonsModel`.

BUG: 478024
2023-12-13 18:34:59 +00:00
l10n daemon script
09796b6e0b GIT_SILENT Sync po/docbooks with svn 2023-12-13 02:12:01 +00:00
l10n daemon script
73c34c68b7 GIT_SILENT Sync po/docbooks with svn 2023-12-12 02:14:39 +00:00
l10n daemon script
76ab96ef3e GIT_SILENT made messages (after extraction) 2023-12-12 01:37:09 +00:00
l10n daemon script
5a580dd16c GIT_SILENT Sync po/docbooks with svn 2023-12-11 02:11:45 +00:00
l10n daemon script
918887525b SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-12-11 02:06:11 +00:00
l10n daemon script
500ebbecbf GIT_SILENT made messages (after extraction) 2023-12-11 01:35:18 +00:00
James Graham
8062dface6 ActionsHandler test
Add basic test suite to make sure that ActionsHandler rejects attempts to handleMessage if either m_room or chatBarCacher are nullptr.
2023-12-10 18:14:51 +00:00
James Graham
8d717b78ac Move the function to get a subtitle string to eventhandler 2023-12-10 13:19:13 +00:00
l10n daemon script
4751ac6acc GIT_SILENT Sync po/docbooks with svn 2023-12-10 02:46:07 +00:00
James Graham
1d8ffb22ee TestUtils
Create TestUtils with TestRoom and use this for all tests which require it
2023-12-09 19:32:48 +00:00
James Graham
a035d6542d Fix spoilers in roomlist subtitles
Make sure spoilers aren't revealed in SubtitleRole like in LastEventRole then remove LastEventRole because it is no longer used
2023-12-09 15:30:19 +00:00
Laurent Montel
d7230022f6 Port [=] operator 2023-12-09 15:47:26 +01:00
James Graham
d25340bc31 Fix inline custom emojis in codeblocks
Make sure that custom emojis in inline code blocks are not turned into images.

By calling preprocess text in `texthandler` the whole function can be simplified as it will now never be called on any text inside any code block (which was the reason for all the split stuff previously).

BUG: 477512
2023-12-09 14:28:00 +00:00
l10n daemon script
c396024a26 GIT_SILENT Sync po/docbooks with svn 2023-12-08 02:12:32 +00:00
James Graham
65b94890ab Add test for pending events into the MessageEventModelTest 2023-12-06 20:07:18 +00:00
l10n daemon script
682004d9a2 GIT_SILENT Sync po/docbooks with svn 2023-12-06 02:18:06 +00:00
Tobias Fella
decf797180 Don't HTML-escape display names in room list subtitles 2023-12-05 16:58:24 +00:00
l10n daemon script
552b6dd913 GIT_SILENT Sync po/docbooks with svn 2023-12-05 02:10:40 +00:00
l10n daemon script
e6358eca16 GIT_SILENT Sync po/docbooks with svn 2023-12-04 02:12:32 +00:00
James Graham
f3bacad460 Add more tests to MessageEventModelTest 2023-12-03 17:58:17 +00:00
Tobias Fella
862f4363a9 Use HTML-escaped display name in avatar tooltip 2023-12-03 16:40:09 +00:00
Tobias Fella
9b3a3dc562 Always clip roomlist
The current behavior is a leftover from some previous component
2023-12-03 14:59:08 +01:00
Tobias Fella
c2641a5fc2 Cleanup error reporting 2023-12-03 14:39:31 +01:00
Tobias Fella
1213ba5916 Don't show notifications view button when room list is collapsed
Looks broken
2023-12-03 14:23:33 +01:00
Tobias Fella
0521ff2c4d Move PasswordStatus out of Controller 2023-12-03 14:09:41 +01:00
Tobias Fella
65c892787e Don't suggest kicking or banning users with a power level too high for us to kick 2023-12-03 13:56:41 +01:00
l10n daemon script
7541c192bf GIT_SILENT Sync po/docbooks with svn 2023-12-03 02:11:34 +00:00
l10n daemon script
c692d7e679 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-12-03 02:06:11 +00:00
Joshua Goins
44a9a491af Add more missing icons on Android 2023-12-02 17:27:56 +00:00
Emir SARI
f8cae7c143 Fix i18n regression 2023-12-02 17:09:19 +00:00
Tobias Fella
4f2b559126 Show author name when previous message was deleted
This will cause the name to show up more often than necessary, but that's better than not showing it at all, which leads to messages being attributed to the wrong person.
The root cause here is a mismatch in event visibility between EventStatus::Hidden and filterAcceptsRow in MessageFilterModel, which will be fixed in a future patch.
2023-12-02 17:12:02 +01:00
James Graham
46fd288a95 Add some clarification around around offical and canonical parents 2023-12-02 13:21:26 +00:00
Joshua Goins
3a1cac6c99 Remove ffmpeg from Android build
This doesn't work on Android right now, and should allow the apk to at least launch.
2023-12-02 03:53:55 +00:00
l10n daemon script
225092a193 GIT_SILENT Sync po/docbooks with svn 2023-12-01 02:13:35 +00:00
Heiko Becker
2fcb17621c GIT_SILENT Update Appstream for new release
(cherry picked from commit 17b14aa556)
2023-11-30 18:35:03 +01:00
l10n daemon script
69e3ee862f GIT_SILENT Sync po/docbooks with svn 2023-11-30 02:08:31 +00:00
James Graham
47c12cb582 MessageEventModel test
Add basic test suite for MessageEventModel
2023-11-29 19:06:43 +00:00
l10n daemon script
94cf75af68 GIT_SILENT Sync po/docbooks with svn 2023-11-29 02:12:57 +00:00
ivan tkachenko
259b9884c7 Set WrapMode on all TextArea components, and fix up some of the Labels
Upstream styles do not provide any wrapping by default, and thus we
should not rely on deceptively convenient override in qqc2-desktop-style.

See https://invent.kde.org/frameworks/qqc2-desktop-style/-/merge_requests/331
2023-11-28 22:26:57 +00:00
l10n daemon script
2980dc49e4 GIT_SILENT Sync po/docbooks with svn 2023-11-28 02:11:26 +00:00
Tobias Fella
5e12f50899 Wrap text in poll delegates
BUG: 477629
2023-11-27 20:44:19 +00:00
James Graham
79940f707f By default only show leave/join state events
As discussed in network/neochat#609
2023-11-27 18:15:48 +00:00
l10n daemon script
e7024a270c GIT_SILENT Sync po/docbooks with svn 2023-11-27 02:12:56 +00:00
Tobias Fella
1a561f6649 Fix linking on windows 2023-11-26 17:40:50 +01:00
Tobias Fella
2cbb6ed65c Enable windows qt6 CI 2023-11-26 15:22:26 +00:00
James Graham
ab4639926a Fix isEdit Check MessageEditComponent
Stop the console being pinged with qrc:/org/kde/neochat/qml/MessageEditComponent.qml:158: TypeError: Cannot read property 'isEditing' of undefined.

Fixes network/neochat#629
2023-11-26 15:21:18 +00:00
Tobias Fella
89b6c54f25 Fix state delegate spacing 2023-11-26 15:06:35 +01:00
James Graham
27c9c62564 ResolveResource
Use ResolveResource rather than calling individual functions like visit user and room
2023-11-26 12:23:28 +00:00
l10n daemon script
bb8ffb02d1 GIT_SILENT Sync po/docbooks with svn 2023-11-26 02:48:22 +00:00
James Graham
201aa82c04 Remove controller::joinRoom
Remove controller::joinRoom in favour of using RoomManager::OpenResource
2023-11-25 15:07:15 +00:00
l10n daemon script
704430db7a GIT_SILENT Sync po/docbooks with svn 2023-11-25 02:08:53 +00:00
Albert Astals Cid
dcbbbd9296 GIT_SILENT Upgrade release service version to 24.01.80. 2023-11-25 00:51:46 +01:00
Tobias Fella
410258c478 Join rooms when visiting them
BUG: 477261
2023-11-24 19:11:15 +01:00
Tobias Fella
6baf2e4888 Fix crash for invalid media uris
BUG: 476698
2023-11-24 18:50:30 +01:00
Tobias Fella
dd6eaac556 Don't crash when sticker pack room doesn't exist
BUG: 476923
2023-11-24 16:43:16 +01:00
l10n daemon script
840903128c GIT_SILENT Sync po/docbooks with svn 2023-11-24 02:10:11 +00:00
l10n daemon script
68f0ca96da GIT_SILENT Sync po/docbooks with svn 2023-11-23 02:13:47 +00:00
l10n daemon script
faf7af06fe GIT_SILENT Sync po/docbooks with svn 2023-11-22 02:09:37 +00:00
l10n daemon script
4ef67c3e0d GIT_SILENT Sync po/docbooks with svn 2023-11-21 02:09:50 +00:00
James Graham
5efd17d370 Loading and End of Timeline Delegates
Add delegate for showing the user a loading indicator and for the beginning of the timeline.

BUG: 455045
BUG: 465285
2023-11-20 17:10:56 +00:00
l10n daemon script
0dbef58ff2 GIT_SILENT Sync po/docbooks with svn 2023-11-20 02:44:00 +00:00
Tobias Fella
6a3df8baf4 Fix initial visual focus in welcomepage 2023-11-19 14:09:08 +01:00
l10n daemon script
2fc973f218 GIT_SILENT Sync po/docbooks with svn 2023-11-19 02:26:37 +00:00
l10n daemon script
7d16999c44 GIT_SILENT Sync po/docbooks with svn 2023-11-18 02:09:37 +00:00
Laurent Montel
f9ba31f2dc Remove unused variables 2023-11-17 10:23:58 +00:00
Laurent Montel
d4ad773ff1 Remove unused "this" argument 2023-11-17 09:36:35 +00:00
Laurent Montel
822a4dc500 Use nullptr 2023-11-17 07:34:46 +00:00
l10n daemon script
bfd1d431c1 GIT_SILENT Sync po/docbooks with svn 2023-11-17 02:12:16 +00:00
Carl Schwan
94bf2481f0 Fix spacing in login screen 2023-11-16 22:43:45 +01:00
Tobias Fella
5c32520c35 Add appium test for opening the user details sheet and fix some accessibility problems 2023-11-16 19:47:13 +01:00
l10n daemon script
de47597f6e GIT_SILENT Sync po/docbooks with svn 2023-11-16 02:21:25 +00:00
l10n daemon script
7780a72888 GIT_SILENT Sync po/docbooks with svn 2023-11-15 02:13:48 +00:00
Carl Schwan
1f8c07fedf Make room timeline non interactible
Currently trying to scroll with this scrollbar is probablematic and it's
unlikely we will find an easy solution to fix it, so make it non interactible.
2023-11-14 19:16:02 +00:00
Tobias Fella
877575b4d3 Fix kirigami name 2023-11-14 19:18:02 +01:00
l10n daemon script
1181df4db2 GIT_SILENT Sync po/docbooks with svn 2023-11-14 02:12:52 +00:00
Joshua Goins
5be2113b32 Add matrix: URL to push notifications 2023-11-13 20:02:07 +00:00
l10n daemon script
7ad7af56e8 GIT_SILENT Sync po/docbooks with svn 2023-11-13 02:12:13 +00:00
Joshua Goins
d3148f8c8b Don't start the entire NeoChat backend when receiving push notifications
This adds a dedicated "set up for push notifications only" function in
Controller, which only sets up the KUnifiedPush connector for receiving
the message and then quitting right afterward. If the user tries to
open a notification, then it will quit and open the main client.
2023-11-12 17:08:15 -05:00
Joshua Goins
100f595026 Add handler for KUnifiedPush messageReceived events 2023-11-12 21:46:33 +00:00
Joshua Goins
15ba6d58e2 Only attempt to setup push notifications on the first syncDone 2023-11-12 15:53:15 -05:00
James Graham
61ad892732 Handle multiple line names
Add function to get the display name for an author on a single line as nothing stops there being linebreaks.

BUG:476731
2023-11-12 18:46:04 +00:00
James Graham
2a3e1dfcd7 Read Marker Hidden
Only show the read marker if there is a non-hidden event earlier in the timeline

fixes network/neochat#615
2023-11-12 16:32:08 +00:00
Joshua Goins
d1dc6fc4ed Fix typo preventing APK from building 2023-11-12 15:36:38 +00:00
James Graham
6dc30a9ca7 Fix hover action position when wide
Fix the positioning of the hover actions when the window is wide by using the content x pos
2023-11-12 14:20:46 +00:00
James Graham
ae0c5ffaef Improve State Text Translatability
Make the state state strings less ambiguous for the purpose of translation.

BUG: 476358
2023-11-12 14:08:36 +00:00
Tobias Fella
fc546d4a43 Add notifications view 2023-11-12 13:16:09 +00:00
Tobias Fella
96e62e3ebe Disable system tray integration by default 2023-11-12 12:46:16 +00:00
Joshua Goins
d979cd2fbc Add Snap Store link in README 2023-11-12 04:01:26 +00:00
l10n daemon script
22298181cb GIT_SILENT Sync po/docbooks with svn 2023-11-12 02:22:14 +00:00
Tobias Fella
1312fde470 Cleanup code 2023-11-12 01:46:23 +01:00
Tobias Fella
7fe2feb1e4 Make NeoChat not shut down when disabling close-to-tray 2023-11-12 01:46:06 +01:00
Ingo Klöcker
67fb5d0824 Add option used on Binary Factory 2023-11-11 22:06:59 +00:00
Ingo Klöcker
359114bd3d Tell Craft that we need Qt 6 and master of the dependencies 2023-11-11 22:06:59 +00:00
Ingo Klöcker
3db9f1198b Add CI template for building APKs 2023-11-11 22:06:59 +00:00
Tobias Fella
2435a6b953 Fix opening account editor 2023-11-11 23:06:26 +01:00
Tobias Fella
e6c8b3fa4b Simplify some android code 2023-11-11 22:59:27 +01:00
Tobias Fella
2d55dca508 Don't allow changing the power level for users with a power level higher or equal to ours
The server won't allow it anyway
2023-11-11 18:20:54 +00:00
Tobias Fella
bbb0bc3092 Improve and fix powerlevels dialog 2023-11-11 17:37:27 +00:00
James Graham
4065aa6a2e Fix linkpreview tooltip
Fix linkpreview tooltip so that the correct text is always shown.

BUG: 467106
2023-11-11 17:29:15 +00:00
Tobias Fella
5942eac5ed Force plaintext in permissions settings 2023-11-11 18:09:03 +01:00
Tobias Fella
85c2b7dada Fix crash on shutdown 2023-11-11 16:03:35 +01:00
Carl Schwan
86ef921cdb Fix alignment user info
Otherwise we end up with two times largeSpacing as right margin for the
user info.
2023-11-11 15:40:15 +01:00
James Graham
aab69c5bae Suggested rooms spaces
Add the ability to set and show suggested rooms for spaces. 

This is just adding the basic functionality, we can do more things with it later like sort/filter the space home for example.
2023-11-11 13:32:19 +00:00
Carl Schwan
624578ec77 Improve welcome page
- Don't use card for welcome message and instead use same layout as
  kwordquiz
- Add separator between login and register button
- Add type annotation in functions
2023-11-11 13:12:56 +00:00
l10n daemon script
197ff984fd GIT_SILENT Sync po/docbooks with svn 2023-11-11 02:19:28 +00:00
James Graham
a26337d5f4 Fix ServerListModel
The server list needs to be populated on connection change as this is instantiated from QML
2023-11-10 20:32:51 +00:00
Joshua Goins
31b4eefadd Move closeDialog signal from Loading to LoginStep
This prevents errors because we try to connect to a non-existent signal
if the step is anything but Loading.
2023-11-10 18:40:37 +00:00
Joshua Goins
b8e592f8ba Fix wrong argument being passed into maximize component creation
It's supposed to refer to the attached property on QQC2.Overlay, not
QQC2.ApplicationWindow
2023-11-10 18:36:49 +00:00
Joshua Goins
555d23863e Port to QEvent::ApplicationPaletteChange
The paletteChanged on QGuiApplication is deprecated in Qt6
2023-11-10 18:30:27 +00:00
Joshua Goins
ffa2d5dc0e Fix push notification registration
Now it should regularly happen after login
2023-11-10 18:08:52 +00:00
Joshua Goins
9987edbaf2 Note that profileTag is intentionally left empty 2023-11-10 18:08:52 +00:00
Joshua Goins
d90298392d Only run setupPushNotification once for new accounts 2023-11-10 18:08:52 +00:00
Joshua Goins
600dbd0603 Remove unnecessary activeConnection() call in setupPushNotifications 2023-11-10 18:08:52 +00:00
Joshua Goins
2179e2cc35 Fix QCoro headers 2023-11-10 18:08:52 +00:00
Joshua Goins
8119ea3ccb Use auto in NeoChatConnection::setupPushNotifications 2023-11-10 18:08:52 +00:00
Joshua Goins
3fc125a798 Move push notification setup to NeoChatConnection 2023-11-10 18:08:52 +00:00
Joshua Goins
99f6778df4 Register for push notifications
This sets it up so the homeserver will give us push notifications, but
we aren't handling them yet.
2023-11-10 18:08:52 +00:00
Joshua Goins
f7bd24db34 Depend on QCoro::Network
For awaiting on QNetworkReply
2023-11-10 18:08:52 +00:00
Joshua Goins
41c2f9c4d5 Re-arrange main.cpp and add no gui option when DBus activated
We don't want the QML engine initialized at all when launching on
notifications, it'll be useless there.
2023-11-10 18:08:52 +00:00
Joshua Goins
56d5f3036b Change name of notify argument to dbus-activated 2023-11-10 18:08:52 +00:00
Tobias Fella
21bb7dce21 Fix background color of UserInfo
Previously, this would change when the window lost focus, which looks strange
2023-11-10 16:16:29 +01:00
l10n daemon script
11081719a7 GIT_SILENT Sync po/docbooks with svn 2023-11-10 02:22:55 +00:00
Joshua Goins
980de7d85d Use go.kde.org for the Matrix link, mention Matrix wiki page
I moved NeoChat up next to Element on go.kde.org, so it's good marketing
;-)
2023-11-09 16:53:36 -05:00
Joshua Goins
7735313b0c Add DBus service for NeoChat and link to KUnifiedPush if found 2023-11-09 21:40:09 +00:00
Joshua Goins
1a3055df86 Add optional KUnifiedPush dependency 2023-11-09 21:40:09 +00:00
Tobias Fella
84cad630cd Refactor and fix ChatBox layouting
BUG: 474616
2023-11-09 20:19:09 +00:00
James Graham
0beb5df08d Hide the search field for room members in a direct chat.
Hide the search field for room members in a direct chat as there are no members to search.
2023-11-09 20:11:38 +00:00
Tobias Fella
4ef44b8e93 Track online status per connection 2023-11-09 19:38:43 +01:00
l10n daemon script
59153be006 GIT_SILENT Sync po/docbooks with svn 2023-11-09 02:12:54 +00:00
l10n daemon script
50be96f762 GIT_SILENT Sync po/docbooks with svn 2023-11-08 09:27:31 +00:00
Tobias Fella
819d88e18c Assorted Qt6 android fixes 2023-11-07 23:17:38 +01:00
James Graham
dbbad2cf13 Restricted Room Security
Create the required ux to allow the restricted room security setting to be re-enabled

BUG: 471307
2023-11-07 20:43:49 +00:00
Albert Astals Cid
08b84c6592 GIT_SILENT Upgrade release service version to 24.01.75. 2023-11-07 21:11:26 +01:00
l10n daemon script
b8abf0540d GIT_SILENT Sync po/docbooks with svn 2023-11-07 03:22:56 +00:00
Tobias Fella
7f9e709559 Improve initial active connection handling
If the last active connection is not reachable (server down, keychain problems,
token revoked, etc.), NeoChat currently fails to load at all, with the only fix
being to delete a line from the config file. This is surprisingly hard to fix with
a nice UX as long as we stick to the principle of loading the user's last active
connection automatically.

This patch thus drops that principle; instead, the user is always asked to choose
the connection to continue with.
2023-11-06 12:26:25 +00:00
l10n daemon script
c4f6abee9d GIT_SILENT Sync po/docbooks with svn 2023-11-06 02:17:00 +00:00
Joshua Goins
1a4947b98a Set accessible press actions for RoomDelegate 2023-11-05 18:09:20 -05:00
Tobias Fella
6ba2b715c3 Port away from Controller::activeConnectionIndex 2023-11-05 21:03:04 +00:00
Joshua Goins
e9e1e223f7 Allow right-clicking on a room without selecting it
Same idea as the fix I did for spaces, we introduce a new signal called
selected instead of using ItemDelegate's button signals.
2023-11-05 20:43:08 +00:00
Joshua Goins
006da1fb16 Show color scheme option on Android
This works on Android now, and the rest of the code changed to enable it
anyway.
2023-11-05 20:38:33 +00:00
James Graham
3aff1795c8 Accounts Popup Close on Hide
Make sure that the accounts popup is closed when the UserInfo component is hidden
2023-11-05 19:57:15 +00:00
Joshua Goins
576b1f928f Set RoomManager connection when opening a room
This was only set for the Controller, but it needed to be set for the
RoomManager too before opening a room. This could cause NeoChat to crash
when activating a notification, for example.
2023-11-05 14:48:55 -05:00
l10n daemon script
fc3ab50701 GIT_SILENT Sync po/docbooks with svn 2023-11-05 14:37:01 +00:00
James Graham
e7fa3ad524 Explicit room parameter DirectChatDrawerHeader
Create explicit room parameter and reference it in DirectChatDrawerHeader
2023-11-05 13:49:13 +00:00
James Graham
5adffddbd8 Fix InviteUserPage
Port the InviteUserPage to Qt6 and fix close action

fixes network/neochat#614
2023-11-05 13:45:10 +00:00
Tobias Fella
1d95d5aa15 Fix Runner and MatrixImageProvider singletons 2023-11-05 14:35:28 +01:00
Carl Schwan
dabd6291a5 roomlist: Fix ListSectionDelegate usage
The default property of ListSectionDelegate is already an alias to the
RowLayout.data and trying to use RoomLayout.children didn't work as
expected.
2023-11-05 13:08:29 +00:00
Tobias Fella
0e55c3b38f Port some things away from Controller::activeConnection 2023-11-05 13:02:18 +00:00
Carl Schwan
ff4cf86ea5 Add profile picture in about data 2023-11-05 12:17:26 +01:00
l10n daemon script
f4d5ccbf12 GIT_SILENT Sync po/docbooks with svn 2023-11-05 11:14:20 +00:00
l10n daemon script
192601d358 GIT_SILENT Sync po/docbooks with svn 2023-11-05 01:41:24 +00:00
l10n daemon script
d7c432119e GIT_SILENT Sync po/docbooks with svn 2023-11-04 17:24:07 +00:00
Tobias Fella
eddb2b73c2 Use new notification action api 2023-11-04 16:18:00 +00:00
Tobias Fella
0c60bfdb83 Don't crash on quit
BUG: 474386
2023-11-04 16:03:54 +00:00
James Graham
2bfb2fa1f9 Improve ChatDocumentHandler handling of null properties
Improve ChatDocumentHandler handling of null properties
2023-11-04 14:43:31 +00:00
l10n daemon script
d1aac971bf GIT_SILENT Sync po/docbooks with svn 2023-11-04 12:51:19 +00:00
Heiko Becker
284cadf305 GIT_SILENT Update Appstream for new release
(cherry picked from commit 753e879556)
2023-11-04 12:33:19 +01:00
l10n daemon script
4697b7fcf1 GIT_SILENT Sync po/docbooks with svn 2023-11-04 02:10:15 +00:00
Tobias Fella
9f356912c9 Add placeholder message to devices page 2023-11-03 22:06:33 +00:00
Tobias Fella
1cf891f845 Fix device logout dialog 2023-11-03 22:06:14 +00:00
Joshua Goins
52e2d636b9 Adjust tests to blockquote formatting changes 2023-11-03 21:52:47 +00:00
Joshua Goins
dc6b539ddf Add somewhat better blockquote styling
Quotes are now "quoted" and also have a different background.
2023-11-03 21:52:47 +00:00
Joshua Goins
e3cf85aa8c Yank "Qt5" out of the description for libQuotient
We aren't using thr Qt5 version anymore, and it's not really a point in
describing which exact Qt version we use with libQuotient in a user
facing string like this anyway.
2023-11-03 17:39:02 -04:00
James Graham
2065eb6684 Mobile explore component
Create a mobile version of explore component and place it at the bottom for single handed use. This also refactors the UserInfo component so it can be at the top on mobile as well as the bottom on dektop.

This should have no effect on desktop and should be identical.

![image](/uploads/9b3133fbde74ca27069d6b039efb1079/image.png)
2023-11-03 17:22:57 +00:00
Tobias Fella
9cac2a8abd Delete KeywordNotificationRuleModel
It's unused
2023-11-03 17:39:10 +01:00
Tobias Fella
feb87e6f70 Show QR codes in UserDetailDialog 2023-11-03 16:23:54 +00:00
l10n daemon script
a0057b8a49 GIT_SILENT Sync po/docbooks with svn 2023-11-03 02:12:15 +00:00
Tobias Fella
dbb0269354 Fix sending locations 2023-11-02 19:46:06 +01:00
Tobias Fella
7fdb617b33 Port RoundButtons in TimelineView to FloatingButton
BUG: 476124
2023-11-02 18:15:57 +01:00
Tobias Fella
d798b0dec9 HTML-escape mentions 2023-11-02 17:04:26 +00:00
James Graham
95cf23eb5b Remove GridLayout ReplyComponent
Stop using GridLayout in ReplyComponent as they are notoriously terribleRemove
2023-11-02 17:04:18 +00:00
James Graham
7e3db20229 Remove isEdit from ChatDocumentHandler
Remove isEdit from ChatDocumentHandler as it was made redundant by the ChatCache rework.
2023-11-02 17:00:41 +00:00
Laurent Montel
12689babfb Add missing moc 2023-11-02 08:50:43 +01:00
l10n daemon script
211407da44 GIT_SILENT Sync po/docbooks with svn 2023-11-02 02:13:36 +00:00
l10n daemon script
400a84e48d GIT_SILENT Sync po/docbooks with svn 2023-11-01 02:15:14 +00:00
Tobias Fella
7a45640e5e Fix string 2023-10-31 17:13:05 +01:00
Tobias Fella
8af20885ab Add account / device security settings page 2023-10-31 14:59:08 +01:00
Tobias Fella
4033f07272 Port away from custom format* QML functions 2023-10-31 14:56:52 +01:00
Tobias Fella
5df4fa297d Move Controller::setBlur and Controller::hasWindowSystem to WindowController 2023-10-31 09:17:44 +00:00
Tobias Fella
33c5b418d2 Move Controller::openOrCreateDirectChat to NeoChatConnection 2023-10-31 09:16:59 +00:00
l10n daemon script
69d378a17b GIT_SILENT Sync po/docbooks with svn 2023-10-31 02:11:02 +00:00
Tobias Fella
f1b1b8ce53 Remove unused include 2023-10-30 21:29:44 +01:00
Tobias Fella
526d4748e0 Remove unused includes 2023-10-30 21:27:36 +01:00
Tobias Fella
c5f93adbf4 Don't percent encode job parameter 2023-10-30 20:51:44 +01:00
Tobias Fella
61630cbe90 Rename "Security.qml" to "RoomSecurity.qml" 2023-10-30 11:07:42 +01:00
l10n daemon script
8c435e9d6d GIT_SILENT Sync po/docbooks with svn 2023-10-30 02:13:41 +00:00
James Graham
57978b1a6e EventHandler Nullptr checks
So I got lazy halfway through doing this the first time.

Add missing checks for null m_room and m_event to EventHandler and add tests for them.
2023-10-29 14:51:25 +00:00
James Graham
f3c4d9449a Move remaining tests to external Json files
Title
2023-10-29 13:12:05 +00:00
James Graham
9b37777f20 Remove getUsers
Remove getUsers as it's unused
2023-10-29 13:07:45 +00:00
l10n daemon script
d6d6c161db GIT_SILENT Sync po/docbooks with svn 2023-10-29 02:23:11 +00:00
Tobias Fella
772bca5ba6 Fix sending messages that were typed before switching rooms 2023-10-28 17:21:12 +02:00
Tobias Fella
036a60a095 Don't linkify urls in code blocks
BUG: 475301
2023-10-28 16:19:32 +02:00
Tobias Fella
b3315e1ed4 Add test for bug 475301
BUG: 475301
2023-10-28 16:19:31 +02:00
Tobias Fella
d300e9cf52 Slightly reformat cmake 2023-10-28 16:18:21 +02:00
Tobias Fella
1f4bcd150f Make SectionDelegate separator thickness consistent with other Separators 2023-10-28 16:16:37 +02:00
Tobias Fella
9ad8894983 Fix connection switching 2023-10-28 15:13:22 +02:00
Tobias Fella
9e63ca5eb7 Remove ShimmerGradient
It's unused
2023-10-28 14:08:51 +02:00
Tobias Fella
ade66242bb Remove unused import 2023-10-28 13:59:23 +02:00
Tobias Fella
2c6932b4cb Fix crash when there is an empty logging category
BUG: 475248
2023-10-28 09:12:59 +00:00
l10n daemon script
5cce9e7205 GIT_SILENT Sync po/docbooks with svn 2023-10-28 02:20:45 +00:00
Tobias Fella
7dd3ad9548 Hide info banner when changing room
BUG: 476128
2023-10-28 00:21:57 +02:00
Tobias Fella
f690b76efa Fix crash for events that are not RoomMessageEvents
BUG: 476153
2023-10-27 22:11:12 +02:00
James Graham
87b8d6710e Update Kirigami PlatformTheme
Update Kirigami PlatformTheme to new path.
2023-10-27 16:13:22 +00:00
l10n daemon script
965b890346 GIT_SILENT Sync po/docbooks with svn 2023-10-27 02:16:58 +00:00
Tobias Fella
02b4e5cc70 Port away from CheckableListItem 2023-10-26 10:07:35 +00:00
Tobias Fella
410add04fb Fix subtle erroneous event casts
Sometimes, the previous code would static_cast an EncryptedEvent to a RoomMessageEvent.
This was mostly unnoticed, since the types are similar enough.
2023-10-26 10:03:09 +00:00
l10n daemon script
b575b1e700 GIT_SILENT Sync po/docbooks with svn 2023-10-26 02:27:46 +00:00
l10n daemon script
5828ee1ada SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-10-26 02:17:19 +00:00
l10n daemon script
a64c80109e GIT_SILENT made messages (after extraction) 2023-10-26 01:45:07 +00:00
Tobias Fella
de47f7f2fa Remove duplicate signal 2023-10-25 20:28:14 +02:00
Laurent Montel
19adc7b9e5 GIT_SILENT: use KLocalizedString::setApplicationDomain(QByteArrayLiteral => saving one deep data copy 2023-10-25 08:25:27 +02:00
l10n daemon script
23f60a59fe GIT_SILENT Sync po/docbooks with svn 2023-10-25 02:25:42 +00:00
l10n daemon script
946ba2e56d GIT_SILENT made messages (after extraction) 2023-10-25 01:50:11 +00:00
Tobias Fella
9dcb7b49fa Use KColorScheme 2023-10-24 07:55:01 +00:00
Tobias Fella
52f5901642 Update replacement room filtering in real-time 2023-10-24 07:51:15 +00:00
Tobias Fella
d4b4a7e1ff Only hide replaced rooms if we're joined to the replacement room 2023-10-24 07:51:15 +00:00
Tobias Fella
4449678b74 Don't abort in the message logger
Let the app do whatever it would do naturally
2023-10-24 07:32:09 +00:00
Tobias Fella
19e197e0ec Fix maps
In Qt6, Map just shows a static map, while MapView allows for zooming, moving, etc.
2023-10-24 07:08:05 +00:00
l10n daemon script
cfc5202645 GIT_SILENT Sync po/docbooks with svn 2023-10-24 02:14:54 +00:00
Tobias Fella
9b80d9e7aa Minor QML cleanup 2023-10-23 22:28:34 +02:00
Tobias Fella
dc409387bd Remove check for libQuotient 0.8 2023-10-23 22:00:34 +02:00
l10n daemon script
1e73a7bda4 GIT_SILENT Sync po/docbooks with svn 2023-10-23 02:12:23 +00:00
James Graham
ef1d62d45c ActionsHandler poperties
Make sure that all low level components get ActionsHandler through actual properties rather than magically
2023-10-22 13:39:34 +00:00
James Graham
c2d82750b1 Fix opening a room in a new window.
Fix opening a room in a new window. This is done by makeing the model top level parameters in RoomPage set from RoomManager but overwritten by RoomWindow
2023-10-22 11:57:27 +00:00
l10n daemon script
c97d276b36 GIT_SILENT Sync po/docbooks with svn 2023-10-22 02:48:07 +00:00
l10n daemon script
681a0b1e93 GIT_SILENT Sync po/docbooks with svn 2023-10-21 02:16:44 +00:00
James Graham
39556f45ab Send Threaded Messages
This MR deals with only sending threaded messages. Showing threads will turn up in a follow up. This allows you to start a new thread by clicking reply in thread to a normal message. 

You can also do a threaded reply to a threaded message in the main timeline at the moment because those messages aren't shown in a separate thread timeline yet but will be in future.
2023-10-20 17:07:09 +00:00
Joshua Goins
3c7774800a Remove now unused QDataStream operators for Emoji 2023-10-20 15:27:33 +00:00
Joshua Goins
bc7530eaa1 Store last used emojis in the state config file
Instead of crumming up the main settings file with the last used emojis,
they now live in the state (where they belong.)
2023-10-20 15:27:33 +00:00
l10n daemon script
82d11f79d6 GIT_SILENT Sync po/docbooks with svn 2023-10-20 02:11:46 +00:00
Joshua Goins
25d0368d41 Compact the event cache JSON
By default, Qt will spit out indented JSON when writing to the config
file, which is useless as it wastes space and no one will read this.
2023-10-19 20:46:17 +00:00
Joshua Goins
83b7e7d121 Use KSharedConfig::openStateConfig() instead of using a "data" file
This function will automatically create a "neochatstarerc" for us, and
KConfig will decide the best place for us to place our state. It won't
always be in AppDataLocation.
2023-10-19 20:39:07 +00:00
Tobias Fella
26fd26f9fd Enable android qt6 ci 2023-10-19 20:18:15 +00:00
James Graham
0029567c3a Reorganise HoverActions Code
Move most of the external code for hover actions into the component.
2023-10-19 19:38:57 +00:00
Laurent Montel
c7614caf41 There's no QVector anymore, QList is the QVector in Qt6 2023-10-19 13:41:46 +02:00
l10n daemon script
6571dbe554 GIT_SILENT Sync po/docbooks with svn 2023-10-19 02:14:15 +00:00
l10n daemon script
b3a29068cc GIT_SILENT Sync po/docbooks with svn 2023-10-18 02:15:55 +00:00
Tobias Fella
5adda55a85 Show rooms instead of spaces in JoinRoomPage 2023-10-17 19:14:07 +00:00
l10n daemon script
d56f0d6086 GIT_SILENT Sync po/docbooks with svn 2023-10-17 02:10:40 +00:00
Tobias Fella
60772be391 Enforce symbolic icon in ExploreComponent 2023-10-16 22:12:13 +02:00
Yuri Chornoivan
27f1679741 Fix minor typo 2023-10-16 09:27:27 +03:00
l10n daemon script
838596c3ae GIT_SILENT Sync po/docbooks with svn 2023-10-16 02:10:50 +00:00
James Graham
a57744891a ChatCache
Move the functionality to cache the contents of a chat bar from the room directly and to a new ChatCache object. This works pretty much the same with a few extra check and balances, this also made it easy to put a test suite around the functionality so I did. The current functionality should be identical to what exists.

This is in prep for threads which will require managing even more caches if we create one per thread.
2023-10-15 12:55:56 +00:00
James Graham
f5417a6227 New parent dialog
Move the add new offical parent to a dialog and make sure that the join room dialog only shows spaces.
2023-10-15 11:28:17 +00:00
l10n daemon script
ac6f9ea219 GIT_SILENT Sync po/docbooks with svn 2023-10-15 02:11:25 +00:00
Tobias Fella
4b49559d39 Fix LocationHelper registration 2023-10-14 23:38:31 +02:00
Laurent Montel
baa33f1843 Remove unused import module 2023-10-14 20:27:18 +00:00
Tobias Fella
dae5718c6c Fix broken shortcut 2023-10-14 22:18:37 +02:00
Tobias Fella
60260cff3b Fix bugs in state delegates
- Don't show a dot over profile pictures.
  The dot was intended to be part of the Avatar when there is no image and the Avatar is too small to show an icon.
  Currently, it is visible over the profile picture. If we still want the dot, it should be upstreamed

- Fix avatar images in StateComponent
2023-10-14 19:33:44 +00:00
Laurent Montel
2df9a26cdc QTLOCATION_MODULE_QML_VERSION was used during qt5/qt6 support. Now version is not necessary in qt6 2023-10-14 20:42:19 +02:00
l10n daemon script
b16cd12b33 GIT_SILENT Sync po/docbooks with svn 2023-10-14 02:21:14 +00:00
Ingo Klöcker
6a3b22ef2d Remove the obsolete x-kde-os attribute for Windows screenshots 2023-10-13 14:06:47 +00:00
Tobias Fella
b28a85ff05 Fix AboutPage 2023-10-13 15:35:39 +02:00
James Graham
e480299563 Canonical Parent
So the original space parent and child stuff was technically a bit naughty in that it allowed multiple rooms to be set as the canonical parent. Because while a room can have multiple parents only one should be canonical. This adds the following:
- When adding a child or parent there is an extra check to select if the new parent should be canonical
- Any parent can be selected as the canonical one from the room settings
- All functions ensure that there is only ever one canonical parent by ensuring all others are false when a new one is set.
2023-10-13 12:00:47 +00:00
Tobias Fella
fe70e2773f Fix logging category filtering 2023-10-13 13:42:15 +02:00
l10n daemon script
e78ea4721a GIT_SILENT Sync po/docbooks with svn 2023-10-13 02:14:45 +00:00
l10n daemon script
1699dcf0c4 GIT_SILENT Sync po/docbooks with svn 2023-10-12 02:15:09 +00:00
Rohan Kumar
9d6aef6c2b Flatpak: allow talking to org.freedesktop.secrets
Previously, kwalletd5 was hard-coded. This should allow secret service
access for users with other secret service providers.
2023-10-11 09:31:30 -07:00
James Graham
a9c2428498 Manual Explore Rooms
This is an update to searching the public room list. Currently if you can't find the room you're looking for you can type a full alias of room ID into the search bar and a view/join button appears. This is hard to discover and technically broken since it was turned into a generic component for finding rooms (it kinda works but doesn't fit now as it's focussed on the joining rooms not adding new ones to spaces). It is also not very discoverable if you don't know it's there.

This patch patch updates the workflow to be truly generic and hopefully more discoverable. Instead of using the search bar if no results are found a button asking if someone wants to manually enter a room ID or alias appears. This launches a dialog where the user can type in an alias or ID and it has some basic checking to make sure the string looks as expected.

The new functionality also generically works for joining rooms and adding children to spaces.
2023-10-11 15:53:21 +00:00
l10n daemon script
0730f15e2b GIT_SILENT Sync po/docbooks with svn 2023-10-11 02:48:51 +00:00
l10n daemon script
136856f3c3 GIT_SILENT Sync po/docbooks with svn 2023-10-10 02:20:01 +00:00
l10n daemon script
763b6af076 GIT_SILENT Sync po/docbooks with svn 2023-10-09 02:21:59 +00:00
Tobias Fella
ac231320a3 Fix closing the login dialog 2023-10-08 10:01:01 +00:00
Tobias Fella
87aee162f1 Fix logout from accounts page 2023-10-08 09:52:47 +00:00
Tobias Fella
0899db31af Fix showing logout confirmation dialog 2023-10-08 09:48:27 +00:00
l10n daemon script
b4198bc13b GIT_SILENT Sync po/docbooks with svn 2023-10-08 02:10:30 +00:00
Tobias Fella
c6bfe73d26 Don't show "No Topic" 2023-10-07 16:43:07 +00:00
Tobias Fella
d490dffa36 Fix opening encryption confirmation dialog 2023-10-07 16:26:43 +00:00
Heiko Becker
43b2b71b73 GIT_SILENT Update Appstream for new release
(cherry picked from commit ffbd92317e)
2023-10-07 18:01:42 +02:00
l10n daemon script
39a51d1f35 GIT_SILENT Sync po/docbooks with svn 2023-10-06 02:14:03 +00:00
Carl Schwan
2eb26ffbb3 Fix typo 2023-10-05 11:13:09 +02:00
Carl Schwan
87ef55215f Allow reporting others
Instead of only being able to report yourself

BUG: 475227
2023-10-05 11:02:39 +02:00
Carl Schwan
f6186aad2e Fix right clicking on chat list delegate
BUG: 475226
2023-10-05 10:59:37 +02:00
Carl Schwan
2251edbf86 Fix invalid attempt to destroy() an indestructible object 2023-10-05 10:58:00 +02:00
l10n daemon script
1c55649740 GIT_SILENT Sync po/docbooks with svn 2023-10-05 02:11:56 +00:00
l10n daemon script
aa0b6613de GIT_SILENT Sync po/docbooks with svn 2023-10-04 02:11:42 +00:00
Yuri Chornoivan
f948e813b6 Fix minor typo 2023-10-03 08:36:04 +03:00
l10n daemon script
b5c6411aad GIT_SILENT Sync po/docbooks with svn 2023-10-03 02:13:22 +00:00
James Graham
b1daa76d9f Fix image reply sizing
Use height rather than implicitHeight for the loader so that replies with images always size properly
2023-10-02 18:55:54 +00:00
James Graham
7180fa022b Room Settings Parents
Add the ability to manage parent rooms from a child, this includes:
- viewing parents
- adding a new parent
- removing an existing one

Follows the rules from the matrix spec https://spec.matrix.org/v1.7/client-server-api/#mspaceparent-relationships
2023-10-02 18:41:17 +00:00
Ingo Klöcker
17bc08270d Tag Windows screenshots with new environment attribute
appstream now officially supports an environment attribute for screenshots.
2023-10-02 19:43:56 +02:00
Tobias Fella
d4cb27eca4 Make singletons owned by the C++ side 2023-10-02 16:29:04 +00:00
Fushan Wen
541350e678 appiumtests: port away from deprecated desired_capabilities
AppiumOptions replaces it
2023-10-02 15:48:58 +00:00
l10n daemon script
843deefaf8 GIT_SILENT Sync po/docbooks with svn 2023-10-02 02:16:12 +00:00
James Graham
070d579bc2 Restore the show author functionality to bubble 2023-10-01 14:05:42 +00:00
l10n daemon script
add283c9fb GIT_SILENT Sync po/docbooks with svn 2023-10-01 02:30:40 +00:00
James Graham
fe4230b5fd Use variable placeholder instead of string concatenation 2023-09-30 10:54:07 +01:00
l10n daemon script
e8f40d98de GIT_SILENT Sync po/docbooks with svn 2023-09-30 02:13:47 +00:00
James Graham
eba62103a4 Remove Space Child
Add button to remove a child in a space if the user has the correct power levels
2023-09-29 20:15:17 +00:00
Tobias Fella
925393deab Add type registration for KeyVerificationSession 2023-09-29 19:26:41 +00:00
Laurent Montel
abe881caf7 Add missing include moc 2023-09-29 13:45:46 +02:00
Yuri Chornoivan
237a3c9dfb Fix minor typo 2023-09-29 09:08:37 +03:00
l10n daemon script
9715440854 GIT_SILENT Sync po/docbooks with svn 2023-09-29 02:10:20 +00:00
James Graham
ecdad9f965 Space Home Page
Add a space homepage with the ability to both create new room and add existing rooms to the space. This uses a tree model for the space hierarchy and will go to any number of levels. The user should only see the add options if they have appropriate permissions.

This MR also combines the create space and room pages and adds a lot of optional functionality for managing space children.

![image](/uploads/1764b0319241ff870dc39b18b39f5d51/image.png)
2023-09-28 17:36:23 +00:00
Carl Schwan
08711fc927 Fix missing renaming in roomlastmessageprovider 2023-09-28 10:38:31 +02:00
Carl Schwan
e44cd405b7 Fix import name 2023-09-28 10:31:14 +02:00
Carl Schwan
8945e004e2 Optimize room config 2023-09-28 07:37:22 +00:00
Janet Blackquill
c04d8d6f59 Redraw tray icon
It seems at some point in time the 16x16 tray icon got lost/hastily upscaled to a 22x22 tray icon,
which resulted in proportions as well as icon guidelines being slightly off.

This replaces the tray icon with a new one redrawn to adhere to icon guidelines and proportions closer
to the colour icon.
2023-09-27 23:43:55 -04:00
l10n daemon script
58a73c0208 GIT_SILENT Sync po/docbooks with svn 2023-09-28 02:11:52 +00:00
Joshua Goins
852110debd Make it clear that the session is broken when the keys are lost
If you use your private keys (like when deleting the quotient database)
your session is broken as you have differing keys on the server. While
it is possible to work your way out of it, it's better to warn users to
bite the bullet and log in again.
2023-09-27 15:13:06 -04:00
Joshua Goins
6b71d3c78d Make the key verification message horizontally centered 2023-09-27 15:13:00 -04:00
Christophe Marin
f3a0adee39 Fix manpage installation 2023-09-27 16:23:29 +02:00
l10n daemon script
6e7b6c9ce0 GIT_SILENT Sync po/docbooks with svn 2023-09-27 02:12:21 +00:00
James Graham
f67cd7deb5 Remove the now unused author ID role from MessageEventModel
Remove the now unused author ID role from `MessageEventModel`. This can be obtained from the author roles object.
2023-09-26 20:21:08 +00:00
l10n daemon script
931b4b1f9a GIT_SILENT Sync po/docbooks with svn 2023-09-26 02:22:24 +00:00
l10n daemon script
167ed4eca3 GIT_SILENT made messages (after extraction) 2023-09-26 01:46:11 +00:00
l10n daemon script
7d5b2c1b6a GIT_SILENT Sync po/docbooks with svn 2023-09-25 02:15:50 +00:00
l10n daemon script
be7b1e49b4 GIT_SILENT Sync po/docbooks with svn 2023-09-24 02:09:06 +00:00
Tobias Fella
957419070a Remove unused includes 2023-09-23 22:43:48 +02:00
Carl Schwan
f22107c8ab Colorful emoji in reaction
Use ICU to determine if the string contains only emojis
2023-09-23 22:16:11 +02:00
Tobias Fella
3a4f71de7f Port to declarative type registration 2023-09-23 14:05:50 +00:00
Tobias Fella
4ed4f3f628 Silence invalid user id warnings 2023-09-23 11:42:21 +02:00
Tobias Fella
ba24f1272f Fix crash in completion 2023-09-23 09:23:25 +00:00
Carl Schwan
443661d113 Port away from BasicListItem 2023-09-23 09:07:05 +00:00
Tobias Fella
091c8806db Fix opening account editor 2023-09-23 10:19:44 +02:00
l10n daemon script
041c719a2e GIT_SILENT Sync po/docbooks with svn 2023-09-23 02:10:02 +00:00
James Graham
83a9bfa974 Remove timeline container as it has been replaced. 2023-09-22 23:50:29 +00:00
James Graham
e35a6f7257 Remove the import version from Bubble.qml, TimelineDelegate.qml and TextDelegate.qml 2023-09-22 18:46:17 +01:00
James Graham
6d56251f6f Fix the timeline Part 2: Bubble Rework
This reworks the bubble as a separate component and makes some fixes to prevent the console being spammed with polish loop warnings.
2023-09-22 17:12:56 +00:00
l10n daemon script
486fae9c10 GIT_SILENT Sync po/docbooks with svn 2023-09-22 02:10:59 +00:00
Tobias Fella
1c26d9b811 Remove QML import versions 2023-09-21 19:38:10 +02:00
Tobias Fella
6d7ae99c94 Don't crash when editing pending message 2023-09-21 16:48:09 +00:00
Carl Schwan
442a343097 Rework context menu RoomList
- Finish port to qt6 and replace icon by icon.name
- Use RoundedItemDelegate
2023-09-21 16:43:27 +00:00
Tobias Fella
f0a7216b4b Don't crash when trying to leave empty room
BUG: 474490
2023-09-21 16:38:49 +00:00
James Graham
e926b22524 Fix the Timeline Part 1
This introduces a new base delegate that handles sizing the content of delegate in the timeline, i.e. it handles all the size helper stuff. This is then used for all the other main delegates:
- messages
- state
- read marker

This means they now all have identical base code to do the sizing (read marker still had legacy code).

Because the new base delegate is called `TimelineDelegate` both `TimelineContainer` and `MessageDelegate` have been renamed:
- MessageDelegate -> TextDelegate - this never made sense before images, videos, etc are all technically messages in Matrix parlance
- TimelineContainer -> MessageDelegate - this has always really been the base for messages

Note - this is mostly groundwork for dealing with the layout polish loop spam which will hopefully be fixed in part 2 with a bubble rework.
2023-09-21 16:26:34 +00:00
Carl Schwan
69087c2117 Add top spacing for Room ListView 2023-09-21 15:07:55 +00:00
Carl Schwan
4d2104b54b Decrease top margin in SpaceDrawer
Make it the same as the left margin of the delegate for an increased
consistency.
2023-09-21 15:07:55 +00:00
l10n daemon script
3f85a359e1 GIT_SILENT Sync po/docbooks with svn 2023-09-21 02:18:35 +00:00
ivan tkachenko
3084913940 Opt-out of Kirigami.SpellCheck when a custom QTextDocument handler is used
Uses Kirigami.SpellCheck's new shorter name.

See https://invent.kde.org/frameworks/kirigami/-/merge_requests/1261
2023-09-21 02:53:32 +03:00
Joshua Goins
e2670cd6ba Use Qt::ArrowType in FormCard.FormArrow usage on AccountsPage 2023-09-20 14:59:11 -04:00
l10n daemon script
1b6fc3dde5 GIT_SILENT Sync po/docbooks with svn 2023-09-20 02:15:06 +00:00
l10n daemon script
69a19effa2 GIT_SILENT Sync po/docbooks with svn 2023-09-19 02:17:37 +00:00
l10n daemon script
4abdf1f920 GIT_SILENT Sync po/docbooks with svn 2023-09-18 02:21:13 +00:00
l10n daemon script
0b1a6a3f6b GIT_SILENT made messages (after extraction) 2023-09-18 01:59:17 +00:00
l10n daemon script
45544c79bb GIT_SILENT Sync po/docbooks with svn 2023-09-17 02:54:29 +00:00
l10n daemon script
c4dddf6e02 GIT_SILENT Sync po/docbooks with svn 2023-09-16 02:18:05 +00:00
Tobias Fella
7f3f628b7d Fix missing connection 2023-09-15 17:41:08 +00:00
James Graham
6bf552398e Fix getting connection in message edit component 2023-09-15 18:35:23 +01:00
James Graham
78f676d71a Fix the room list menu
As title
2023-09-15 16:22:59 +00:00
James Graham
33c0cae64c Message menu rework
Rework the file menu so that it no longer relies on having a reference to the media delegate to manage a download for either opening externally or copying to clipboard. This allows the menus to be moved out of the delegates and maximize components and have them accessed through RoomManager. This reduces duplication and reduces the number of components in an already heavy delegate.
2023-09-15 13:57:40 +00:00
James Graham
14cdd096cf Fix Delegate Menu in NeochatMaximizeComponent
Make sure NeochatMaximizeComponent provides all the required properties to the delegate menu
2023-09-15 11:00:40 +00:00
James Graham
c04ddfde26 EventSource Refactor
Move showing th event source to a call to RoomManager. This means the SourceRole is no longer required in the message and search models
2023-09-15 10:54:04 +00:00
l10n daemon script
ec4c156a8c GIT_SILENT Sync po/docbooks with svn 2023-09-15 02:14:09 +00:00
Tobias Fella
17ff5b4c56 Add button to reject invitation and ignore user
BUG: 474274
2023-09-14 15:34:19 +00:00
Tobias Fella
0e2275e415 Always require passing tests 2023-09-14 10:23:52 +00:00
l10n daemon script
12fd1875b5 GIT_SILENT Sync po/docbooks with svn 2023-09-14 02:13:41 +00:00
l10n daemon script
10e50804c7 GIT_SILENT made messages (after extraction) 2023-09-14 01:54:51 +00:00
James Graham
c01c638a49 Fix file menu
Pass file menu eventSource rather than source and htmlText
2023-09-13 18:46:41 +00:00
Tobias Fella
399151eb1d Fix opening context menus 2023-09-13 15:48:39 +02:00
Tobias Fella
5e80715898 Cleanup connection handling in QML
Consistently pass connection objects to files that need them instead of randomly using Controller.activeConnection in some of them
2023-09-13 13:12:01 +00:00
Tobias Fella
6439fa48f9 Adapt to QML api changes 2023-09-13 12:57:27 +00:00
Tobias Fella
823f3cdd4e Remove QML Qt5/Qt6 compatibility hacks 2023-09-13 12:57:27 +00:00
Tobias Fella
f542d0b9fd Change rowStride in runner to qsizetype 2023-09-13 14:53:07 +02:00
Tobias Fella
a43990559b Rename source property of MessageDelegateContextMenu
Starting with Qt6.6, this collides with a FINAL property of Loader and thus doesn't run
2023-09-13 14:16:48 +02:00
Tobias Fella
feb2dbc9fb Don't try finding KStatusNotifierItem on android 2023-09-13 12:05:40 +00:00
Tobias Fella
f299d5a245 Fix KF6 crash in emoji completion 2023-09-13 13:41:08 +02:00
Tobias Fella
d69b8fbf8c Fix compilation on FreeBSD 2023-09-13 13:27:33 +02:00
Tobias Fella
234e5c49c4 Re-enable FreeBSD CI
Was accidentally disabled during a merge
2023-09-13 13:23:45 +02:00
Tobias Fella
cee72b6d48 Remove Qt5 compatibility ifdefs 2023-09-13 11:16:02 +00:00
Tobias Fella
539fdcaf2e Remove compatibility with Qt5 in CMake 2023-09-13 11:09:41 +00:00
Joshua Goins
32b3861c3e Only show the "View Source" message action when dev tools are enabled
This is a very developer-oriented action, and other uses of this dialog
(such as interacting with room state events under a room debug page) is
also locked behind this option.
2023-09-13 07:12:18 +00:00
l10n daemon script
f1076a5ced GIT_SILENT Sync po/docbooks with svn 2023-09-13 02:24:16 +00:00
Joshua Goins
bf8f5705d0 Fix message event source dialog not showing any data 2023-09-12 17:10:23 -04:00
Tobias Fella
2656a93ee7 Disable Qt5 CI 2023-09-12 15:39:25 +00:00
l10n daemon script
cbab810a2e GIT_SILENT Sync po/docbooks with svn 2023-09-12 01:47:54 +00:00
Tobias Fella
e78dfaec34 Use view background color for SpaceDrawer 2023-09-11 20:20:49 +00:00
ivan tkachenko
3cfa773820 Settings: Port to AvatarButton and fix OpenFileDialog lifespan
The dialog won't show again after being closed first time, so we need
to dynamically destroy it on both accept and reject. It helps clear out
any state on its way.
2023-09-11 22:47:33 +03:00
Tobias Fella
94c0e8b6cd Port ChatBar actions to Button
Cleans up the code and improves accessibility
2023-09-11 19:23:13 +00:00
Tobias Fella
35b1f24cb7 Fix roomlist when switching accounts
Fixes #605
2023-09-11 19:03:30 +00:00
Tobias Fella
de3072125e Change all remaining QML file ids to "root" 2023-09-11 20:47:32 +02:00
Tobias Fella
f7d2ffac66 Move Controller::createRoom and Controller::createSpace to NeoChatConnection 2023-09-11 17:55:52 +00:00
James Graham
ff0990bb7c Emit Room Selected from JoinRoomPage
Change the `JoinRoomPage` so that it emits a `roomSelected` signal with the selected delegate's info instead of calling the functions to join or enter the room itself. This is so that the `JoinRoomPage` can be used for other purposes like selecting an existing child to add to a space.
2023-09-11 17:16:12 +00:00
James Graham
8285961c42 Restore compact mode background
Restore compact mode using the darker/lighter depending on color scheme background (i.e. the same as the bubble background) it broke somewhere in the refactor of roompage
2023-09-11 07:19:32 +00:00
James Graham
cd39d5b129 Shutup LinkPreviewDelegate
Make sure that the console isn't spammed having `linkpreviewer` undefined in `LinkPreviewDelegate`, even though it shouldn't ever be and I couldn't find any case where it was but my console was still intermittently getting spammed.
2023-09-11 06:27:13 +00:00
l10n daemon script
83b3fefbf5 GIT_SILENT Sync po/docbooks with svn 2023-09-11 01:48:45 +00:00
l10n daemon script
3718bd716a GIT_SILENT made messages (after extraction) 2023-09-11 00:46:51 +00:00
Akseli Lahtinen
a18257ee17 Taskbar badge highlight counter
Instead of the taskbar badge showing count for all notifications, only show the count for total highlights.
2023-09-10 20:57:39 +00:00
Laurent Montel
def46d90a8 Fix qml signal argument warning 2023-09-10 20:19:32 +02:00
ivan tkachenko
8afd7b2892 Give "+" tool button a proper a11y role and an RTL-friendly modal menu 2023-09-10 20:40:23 +03:00
ivan tkachenko
deb11367cb ChatBox: Fix jittery ChatBar
ChatBar animated its implicit height, and there is no way for us to
force it animating on integer values only. It is contained in a Layout
type, and QtQuick.Layouts are known to round up size of their items and
position them on an integer scale. All in all, is caused bottom of chat
bar (action icons row and the whole bottom edge) to flicker during
height animation.
2023-09-10 20:40:23 +03:00
ivan tkachenko
ffd1b06a82 RoomSettings: Port disabled text fields to readOnly
Improves visuals, and allows to select & copy text. Also hides Save
button when there's no chance it would get enabled.

Depends on very recently merged MR in kirigami-addons:
https://invent.kde.org/libraries/kirigami-addons/-/merge_requests/153
2023-09-10 20:40:22 +03:00
ivan tkachenko
2597f0aec9 RoomSettings: Make room avatar bigger
This is literally the page about the room, we are not short on space
here. Make it shine.
2023-09-10 20:40:22 +03:00
James Graham
33ca72efd9 Fix ImageDelegate
Restore the animated mediaInfo to eventHandler and make sure ImageDelegate uses the media helper size for the sourceSize.
2023-09-10 16:22:14 +00:00
ivan tkachenko
2fbf659eb4 RoomInformation: Fix sizing of ListView header
Header is parented to ListView's contentItem (flickable) which is
subject to padding due to vertical scrollbar.
2023-09-10 17:07:20 +03:00
Antonio Rojas
763198b2c3 Add cmake check for qtlocation QML module
So that packagers are notified that it is a dependency
2023-09-10 10:12:52 +00:00
q234 rty
50551541ed Use shortcode as a fallback for body when sending stickers 2023-09-10 09:41:46 +00:00
James Graham
323cd4962e Explore rooms page RoundedItemDelegate
Move the explore rooms page to using the new RoundedItemDelegate
2023-09-10 09:00:57 +00:00
l10n daemon script
b2f592afeb GIT_SILENT Sync po/docbooks with svn 2023-09-10 01:45:20 +00:00
Tobias Fella
f7f98c43e2 Fix fix for crash in push rules 2023-09-09 12:13:33 +00:00
l10n daemon script
06134f96eb GIT_SILENT Sync po/docbooks with svn 2023-09-09 01:46:10 +00:00
Laurent Montel
bb62849a19 Use explicit qml signal argument in ShareAction 2023-09-08 07:44:31 +00:00
Laurent Montel
d05385caed Remove unused qml module 2023-09-08 08:28:03 +02:00
l10n daemon script
209ca747b5 GIT_SILENT Sync po/docbooks with svn 2023-09-08 01:46:47 +00:00
James Graham
2c6ab498ac Event Handler
Similar to text handler, pull out the disparate array of functions which format information from an event ready for display in the UI and put in a handler class with a test suite.

requires https://github.com/quotient-im/libQuotient/pull/686
2023-09-07 19:02:50 +00:00
Laurent Montel
597633f824 Add explicit signal argument 2023-09-07 13:42:45 +00:00
Laurent Montel
65da416b8e Disable add button when text is empty 2023-09-07 08:16:02 +00:00
l10n daemon script
c528929b30 GIT_SILENT Sync po/docbooks with svn 2023-09-07 01:46:10 +00:00
l10n daemon script
8650ce1755 GIT_SILENT Sync po/docbooks with svn 2023-09-06 01:44:38 +00:00
Tobias Fella
8936b23da9 Remove "Apply" Button in security settings
It doesn't do anything. All settings are instant-apply.
2023-09-05 12:58:57 +00:00
l10n daemon script
cf72fbea2e GIT_SILENT Sync po/docbooks with svn 2023-09-05 01:45:00 +00:00
Laurent Montel
0d5929b4bc Fix enable/disable save button when image.source is empty. Otherwise it will crash 2023-09-04 19:03:06 +00:00
Ingo Klöcker
d43cc9a044 Terminate the mock server after the test 2023-09-04 17:47:34 +02:00
Ingo Klöcker
682e3967ba Increase timeout per test to 90 seconds
The Appium test (including the setup) takes more than the default 60 s.
2023-09-04 17:14:02 +02:00
Ingo Klöcker
ceebee3a56 Look for "login-server.py" next to "logintest.py" 2023-09-04 16:46:20 +02:00
Ingo Klöcker
52ab052aef Choose the Login option before trying to enter the login credentials 2023-09-04 16:11:20 +02:00
Ingo Klöcker
e6a2b2d125 Disable outdated test for now 2023-09-04 16:01:58 +02:00
Ingo Klöcker
92dadc2cc9 Use sys.executable instead of a hardcoded executable name/path of Python 2023-09-04 16:01:34 +02:00
Tobias Fella
6ca9380a51 Enable linux Qt5 CI 2023-09-04 13:12:37 +00:00
Laurent Montel
51d41ab5bf Enable "add" button only if text is not empty
=> otherwise it will report error
2023-09-04 07:24:25 +02:00
l10n daemon script
f1047fa474 GIT_SILENT Sync po/docbooks with svn 2023-09-04 01:47:23 +00:00
Tobias Fella
011b11681f Remove button to toggle search in room member list 2023-09-03 16:15:36 +02:00
Tobias Fella
8baeb236bc Remove unused signals in Controller 2023-09-03 11:32:59 +00:00
Tobias Fella
b9d173d0b5 Remove Controller::accountCount in favor of AccountRegistry::accountCount 2023-09-03 11:23:39 +00:00
Tobias Fella
3790955c56 Port CreateRoomDialog to FormCard 2023-09-03 11:15:33 +00:00
James Graham
199772a013 Room Drawer Media Tab
Add a tab bar to the room drawer which includes a new media tab in addition to the room information tab. This mr completes the architecture for adding others easily later e.g. message highlights or threads.

To put this together I had to make sure things like the menus and the maximize delegate were available to both the room drawer and page so there is some rework there to put it all together.

Wide\
![image](/uploads/b7d3a3ee00016f9ede5cf6fb93e7b40c/image.png)

Mobile\
![image](/uploads/aa02e23f79b37f6cad903d3f356e0ef4/image.png)
2023-09-03 10:25:04 +00:00
l10n daemon script
54cc3ac761 GIT_SILENT Sync po/docbooks with svn 2023-09-03 02:08:34 +00:00
Tobias Fella
1675c14c92 Port GlobalNotificationsPage to FormCard 2023-09-02 17:12:46 +00:00
James Graham
56f5ef2611 MediaSizeHelper
Create a media size helper and use it to force video and images to be the correct size even in replies.
2023-09-02 16:43:05 +00:00
Tobias Fella
7ba63eb680 Port proxy page to formcard 2023-09-02 15:59:22 +00:00
Tobias Fella
ddd690f6d5 Port DevicesPage to FormCard 2023-09-02 15:59:07 +00:00
Tobias Fella
d9dc5f48bc Port appearance settings to formcard 2023-09-02 15:58:55 +00:00
Tobias Fella
a3b40a5e6d Port devtools to FormCard 2023-09-02 15:58:37 +00:00
Tobias Fella
be71a4349b Port accounts page to formcard 2023-09-02 15:50:05 +00:00
James Graham
ede2707767 New default pushrules
Add handling for new default push rules added in 1.7 also add a generic unknown handling for if any others are added in the future so they don't appear in keywords
2023-09-02 15:48:50 +00:00
Tobias Fella
5871903529 Port CreateSpaceDialog to FormCard 2023-09-02 15:46:25 +02:00
Tobias Fella
87745c360d Port EmoticonEditorPage to FormCard 2023-09-02 11:45:14 +00:00
Tobias Fella
40d2eb5aba Port general settings page to FormCard 2023-09-02 11:45:01 +00:00
Tobias Fella
cfd9f36a97 Port NotificationRuleItem to FormCard 2023-09-02 11:42:44 +00:00
Tobias Fella
48f7e06c01 Port remaining room settings to FormCard 2023-09-02 11:42:38 +00:00
Tobias Fella
43ecd188f1 Port SonnetConfigPage to FormCard 2023-09-02 11:33:03 +00:00
Tobias Fella
063056bebd Port EmoticonsPage to FormCard 2023-09-02 11:25:32 +00:00
Laurent Montel
dfba655527 Fix missing argument signal in qml 2023-09-02 11:13:51 +00:00
Laurent Montel
23178b6224 Remove unused import qml module (scripted) 2023-09-02 11:54:28 +02:00
Tobias Fella
a9a6e31b8c Use FormCard AboutKDE 2023-09-02 07:41:41 +00:00
l10n daemon script
0afd74d96a GIT_SILENT Sync po/docbooks with svn 2023-09-02 01:50:44 +00:00
Tobias Fella
c5501f2b5d Port ColorScheme to FormCard 2023-09-01 19:19:08 +00:00
Tobias Fella
68602fc177 Port ExploreComponent actions to pageStack.pushDialogLayer 2023-09-01 19:04:56 +00:00
Tobias Fella
8ce5a57499 Remove type registration for RoomMessageEvent 2023-09-01 18:54:58 +00:00
James Graham
bf3c5708c7 Remove support streaming
Remove support streaming from video delegate as it's breaking downloads and unused
2023-09-01 17:54:37 +00:00
Tobias Fella
8359c1fe90 Only set graphics API when using Qt6 2023-09-01 16:06:00 +00:00
Laurent Montel
774121ea8c Fix qml explicit signal argument 2023-09-01 17:11:35 +02:00
Tobias Fella
370bbf8a4b Set attributes for QtWebEngine 2023-09-01 11:34:33 +00:00
Tobias Fella
4fd36fb221 Fix crash for push rules without action
@nvrwhere how much sense does this fix make? i only know that it doesn't crash anymore
2023-09-01 11:33:29 +00:00
Laurent Montel
167349b9d2 Remove unused forward declaration 2023-09-01 11:51:36 +02:00
l10n daemon script
296aa9ddad GIT_SILENT Sync po/docbooks with svn 2023-09-01 01:45:50 +00:00
Tobias Fella
94c1b67ec9 Port account editor to formcard 2023-08-31 22:02:30 +00:00
Tobias Fella
a9965acdd3 Fix compilation warning in searchmodel 2023-08-31 21:52:23 +00:00
Tobias Fella
35313271a3 Cleanup registration.h 2023-08-31 21:36:56 +00:00
Tobias Fella
e40179f641 Don't load data from invalid indices in MessageFilterModel 2023-08-31 21:28:20 +00:00
Tobias Fella
dacf3ff8a0 Fix compilation warnings in registration.cpp 2023-08-31 21:21:22 +00:00
Tobias Fella
0274d70f71 Fix connection property initialization 2023-08-31 21:16:57 +00:00
Tobias Fella
0c19052f32 Port PushNotification settings page to FormCard 2023-08-31 20:40:59 +00:00
Laurent Montel
a3423e5724 Fix warning about missing argument qml signal 2023-08-31 10:02:32 +00:00
l10n daemon script
e09f31f891 GIT_SILENT Sync po/docbooks with svn 2023-08-31 01:46:27 +00:00
Tobias Fella
e05e0f5489 Improve QML types 2023-08-30 23:04:18 +00:00
Tobias Fella
002961f638 Move jobs to individual files 2023-08-30 21:10:56 +00:00
Laurent Montel
e28419ef88 Use isEmpty() here 2023-08-30 19:29:02 +02:00
Laurent Montel
0e4df58fc9 Add missing include moc file 2023-08-30 19:20:04 +02:00
Tobias Fella
21a55885b3 Only read role names from source model when there is a source model 2023-08-30 15:21:24 +00:00
l10n daemon script
6a8ac8f6e5 GIT_SILENT Sync po/docbooks with svn 2023-08-30 01:46:13 +00:00
Tobias Fella
9fcfad7058 Fix supportStreaming in VideoDelegate 2023-08-29 20:48:02 +00:00
Tobias Fella
cfcc1756dd Implement deactivating accounts 2023-08-29 22:38:32 +02:00
Tobias Fella
e15bec2295 Introduce NeoChatConnection
Previously, some functions that conceptually belong to the connection needed to be in the Controller, since we didn't have a place to put them.
This fixes that by extending the Connection class in a similar way as we extend the Room class.
2023-08-29 20:14:44 +00:00
James Graham
9071cf827f Make sure that the event after a state event is also a state event before filtering it out. 2023-08-29 17:41:20 +01:00
Yuri Chornoivan
c7deaaba84 Fix minor typo 2023-08-29 09:52:45 +03:00
l10n daemon script
414035de8b GIT_SILENT Sync po/docbooks with svn 2023-08-29 01:44:33 +00:00
James Graham
442612d31d Merge the functionality of CollapseStateProxyModel into MessageFilterModel
Merge the functionality of CollapseStateProxyModel into MessageFilterModel there is no need for a whole separate model the filters can be combined trivialy.
2023-08-28 10:31:18 +00:00
Tobias Fella
59164d3bb2 Implement account registration
Implements #7
2023-08-28 10:05:09 +00:00
Tobias Fella
cc60dde62d Deselect space when leaving it
BUG: 473271
2023-08-28 11:47:39 +02:00
l10n daemon script
cbed8148a3 GIT_SILENT Sync po/docbooks with svn 2023-08-28 02:09:20 +00:00
James Graham
50e8b9ebf6 Visit User
Move to using visit user in all cases.
2023-08-27 19:05:55 +00:00
Nicolas Fella
f5ad2ad162 Fix enter key naviation in login flow 2023-08-27 19:32:41 +02:00
Tobias Fella
d11d6c74b3 Fix opening settings
BUG: 473789
2023-08-27 17:17:12 +00:00
James Graham
63ed69a5d4 Use updated AlbumMaximizeDelegate
Autoload is being removed so don't use it.

Requires libraries/kirigami-addons!146
2023-08-27 16:02:07 +00:00
Tobias Fella
a8aa775575 Implement message forwarding
Implements #338
2023-08-27 09:55:31 +00:00
Tobias Fella
6305359b3c Use round instead of ceil in delegatesizehelper
Fixes #592
2023-08-27 09:54:57 +00:00
Tobias Fella
7e859364af Don't show "no canonical alias" message in GroupChatDrawerHeader
The word "canonical" is confusing to average people and there isn't really a point in showing the message.
2023-08-27 09:54:41 +00:00
Tobias Fella
8abd0db012 Remove redundant NeoChatRoom::htmlSafeDisplayName 2023-08-27 09:54:28 +00:00
Tobias Fella
dbc10685f0 Port login to FormCard 2023-08-27 09:54:12 +00:00
l10n daemon script
96582a12bc GIT_SILENT Sync po/docbooks with svn 2023-08-27 01:50:22 +00:00
l10n daemon script
0ac61854bd GIT_SILENT made messages (after extraction) 2023-08-27 00:46:25 +00:00
Tobias Fella
68298f038d Fix opening report sheet 2023-08-26 19:54:45 +00:00
Tobias Fella
405fd5841a Fix opening ban sheet 2023-08-26 19:54:17 +00:00
Tobias Fella
5da9bba844 Force plain text user display name in user detail sheet 2023-08-26 19:54:06 +00:00
Tobias Fella
84373712ef Fix opening about page 2023-08-26 21:51:40 +02:00
James Graham
50f4f96341 Fix maximize component menu
Should be plainText not plainMessage
2023-08-26 19:29:11 +00:00
Tobias Fella
1b27b1a4e2 Make sure we don't load link previews when they're not enabled
Fixes #591
2023-08-26 19:28:29 +00:00
Tobias Fella
33811a4c49 Remove unused kitemmodels import 2023-08-26 21:25:09 +02:00
James Graham
43715486e5 Room Drawer Mobile
Push the room drawer as a page rather than a drawer when on mobile or the window is thin.

This also lays some foundations for having multiple different pages in the drawer by separating the room information into it's own component which could be switched out to show other things like highlights or media.
2023-08-26 08:42:39 +00:00
l10n daemon script
5c72bd4ab7 GIT_SILENT Sync po/docbooks with svn 2023-08-26 01:47:31 +00:00
James Graham
092f1be99b Further mark messages read fixes
Add a timer to lockout the scroll trigger for marking messages as read in the first second after changing room. This is because the scrollview can't differentiate between mouse scrolling and the multiple changes in scrollview that happen as the room is changed over.
2023-08-25 22:27:20 +00:00
Carl Schwan
550d55cb1a Add release note for last two version 2023-08-25 14:25:34 +02:00
l10n daemon script
e9edb61245 GIT_SILENT Sync po/docbooks with svn 2023-08-25 01:47:19 +00:00
Tobias Fella
89aae665b1 Fix reaction string 2023-08-24 17:38:17 +00:00
Carl Schwan
1e3c3dd1f4 Remove debuging value
Otherwise like of connectivity never disapear
2023-08-24 16:10:01 +02:00
Ingo Klöcker
6f4d2c0216 Add Windows-specific screenshots as screenshots with custom attribute
Instead of using translated custom values (which are not accepted by
AppStream validation) this adds the Windows-specific screenshots as
normal screenshots with custom attribute x-kde-os="windows". AppStream
validation accepts custom attributes (in fact, it ignores any attributes
other than "type").

Upstream appstream tooling will treat those screenshots as any other
extra screenshots (screenshots without type="default").
2023-08-23 15:31:47 +02:00
l10n daemon script
803cd2b4e4 GIT_SILENT Sync po/docbooks with svn 2023-08-23 01:47:24 +00:00
Carl Schwan
9f3012061d ReactionDelegate: Don't bind twice the reaction repeater model
We already are using an alias for this
2023-08-22 21:49:30 +00:00
Tobias Leupold
c1604a9c4f Trayicon tweaks
This fixes two minor inconveniences:

- When closing the chat window and re-showing it from the systray icon, the geometry was not properly restored. The window was always shown in the middle of the screen. Now, one gets the window back with it's actual last position and size.
- It is now possible to not only show the window from the systray icon, but also to close it. This is the way other chat programs do it (Kopete back in the day, Konversation, Quassel IRC etc.)
2023-08-22 20:58:04 +00:00
l10n daemon script
3c7fcee244 GIT_SILENT Sync po/docbooks with svn 2023-08-22 01:47:22 +00:00
Tobias Fella
d33a50a00d Fix json for replies 2023-08-21 19:10:15 +02:00
Tobias Fella
ed033a1c5e Raise compiler settings level to 5.105 2023-08-21 13:02:14 +02:00
l10n daemon script
2b961703ae GIT_SILENT Sync po/docbooks with svn 2023-08-21 01:46:37 +00:00
l10n daemon script
0539665779 GIT_SILENT made messages (after extraction) 2023-08-21 00:46:26 +00:00
James Graham
df127b88e6 Fix Image Replies
Make sure that the image container has it's implicit width/height set so that the correct size can always be calculated. This was breaking images that were a reply to another message (not sure if that's legal because we don't allow but other clients do because I found one).
2023-08-20 18:16:51 +00:00
Joshua Goins
27c4b57f0f Fix link to 'made for matrix' bade 2023-08-20 11:30:05 -04:00
Joshua Goins
f875a23e83 Only close the settings window if there's no accounts left 2023-08-20 15:08:57 +00:00
Joshua Goins
7f5cfbf21c Move the sign out button outside the editor, and close the dialog 2023-08-20 15:08:57 +00:00
Joshua Goins
f7c7643c1c Emit the accepted signal in the logout confirmation dialog 2023-08-20 15:08:57 +00:00
Joshua Goins
692edf52f1 Allow customizing the connection for the logout confirm dialog 2023-08-20 15:08:57 +00:00
Joshua Goins
e48cfaa41f Check if the room is valid before trying to refresh users 2023-08-20 15:08:57 +00:00
Joshua Goins
ba116460d5 Check if there's an active connection before updating notification rules 2023-08-20 15:08:57 +00:00
Joshua Goins
c71672dab3 Remove used logout dialog in main.qml 2023-08-20 15:08:57 +00:00
l10n daemon script
932ef72311 GIT_SILENT Sync po/docbooks with svn 2023-08-20 01:46:49 +00:00
l10n daemon script
7e53a2234f GIT_SILENT made messages (after extraction) 2023-08-20 00:46:36 +00:00
Joshua Goins
a0499e5140 Set sourceSize in for images, improving memory usage and smoothing
In some cases (where we don't get a thumbnail) we load the entire image,
which might be large. Even when we get a thumbnail, the smoothing we
apply doesn't get the best results and the only other option is
mipmapping which is more memory intensive - it stores progressively
smaller images but keeps all of them in memory.

Now the ImageDelegate sets the sourceSize, which helps reduce the memory
footprint (since Qt will throw away whatever parts of the image we don't
need) and makes the images look smoother when scaled. However,
AnimatedImages do not support this so this change introduces a new
property to tell if the image could possibly be animated. It will
erroneously pick up formats that could support animation (e.g. WebP) but
other image formats will still benefit so it's a net positive. The
ImageDelegate will load the correct image component depending on this
property.
2023-08-19 18:20:49 +00:00
Joshua Goins
093ef0a18c Use mxc urls for completion room avatars 2023-08-19 11:49:03 -04:00
Joshua Goins
36bf862ab9 Change the completion proxy model to filter out invalid entries
When auto-completing rooms, there may be some that do not have
canonical addresses (e.g. 1-to-1 chats). These can't be linked anyway,
so skip them and any other unlinkable entries.
2023-08-19 15:45:51 +00:00
Joshua Goins
6d8c1d0780 Fix avatar URLs for rooms
Room avatar URLs don't specify the new mxc:// format the user avatars
use, so we need to carve out a workaround for them.
2023-08-19 15:45:51 +00:00
Joshua Goins
7fe85066a4 Move attachment dialog to ChatBar, where it can actually be used
ChatBar calls to an attachDialog that never comes, so let's have them
move in together.
2023-08-19 15:23:04 +00:00
Tobias Fella
1fefa228e6 Don't check isJobPending in explore page 2023-08-19 14:08:45 +00:00
Joshua Goins
4104e10d95 Add another message when no rooms are found 2023-08-19 14:08:45 +00:00
Joshua Goins
05f3c3ee0a Make the explore page header way prettier, like it is in KCMs 2023-08-19 14:08:45 +00:00
Joshua Goins
0a1c489401 Make the explore page search loading process more obvious
Adds progress bars, lots of them! Now it's easier to tell if NeoChat is
trying it's best to load the public room list.
2023-08-19 14:08:45 +00:00
l10n daemon script
e53d63ad8b GIT_SILENT Sync po/docbooks with svn 2023-08-18 01:44:42 +00:00
l10n daemon script
78541b32f0 GIT_SILENT Sync po/docbooks with svn 2023-08-17 01:46:48 +00:00
Carl Schwan
3bd93996c0 Don't inherit color in TimelineContainer 2023-08-16 23:44:22 +02:00
Heiko Becker
61968aa475 GIT_SILENT Update Appstream for new release
(cherry picked from commit 91b5573016)
2023-08-16 23:33:49 +02:00
Joshua Goins
24d0082048 Use view-list-details instead of expand icon in room drawer 2023-08-16 20:07:46 +00:00
Joshua Goins
2980af11b0 Destroy the correct component in space list context menu 2023-08-16 20:07:46 +00:00
Joshua Goins
91d9406c38 Prevent the TapHandler in AvatarTabButton from triggering clicked()
This caused right-clicks on this component (for example, in the space
drawer) to cause clicked() to be called on the delegate.
2023-08-16 20:07:46 +00:00
Joshua Goins
280d1e38e2 Add icons to the space list context menu items 2023-08-16 20:07:46 +00:00
Joshua Goins
7b520da4b4 Prevent the chat bar from pasting a local file URL if we save the bitmap
There's no point in also putting the file:// URL, so catch the event if
saving the bitmap from the clipboard is successful.
2023-08-16 19:57:22 +00:00
Joshua Goins
419b4cea98 Ensure that the notification avatar is drawn with no pen 2023-08-16 19:46:59 +00:00
Joshua Goins
38824f30ac Further notification avatar improvements
The correct render hint is actually SmoothPixmapTransform, as
Antialiasing only matters for primitives. Also, render a white
background for potentially transparent avatars.
2023-08-16 19:46:59 +00:00
Joshua Goins
9c4d8ef823 Fix the account switcher width so it doesn't spill off the side 2023-08-16 19:39:14 +00:00
Joshua Goins
fe3bf3a638 Pick a better shadow and clean up emoji popup backgrounds
These shadows are now closer to how other popups look.
2023-08-16 19:31:07 +00:00
Joshua Goins
d678a446e2 Don't clip the emoji popups as they destroy shadows 2023-08-16 19:31:07 +00:00
Nicolas Fella
6df60a39b0 Port to KStatusNotifierItem framework 2023-08-16 11:43:56 +00:00
l10n daemon script
6f9fa76ab7 GIT_SILENT Sync po/docbooks with svn 2023-08-16 01:47:00 +00:00
Carl Schwan
6e8b0f001f Add network cache 2023-08-15 15:33:46 +00:00
l10n daemon script
0bfad95d8b GIT_SILENT Sync po/docbooks with svn 2023-08-15 01:48:13 +00:00
Tobias Fella
1b43846196 Remove obsolete quotientMinorVersion property 2023-08-14 18:05:14 +00:00
Tobias Fella
4ea183b139 Improve tooltips in chatbar 2023-08-14 07:54:47 +00:00
Tobias Fella
22fd24549b Wrap room display name in Room Drawer 2023-08-13 20:02:58 +02:00
l10n daemon script
af793fb865 GIT_SILENT Sync po/docbooks with svn 2023-08-13 01:45:51 +00:00
l10n daemon script
13414b5834 GIT_SILENT made messages (after extraction) 2023-08-13 00:46:24 +00:00
l10n daemon script
65a1df4a75 GIT_SILENT Sync po/docbooks with svn 2023-08-12 01:49:08 +00:00
l10n daemon script
d15157703a GIT_SILENT made messages (after extraction) 2023-08-12 00:46:19 +00:00
l10n daemon script
2d21330a36 GIT_SILENT Sync po/docbooks with svn 2023-08-11 01:45:25 +00:00
l10n daemon script
fbc4611d02 GIT_SILENT Sync po/docbooks with svn 2023-08-10 01:47:01 +00:00
l10n daemon script
e257865b19 GIT_SILENT made messages (after extraction) 2023-08-10 00:46:30 +00:00
James Graham
018154f555 No emoji chatbar button on mobile
Hide the emoji button in the `chatbar` and don't instantiate the dialog component on mobile. This isn't needed on mobile as the virtual keyboard can add emojis. Should also save a small amount of memory on mobile from the dialog which is normally always instantiated.
2023-08-09 18:10:53 +00:00
l10n daemon script
80a5daa1f7 GIT_SILENT Sync po/docbooks with svn 2023-08-09 01:48:44 +00:00
Carl Schwan
bf5ce049d9 Port to new settings component 2023-08-08 21:40:05 +00:00
Carl Schwan
58213ee3e6 Display big emoji correctly
We already check with a regex if the message only contains emoji so it is safe
to hardcode the font family as emoji for these messages.
2023-08-08 12:07:16 +02:00
l10n daemon script
2d1862a637 GIT_SILENT Sync po/docbooks with svn 2023-08-08 01:49:39 +00:00
Tobias Fella
67453d9fb8 Remove ifdefs for E2EE 2023-08-07 21:15:11 +00:00
Tobias Fella
3ab04583ae Force plain text in room delegate 2023-08-07 22:58:11 +02:00
l10n daemon script
794683b5d2 GIT_SILENT Sync po/docbooks with svn 2023-08-07 02:08:13 +00:00
l10n daemon script
9f7f5409bd SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-08-07 01:51:19 +00:00
l10n daemon script
7d7b9d7ae0 GIT_SILENT made messages (after extraction) 2023-08-07 00:48:50 +00:00
James Graham
c7c892c51c Fix message long press
Add a tap handler so that long press events in the text of a message can be captured. This should make mobile menus work on text messages again.
2023-08-06 17:08:46 +00:00
l10n daemon script
97903a7cb0 GIT_SILENT Sync po/docbooks with svn 2023-08-06 01:50:23 +00:00
l10n daemon script
0c8f488ac4 GIT_SILENT made messages (after extraction) 2023-08-06 00:46:42 +00:00
Tobias Fella
88368cefaa Remove leftover debug statement 2023-08-06 00:51:28 +02:00
Tobias Fella
ab4bb41979 Fix last active time in devices page 2023-08-05 20:32:47 +02:00
James Graham
c2398b19dc Fix mark all read on room change
Fix it so that the view is correctly positioned at the bottom when the room is changed and make sure this is not seen as a scroll event (i.e. messages are not automatically marked as read but the timer has to time out first and all visible on screen).
2023-08-05 17:38:21 +00:00
James Graham
4b3dac025f Declare currentRoom property
Make sure `currentRoom` is a property for every qml component where it's used in `chatbar`.
2023-08-05 16:50:06 +00:00
l10n daemon script
9eeff06328 GIT_SILENT Sync po/docbooks with svn 2023-08-05 01:46:52 +00:00
l10n daemon script
657a8291d0 GIT_SILENT made messages (after extraction) 2023-08-05 00:46:28 +00:00
James Graham
bc4431462a Chatbox id for all property refs
Change the chatbox id to root and use for all references to it properties. Using root.currentRoom is needed for the chatbar to be visible in KF6
2023-08-04 13:56:26 +00:00
l10n daemon script
fdd8a62873 GIT_SILENT Sync po/docbooks with svn 2023-08-04 01:47:18 +00:00
l10n daemon script
c164228894 GIT_SILENT made messages (after extraction) 2023-08-04 00:46:08 +00:00
Carl Schwan
7d418f0883 Shorten appstream description 2023-08-03 16:17:58 +00:00
Tobias Fella
e90aecbead Port UserDetailDialog to Kirigami.Dialog 2023-08-03 17:26:46 +02:00
l10n daemon script
221c27fbbe GIT_SILENT Sync po/docbooks with svn 2023-08-03 02:09:50 +00:00
l10n daemon script
1907404124 GIT_SILENT Sync po/docbooks with svn 2023-08-02 01:54:58 +00:00
James Graham
81e953dd8c use QTEST_MAIN 2023-08-01 15:57:58 +00:00
James Graham
9311052e39 Move polishcolor to a utils namespace and rename getusercolor 2023-08-01 15:57:58 +00:00
James Graham
648fff20f2 Updates based on comments 2023-08-01 15:57:58 +00:00
James Graham
980211f36a Remove unneeded include 2023-08-01 15:57:58 +00:00
James Graham
25e0e3fa8e Remove NeoChatUser and just use Quotient::User this simplifies things and avoids casting from one to the other which address santizer didn't like 2023-08-01 15:57:58 +00:00
l10n daemon script
403c1ed391 GIT_SILENT Sync po/docbooks with svn 2023-08-01 01:58:12 +00:00
l10n daemon script
c2f76612cf GIT_SILENT made messages (after extraction) 2023-08-01 00:46:09 +00:00
Tobias Fella
2a651b8946 Use pageStack.pushDialogLayer for devtools and inviteuser 2023-07-31 20:44:50 +02:00
Volker Krause
00c0d1c276 Add heading indicator for live locations
Heading isn't covered by any MSC so far, so that is using Itinerary's
vendor prefix for now.
2023-07-31 18:06:52 +02:00
Carl Schwan
0162d91b60 Ensure e2ee is enabled 2023-07-31 07:09:23 +00:00
Carl Schwan
5f41b7b4c1 Fix opening account menu on right click 2023-07-31 07:02:00 +00:00
l10n daemon script
d9691bac7c GIT_SILENT Sync po/docbooks with svn 2023-07-31 02:10:40 +00:00
Tobias Fella
719b916837 Add accessible name to RoomDelegate 2023-07-30 22:57:46 +02:00
Tobias Fella
f9514fe925 Add accessible name to chatbar 2023-07-30 22:57:43 +02:00
Tobias Fella
399b9e6944 Add text and tooltip to section collapse/expand button 2023-07-30 22:29:21 +02:00
l10n daemon script
00cf5c8a5b GIT_SILENT Sync po/docbooks with svn 2023-07-30 01:49:49 +00:00
l10n daemon script
02f26424e2 GIT_SILENT made messages (after extraction) 2023-07-30 00:45:54 +00:00
Tobias Fella
3bd639775a Fix room list icon size in compact room list
BUG: 472682
2023-07-29 19:00:58 +00:00
Tobias Fella
163c1ef407 Html-escape display names in state delegates 2023-07-29 15:42:53 +02:00
Tobias Fella
9997b1074a Make "Close to system tray" string more correct
BUG: 472051
2023-07-29 09:01:14 +00:00
l10n daemon script
f52a25717b GIT_SILENT Sync po/docbooks with svn 2023-07-29 01:46:50 +00:00
l10n daemon script
5746c24b73 GIT_SILENT Sync po/docbooks with svn 2023-07-28 01:55:04 +00:00
l10n daemon script
dca1b22521 GIT_SILENT made messages (after extraction) 2023-07-28 00:47:00 +00:00
l10n daemon script
b15f1461d8 GIT_SILENT Sync po/docbooks with svn 2023-07-27 01:47:22 +00:00
Joshua Goins
24fd7a0f5b Use prettier notification images
Avatars are shown rounded in the main interface, so they should look the
same in the notification tray too. On top of that, if the room is a
group then show that group's icon when applicable in the bottom right.
2023-07-26 08:31:58 +00:00
Joshua Goins
0ac3932303 Add an obvious "upload" button in the account editor
It's not obvious at first glance that you can click on the avatar in the
account editor to upload an image. This adds a new button when there is
no image uploaded.
2023-07-26 08:27:55 +00:00
Joshua Goins
807a9ee779 Fix errors preventing the avatar from being shown when uploaded 2023-07-26 08:27:55 +00:00
Joshua Goins
4f32a168cd Fix settings button tooltip 2023-07-26 02:04:24 -04:00
l10n daemon script
45d2da56c7 GIT_SILENT Sync po/docbooks with svn 2023-07-26 01:49:31 +00:00
l10n daemon script
d794e26d62 GIT_SILENT made messages (after extraction) 2023-07-26 00:46:56 +00:00
l10n daemon script
42cc42642d GIT_SILENT Sync po/docbooks with svn 2023-07-25 01:47:33 +00:00
l10n daemon script
ffd6205bd1 GIT_SILENT Sync po/docbooks with svn 2023-07-24 09:05:17 +00:00
Tobias Fella
9ba6b2f0a5 Fix clearing user search field text when switching rooms 2023-07-24 08:45:51 +00:00
Carl Schwan
f8d3e25f8e Move no connection info message to the top 2023-07-24 08:45:10 +00:00
Carl Schwan
75cd77facb Refactor completion menu
- Use new Avatar
- Use required property in delegate
2023-07-24 08:44:49 +00:00
l10n daemon script
8546d76a54 GIT_SILENT made messages (after extraction) 2023-07-24 07:34:02 +00:00
Tobias Fella
00b7f68a03 Fix nullptr check 2023-07-23 23:10:52 +02:00
Carl Schwan
b486cb905c Add back some spacing around the avatar in the timeline 2023-07-22 18:41:09 +00:00
Carl Schwan
cdd5c9f484 Fix accessibility of StartChatPage and port to new components 2023-07-22 18:41:09 +00:00
Carl Schwan
3e6c426397 Port Avatar usage in Settings KirigamiAddons 2023-07-22 18:41:09 +00:00
Carl Schwan
847f41e1ad Port most Avatar usage to new KirigamiAddons Avatar 2023-07-22 18:41:09 +00:00
Carl Schwan
ed5bb270ff Discard wrong avatar urls 2023-07-22 17:51:03 +00:00
Carl Schwan
c8b4da2b96 Scroll to top of RoomDrawer on loading of header 2023-07-22 17:50:32 +00:00
Tobias Fella
ba5445e135 Stop finding QtKeychain
Has been upstreamed to libQuotient
2023-07-22 16:14:56 +02:00
l10n daemon script
1cca39e105 GIT_SILENT Sync po/docbooks with svn 2023-07-22 01:57:06 +00:00
Carl Schwan
dbf67b984e Fix reply error message when the reply is not loaded yet 2023-07-21 11:24:10 +02:00
l10n daemon script
c9126cf38e GIT_SILENT Sync po/docbooks with svn 2023-07-21 02:04:06 +00:00
Tobias Fella
13988da4fc Add login appium test 2023-07-20 07:14:23 +00:00
Carl Schwan
0847839abc Remove hover effect on timeline events 2023-07-20 08:40:15 +02:00
Carl Schwan
6b55e502a0 Remove duplicated code in QuickSwitcher for RoomDelegate 2023-07-20 08:39:59 +02:00
Carl Schwan
8f81629ac1 Redesign room list
Use KirigamiAddons.Delegated.RoundedItemDelegate
2023-07-20 08:39:57 +02:00
Carl Schwan
7f459cb90f Redesign timeline
Remove border von bubbles and only hilight the bubble on hover
2023-07-20 08:38:51 +02:00
l10n daemon script
420e195313 GIT_SILENT Sync po/docbooks with svn 2023-07-20 01:59:01 +00:00
Carl Schwan
3263a69880 Port to KirigamAddons.Banner 2023-07-19 22:46:36 +02:00
l10n daemon script
b060881f06 GIT_SILENT Sync po/docbooks with svn 2023-07-19 02:41:03 +00:00
Tobias Fella
701e786c1f Require passing tests on windows 2023-07-18 23:23:33 +02:00
Tobias Fella
646c8ba8fe Fix opening user mentions 2023-07-18 05:54:15 +00:00
Tobias Fella
9b31fdea10 Cleanup CMake after depending on libQuotient 0.7 2023-07-18 05:26:49 +00:00
l10n daemon script
ce5dfdee16 GIT_SILENT Sync po/docbooks with svn 2023-07-18 01:55:04 +00:00
Tobias Fella
918e805718 Fix image loading in room avatars 2023-07-17 11:25:52 +00:00
Albert Astals Cid
7debf47833 GIT_SILENT Upgrade release service version to 23.11.70. 2023-07-17 12:53:16 +02:00
Tobias Fella
2c142c36e6 Remove cmake policy 2023-07-17 11:57:19 +02:00
l10n daemon script
3279142498 GIT_SILENT Sync po/docbooks with svn 2023-07-17 01:57:57 +00:00
l10n daemon script
0e08a1aa7e GIT_SILENT made messages (after extraction) 2023-07-17 00:49:09 +00:00
Laurent Montel
3855922ad2 Add explicit moc includes to sources for moc-covered headers 2023-07-16 11:08:19 +02:00
l10n daemon script
89a094ce8f GIT_SILENT Sync po/docbooks with svn 2023-07-16 01:58:12 +00:00
l10n daemon script
d4421aaecf GIT_SILENT made messages (after extraction) 2023-07-16 00:48:59 +00:00
Tobias Fella
80b451c27b Only create consent sheet if required 2023-07-15 20:52:03 +00:00
Tobias Fella
32ff22ba89 Fix most compilation warnings 2023-07-15 20:39:38 +00:00
Tobias Fella
b990e3fbcb Stop using the AccountRegistry Singleton 2023-07-15 20:31:24 +00:00
Laurent Montel
8d1baab89f Add missing explicit keyword 2023-07-15 16:01:19 +00:00
Laurent Montel
62ecbc8d6b Includes is already defined in header 2023-07-15 16:58:34 +02:00
Laurent Montel
0e1c7f8c47 Fix qml Audio/Video support in qt6 too.
in Audio qt6 we don't have autoload feature but we disable it in qt5 => it seems ok

In Video qml qt6 we don't have flushMode.
2023-07-15 12:51:13 +00:00
Tobias Fella
c963966f1d Enforce namespaced includes for libQuotient 2023-07-15 14:05:11 +02:00
Tobias Fella
8db2526153 Improve DevicesPage and DevicesModel
- Split the list into sections for "this devices", "verified devices", "unverified devices", and "devices without encryption support"
- Sort the lists by last activity
2023-07-15 13:31:28 +02:00
Tobias Fella
7587a1a418 Drop ifdefs for libQuotient 0.7 2023-07-15 09:18:05 +02:00
Tobias Fella
294812956a Require libQuotient 0.7 2023-07-15 00:53:43 +02:00
Tobias Fella
d01aac6fa3 Remove libQuotient 0.6 based CI 2023-07-15 00:53:19 +02:00
l10n daemon script
5cda1ca3ce GIT_SILENT Sync po/docbooks with svn 2023-07-14 02:01:40 +00:00
Laurent Montel
bf26a463e0 Ignore build* 2023-07-13 07:13:47 +02:00
l10n daemon script
30180c1ac8 GIT_SILENT Sync po/docbooks with svn 2023-07-13 01:56:46 +00:00
l10n daemon script
41c296061c SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-07-13 01:45:17 +00:00
l10n daemon script
461420af0a GIT_SILENT made messages (after extraction) 2023-07-13 00:49:09 +00:00
Laurent Montel
052a7ed571 Ignore src/res.generated.qrc file 2023-07-12 22:28:08 +00:00
Laurent Montel
98e86f887b Adapt qml for qt5 and qt6 2023-07-12 22:28:08 +00:00
Laurent Montel
63a17b5985 Remove duplicate headers between header/cpp 2023-07-12 22:27:39 +00:00
Tobias Fella
025b367a7e Always enable E2EE in libQuotient
It's off-by-default in libQuotient 0.8
2023-07-12 22:10:37 +00:00
Laurent Montel
a8536b0634 Remove extra ; 2023-07-12 18:16:55 +00:00
Laurent Montel
0c43d3eeee Fix equal operator deprecated in c++20 2023-07-12 18:16:19 +00:00
Laurent Montel
bf1614256b Qt::AA_EnableHighDpiScaling is by default in qt6 2023-07-12 18:14:28 +00:00
Laurent Montel
99614d1b27 Use QString::isEmpty here 2023-07-12 14:27:24 +00:00
Laurent Montel
e1e57ef27a Use qt new header 2023-07-12 13:15:58 +00:00
Laurent Montel
6d45d126f8 Add explicit moc includes to sources for moc-covered headers
Add missing #pragma once + missing include

* speeds up incremental builds as changes to a header will not always
  need the full mocs_compilation.cpp for all the target's headers rebuild,
  while having a moc file sourced into a source file only adds minor
  extra costs, due to small own code and the used headers usually
  already covered by the source file, being for the same class/struct
* seems to not slow down clean builds, due to empty mocs_compilation.cpp
  resulting in those quickly processed, while the minor extra cost of the
  sourced moc files does not outweigh that in summary.
  Measured times actually improved by some percent points.
  (ideally CMake would just skip empty mocs_compilation.cpp & its object
  file one day)
* enables compiler to see all methods of a class in same compilation unit
  to do some sanity checks
* potentially more inlining in general, due to more in the compilation unit
* allows to keep using more forward declarations in the header, as with the
  moc code being sourced into the cpp file there definitions can be ensured
  and often are already for the needs of the normal class methods
2023-07-12 13:15:19 +00:00
Laurent Montel
732b43cbd6 Use const'ref 2023-07-12 11:55:50 +00:00
Laurent Montel
a5da17b000 Use explicit keyword 2023-07-12 11:49:12 +00:00
Laurent Montel
10a294f99e Fix show headers in qtc6 2023-07-12 13:17:30 +02:00
Laurent Montel
882a0d4901 Autogenerate + Install debug category file 2023-07-12 09:50:58 +00:00
Laurent Montel
506d31f53f "This" is not used 2023-07-12 09:50:41 +00:00
l10n daemon script
110f007b41 GIT_SILENT made messages (after extraction) 2023-07-12 00:47:42 +00:00
l10n daemon script
a90943d9ac GIT_SILENT Sync po/docbooks with svn 2023-07-11 01:50:22 +00:00
l10n daemon script
cbe7d8c2c2 GIT_SILENT made messages (after extraction) 2023-07-11 00:47:06 +00:00
James Graham
ae4943dd71 Use new mobileform heading
Does what is says on the tin. Use the recently merged new `MobileForm.FormHeader` component in all settings pages.
2023-07-10 16:46:35 +00:00
James Graham
7bd84bf51e Push Rule Model Rework
This is a significant rework of the handling of push rules. Rather than using a lot of boilerplate code for the default models `KeywordNotificationModel` has been converted to `PushRuleModel` and now handles all push rules.

The new model has the following features:
- Handles all push rules
- Has special handling for the names of default keywords (i.e. it still gives the same text as previously for showing in the settings menus)
- Push rules for blocking individuals or room overrides are still there but hidden so will be available for developer tools (to follow)
- Room specific keywords are now supported.

The notification settings pages have also been refactored to take advantage of the new models. Each section is now just a repeater with a filter for the rules that it should contain. The push rule delegate has now been cleaned up and uses required properties.

Implements network/neochat#574
2023-07-10 16:17:17 +00:00
l10n daemon script
a6ce44eb24 GIT_SILENT Sync po/docbooks with svn 2023-07-10 01:56:36 +00:00
Carl Schwan
b1c42c3d3d Make the whole right sidebar scrollable
The sidebar grew a lot and now contains some tools. This makes the space
left for the room members very small. Particuliary on mobile.

So make the whole sidebar contained inside the ScrollView

This also refactor a few things (e.g. use a plain ToolBar for the header)
2023-07-09 22:41:28 +00:00
Carl Schwan
213aaf3ac4 Ensure chat box and userInfo have the same height 2023-07-09 22:32:46 +00:00
James Graham
c55b40c9c6 Media Model
Create a media model for all the media message in the timeline and then setup `NeoChatMaximizeComponent` so that it can use the media model to scroll through all loaded images and video in the current room.

Depends upon libraries/kirigami-addons!105

FEATURE: 467411
2023-07-08 11:07:04 +00:00
Volker Krause
81928d8b93 Fix binary stripping of APKs with Qt 5.15.10
This fixes APKs on binary factory having exploded in size 3x-5x after
the Qt 5.15.10 update. This also affects release packages and will need
to be backported to those (in Craft).
2023-07-08 07:51:24 +02:00
Ingo Klöcker
b7bddba053 Add Windows-specific screenshots as custom values for Microsoft Store
This is an interim solution until AppStream (hopefully) gets support
for platform-specific screenshots. The captions will be extracted for
translation.
2023-07-07 15:55:11 +02:00
l10n daemon script
307a9370db GIT_SILENT Sync po/docbooks with svn 2023-07-07 01:54:27 +00:00
Volker Krause
2f65cbeb36 Show location descriptions in the timeline when available 2023-07-06 15:08:42 +00:00
l10n daemon script
e0c0b1f0e8 GIT_SILENT Sync po/docbooks with svn 2023-07-06 02:28:47 +00:00
l10n daemon script
74f767aa82 GIT_SILENT Sync po/docbooks with svn 2023-07-04 02:36:05 +00:00
l10n daemon script
7176dd4476 GIT_SILENT Sync po/docbooks with svn 2023-07-03 02:15:16 +00:00
l10n daemon script
f75fe31571 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-07-03 01:58:53 +00:00
l10n daemon script
61bdb1ed5f GIT_SILENT made messages (after extraction) 2023-07-03 00:55:03 +00:00
l10n daemon script
527e9d93a5 GIT_SILENT Sync po/docbooks with svn 2023-07-02 02:21:48 +00:00
l10n daemon script
7d22b30217 GIT_SILENT Sync po/docbooks with svn 2023-06-30 01:54:09 +00:00
Heiko Becker
c0d2333a3d GIT_SILENT Update Appstream for new release
(cherry picked from commit c72cf64369)
2023-06-30 01:16:59 +02:00
l10n daemon script
4a7e1d058c GIT_SILENT Sync po/docbooks with svn 2023-06-29 01:52:16 +00:00
l10n daemon script
66974615f6 GIT_SILENT Sync po/docbooks with svn 2023-06-28 01:55:40 +00:00
Ingo Klöcker
116c888686 Add "16:9 Super hero art" for Microsoft Store 2023-06-27 12:29:01 +02:00
Ingo Klöcker
f6d6a804d2 Add some logos in different sizes for the Microsoft Store 2023-06-27 12:28:06 +02:00
l10n daemon script
6d6d702b97 GIT_SILENT Sync po/docbooks with svn 2023-06-27 01:59:23 +00:00
l10n daemon script
9be04c1272 GIT_SILENT Sync po/docbooks with svn 2023-06-26 01:59:28 +00:00
l10n daemon script
6f5d88cf63 GIT_SILENT Sync po/docbooks with svn 2023-06-25 02:12:18 +00:00
l10n daemon script
1103e80191 GIT_SILENT made messages (after extraction) 2023-06-25 00:52:33 +00:00
l10n daemon script
a5320397c2 GIT_SILENT Sync po/docbooks with svn 2023-06-24 02:10:00 +00:00
Volker Krause
53719b971d Show a placeholder message if there are no shared locations 2023-06-22 15:17:40 +00:00
Volker Krause
64a1316f9b Zoom/center the page map so that all locations are in view 2023-06-22 15:17:40 +00:00
Volker Krause
a3b8168744 Add bounding box property for LocationsModel as well
Needed to property position the room map.
2023-06-22 15:17:40 +00:00
Volker Krause
c06e69931a Add fullscreen map to live location delegates as well 2023-06-22 15:17:40 +00:00
Volker Krause
30f8573dfc Show live location shares on the room map as well 2023-06-22 15:17:40 +00:00
Volker Krause
7f067b698e Unify map markers on the full screen and room maps as well 2023-06-22 15:17:40 +00:00
Volker Krause
b56ebdf149 Don't assert on invalid/empty geo: URIs 2023-06-22 15:17:40 +00:00
Volker Krause
a02dd4ab87 Extend LocationsModel to include asset and auther roles
Needed for compatibility with the standard map marker.
2023-06-22 15:17:40 +00:00
Volker Krause
898f0c962a Factor out map marker into its own QML element for reuse 2023-06-22 15:17:40 +00:00
Tobias Fella
5b4ae764cf Show a map for location events 2023-06-22 15:17:40 +00:00
l10n daemon script
d14db326bb GIT_SILENT Sync po/docbooks with svn 2023-06-22 01:53:18 +00:00
l10n daemon script
5c51e0d0fc GIT_SILENT Sync po/docbooks with svn 2023-06-21 01:49:24 +00:00
l10n daemon script
f78b4af692 GIT_SILENT Sync po/docbooks with svn 2023-06-19 02:05:24 +00:00
Carl Schwan
bd5ed0f46c Fix toolbar of RoomList when using font size 11px
We don't need to use a ToolBar for the titleDelegate since the
titleDelegate is already included inside a toolbar. This work magically
when using the default font size of 10px Noto Sans but breaks with 11px

BUG: 467242
2023-06-18 07:00:47 +00:00
l10n daemon script
529cfa8f7d GIT_SILENT Sync po/docbooks with svn 2023-06-18 02:44:28 +00:00
Carl Schwan
5552cd60f6 Group pageStack properties of the ApplicationWindow together 2023-06-17 21:29:15 +02:00
Tobias Fella
c51a1f4851 Fix another missing import 2023-06-17 14:32:03 +02:00
James Graham
a27f4765e4 Fix permission model
Make sure `Permissions.qml` uses the right role.
2023-06-17 09:34:42 +00:00
James Graham
402f99923c Fix NeoChatRoom type QML
Make sure import `org.kde.neochat 1.0` is included where `NeoChatRoom` is used as a type
2023-06-17 09:26:22 +00:00
l10n daemon script
2afda78912 GIT_SILENT Sync po/docbooks with svn 2023-06-17 01:53:16 +00:00
Volker Krause
25f9c7e125 Compute live location bounding box and center the map accordingly 2023-06-16 14:12:15 +00:00
Volker Krause
05082cb2bb Consider live location beacon timeouts for their 2023-06-16 14:12:15 +00:00
Volker Krause
59495a1452 Show starting live location beacons as location delegates in the timeline
Also, hide ending live location beacon state changes.
2023-06-16 14:12:15 +00:00
Volker Krause
d10460c45b Add live location tracking model
This can either watch a single live location beacon or all of those in
a given room.
2023-06-16 14:12:15 +00:00
l10n daemon script
b968c85de2 GIT_SILENT Sync po/docbooks with svn 2023-06-16 01:49:40 +00:00
l10n daemon script
13efc08b07 GIT_SILENT Sync po/docbooks with svn 2023-06-14 01:51:18 +00:00
Tobias Fella
718060c757 Re-enable accidentally disabled encryption 2023-06-13 12:22:32 +00:00
l10n daemon script
4092cd8b6a GIT_SILENT Sync po/docbooks with svn 2023-06-13 01:56:15 +00:00
Tobias Fella
ea99c26556 Fix logging 2023-06-12 13:33:38 +02:00
Tobias Fella
7527fd47cd Fix compiler warning 2023-06-12 13:29:23 +02:00
l10n daemon script
c72c9c5cba GIT_SILENT Sync po/docbooks with svn 2023-06-12 02:16:05 +00:00
Volker Krause
09ded20409 Fix location map asset check 2023-06-11 10:26:41 +02:00
l10n daemon script
0fd3de6215 GIT_SILENT Sync po/docbooks with svn 2023-06-11 01:56:11 +00:00
Tobias Fella
1de160cb19 Fix the search page
The search model needed to adapted to the changes in messageeventmodel
2023-06-10 13:57:03 +00:00
l10n daemon script
921abac3c1 GIT_SILENT Sync po/docbooks with svn 2023-06-10 01:54:53 +00:00
Volker Krause
7c75a2fd06 Create the OSM QtLocation plugin only once
Just loading that plugin already triggers an HTTP request, so lets only
do that when really needed and even more importantly, not for every single
location delegate again.
2023-06-09 18:39:38 +02:00
James Graham
105be518c7 Further improvements to the ChatBox API
Further improvements to the ChatBox API so that outside components no longer access the ChatBar item directly.
2023-06-09 15:02:42 +00:00
l10n daemon script
9425f24315 GIT_SILENT Sync po/docbooks with svn 2023-06-09 01:58:12 +00:00
Tobias Fella
47c28ce9a2 Improve QML types 2023-06-08 20:26:34 +00:00
Tobias Fella
72c85af407 Implement creating spaces 2023-06-08 20:05:53 +00:00
Volker Krause
22694fe5e4 Handle invalid model indices gracefully
data() being called with an invalid model index seems to happen during
normal operations here, with something in the proxy model chain not
catching that case (due to a row being filtered out presumably?).
2023-06-08 19:54:08 +00:00
Tobias Fella
a02232dc19 Fix custom emojis being visible in the sticker selector 2023-06-08 19:43:52 +00:00
Tobias Fella
252e099e75 Fix renaming log files > 10 2023-06-08 21:32:39 +02:00
Tobias Fella
76a697c3f6 Fix another invalid index 2023-06-08 21:23:38 +02:00
Joshua Goins
5b23593fd2 Let accounts without the emoticon account data to create emojis/stickers
This check worked for accounts that already had custom emojis, but if it
never had any added, m_images was never filled and the model would crash
when adding more.
2023-06-08 19:18:04 +00:00
Joshua Goins
c2580c1d2d Use correct placeholder message when there's no stickers
Instead of saying "No emojis" which doesn't make sense on the sticker
page.
2023-06-08 14:43:11 -04:00
Tobias Fella
3303d2c7db Keep last 50 log files
Keeping just the last two probably leads to important info being lost.
2023-06-08 17:55:45 +00:00
Tobias Fella
22107fc598 Don't try getting data for invalid indices
BUG: 470639
2023-06-08 17:55:13 +00:00
Tobias Fella
bc4c4f8519 Refactor login
BUG: 469486
2023-06-08 17:29:09 +00:00
l10n daemon script
16c63dbe93 GIT_SILENT Sync po/docbooks with svn 2023-06-08 01:56:11 +00:00
Volker Krause
9e78ab3328 Fix location markers not being shown on the map 2023-06-07 17:30:06 +02:00
l10n daemon script
e6dc1f54b3 GIT_SILENT Sync po/docbooks with svn 2023-06-07 02:00:09 +00:00
Tobias Fella
09025fa16d Remove some useless checks 2023-06-06 20:47:39 +02:00
l10n daemon script
357b148944 GIT_SILENT Sync po/docbooks with svn 2023-06-06 01:52:45 +00:00
Tobias Fella
8b71e56a5f Remove unneeded fallback 2023-06-05 21:41:13 +02:00
Tobias Fella
f5aa5ac7f4 Remove unneeded fallback for user's display name
The display name falls back to the user id internally.
2023-06-05 21:38:48 +02:00
James Graham
075d2fda4d Small chatbox api improvement
Small improvement to the chatbox api by making currentRoom explicit and removing redundant properties.
2023-06-05 18:20:12 +00:00
James Graham
b5c781212c Improve the handling of notifications
The aim is to put some additional filtering in place to better stop floods of old notifications. This is achieved with a couple of new filters and better tracking of old notifications.

- Make sure to paginate through all notification on initialization to ensure they are all added to old notifications. While we were not previously putting a limit on the number of returned notifications the server can and will do this when there are a very large amount.
- Find the newest timestamp for each connection on initialization and don't post any notifications with an earlier timestamp.
- Track old notifications on a per-connection basis.

Closes network/neochat#358 and network/neochat#423
2023-06-05 16:42:01 +00:00
l10n daemon script
af136943c3 GIT_SILENT Sync po/docbooks with svn 2023-06-05 01:48:05 +00:00
Tobias Fella
b2a29c8d45 Mark parameter as unused 2023-06-04 22:31:18 +02:00
Tobias Fella
5d16d78914 Minor cleanup in Controller::createRoom 2023-06-04 08:51:29 +00:00
Tobias Fella
94e970e15a Disable Windows Qt6 CI temporarily 2023-06-04 10:29:53 +02:00
Tobias Fella
1f4b984664 Unify emoji and sticker settings pages 2023-06-04 08:11:36 +00:00
l10n daemon script
a2a27e78d1 GIT_SILENT Sync po/docbooks with svn 2023-06-04 01:57:07 +00:00
l10n daemon script
915a5c188f GIT_SILENT made messages (after extraction) 2023-06-04 00:47:06 +00:00
Heiko Becker
e8f0420ad5 GIT_SILENT Update Appstream for new release
(cherry picked from commit 8dcc231bdc)
2023-06-02 22:05:12 +02:00
l10n daemon script
7a01b3ea28 GIT_SILENT Sync po/docbooks with svn 2023-06-01 01:55:18 +00:00
l10n daemon script
7cff2aaa97 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-06-01 01:40:43 +00:00
l10n daemon script
9588c7d8ef GIT_SILENT made messages (after extraction) 2023-06-01 00:47:06 +00:00
James Graham
d5a6c7683e Fix missing end of comment block. 2023-05-31 17:13:18 +01:00
l10n daemon script
1de4e2ecd3 GIT_SILENT Sync po/docbooks with svn 2023-05-31 02:29:02 +00:00
James Graham
fa37f28c94 Improve Delegate Width Sizing
Create a cpp helper class to calculate the correct delegate width given it's parent width.

This is designed to be more robust and hopefully easier to understand than the current mass of javascript calcs.

BUG: 470167
2023-05-30 18:14:25 +00:00
Tobias Fella
f1be509d13 Fix loading 2023-05-30 17:14:33 +02:00
l10n daemon script
fed528c6d8 GIT_SILENT Sync po/docbooks with svn 2023-05-30 02:12:13 +00:00
James Graham
d09cd5d71b Cleanup the list of required properties for MessageDelegateContextMenu 2023-05-29 15:03:34 +00:00
James Graham
4e40f5c7d9 getUser UserDetailDialog
Use `NeoChatRoom::getUser` to provide the user properties in `UserDetailDialog`
2023-05-29 13:43:24 +00:00
l10n daemon script
3b5bb06b4a GIT_SILENT Sync po/docbooks with svn 2023-05-29 01:51:45 +00:00
Tobias Fella
8f4e5a41c5 Drop reset*Count invocations
Still coming from Spectral, where they were taken from Quaternion, where they were dropped because they don't work as expected.
Also, soon to be removed from libQuotient itself.
2023-05-28 10:24:21 +00:00
l10n daemon script
9b1005efc3 GIT_SILENT Sync po/docbooks with svn 2023-05-28 01:59:58 +00:00
James Graham
e1d4b66479 Unify getUser
Always use `NeoChatRoom::getUser` for getting user details in a room context.
- `MessageEventModel` now calls `getUser`
- `getUser` is now overloaded to also be able to take a `NeoChatUser*`
- add params to `getUser` that are needed for the model outputs
2023-05-27 18:27:28 +00:00
Tobias Fella
f2aa375b43 Rename AccountStickerModel to AccountEmoticonModel
In preparation for using it for custom emojis as well
2023-05-27 16:38:25 +00:00
James Graham
ee53793a6d Fix replying and editing from chatbox
Restore the functionality to edit or reply to the last message in the `chatbar`.

This is achieved be moving the functions `getLastLocalUserMessageEventId` and `getLatestMessageFromRow` to `NeoChatRoom` as `editLastMessage` and `replyLastMessage` as `chatbar` no longer has access to `messageEventModel`.

The functions are also simplified as they only need to find the `eventId` and always from row 0 as this was the only use of the functions.

BUG: 469733
2023-05-27 16:36:09 +00:00
James Graham
528d46be9f Fix the room timeline being dragged when selecting text by making it non...
Fix the room timeline being dragged when selecting text by making it non interactive in desktop mode.

BUG: 467163
2023-05-27 16:06:20 +00:00
Joshua Goins
cc80e69644 Add better checks when the pack is omitted from im.ponies.room_emotes
This field is omittable, and I hit it this morning. Let's check if it's
filled before using it.
2023-05-27 15:33:42 +00:00
James Graham
09ced090f2 Use replyId role for reply ID 2023-05-27 16:12:21 +01:00
James Graham
8ad23e7a40 Timeline required properties
Move to using required properties for timeline delegates.
2023-05-27 14:57:34 +00:00
Tobias Fella
a94f46f904 Fix build against libQuotient 0.8 2023-05-27 13:17:02 +00:00
l10n daemon script
41a5d2557e GIT_SILENT Sync po/docbooks with svn 2023-05-27 01:50:19 +00:00
l10n daemon script
0b36db0ecc GIT_SILENT made messages (after extraction) 2023-05-27 00:47:24 +00:00
Shubham Arora
aae5519bed NeochatMaximizeComponent.qml: Add sourceWidth and sourceHeight
Depends on: https://invent.kde.org/libraries/kirigami-addons/-/merge_requests/103
2023-05-23 16:41:14 +00:00
l10n daemon script
df849accfa GIT_SILENT Sync po/docbooks with svn 2023-05-23 02:31:17 +00:00
l10n daemon script
b098937d1b GIT_SILENT Sync po/docbooks with svn 2023-05-22 01:52:21 +00:00
l10n daemon script
fbe4fc49e1 GIT_SILENT made messages (after extraction) 2023-05-22 00:47:42 +00:00
James Graham
8741fd8fed Refactor hover actions
Refactor hover actions into their own component.
2023-05-21 15:36:43 +00:00
l10n daemon script
ccc952b65e GIT_SILENT Sync po/docbooks with svn 2023-05-21 01:50:51 +00:00
Tobias Fella
6a68375b10 Rename NameRole to DisplayNameRole in UserListModel 2023-05-20 20:03:08 +00:00
Tobias Fella
4dcb19edb7 Fix avatar source warning 2023-05-20 19:47:12 +00:00
Tobias Fella
838abc9af3 Fix binding loop in GroupChatDrawerHeader 2023-05-20 19:29:35 +00:00
Tobias Fella
7283b2dd4d Use NavigationTabButtons for Emoji and sticker categories 2023-05-20 17:03:56 +00:00
Tobias Fella
2c1f00da03 Temporarily disable android qt6 CI 2023-05-20 17:03:33 +00:00
Carl Schwan
c7caec894e Assert that index is valid 2023-05-20 17:03:33 +00:00
Tobias Fella
b254b4aa9b Use KFormat for formatting dates 2023-05-20 17:03:33 +00:00
Tobias Fella
67107959e4 Remove unneeded "using namespace Quotient" 2023-05-20 17:03:33 +00:00
Tobias Fella
26d3e16e6d Remove empty destructor 2023-05-20 17:03:33 +00:00
Tobias Fella
bb8ee4ef44 Remove unneeded qml type registrations 2023-05-20 17:03:33 +00:00
Tobias Fella
ee65ad22e6 Rename LongOperationRole to ProgressInfoRole 2023-05-20 17:03:33 +00:00
Tobias Fella
b823f2c6b9 Remove unused role 2023-05-20 17:03:33 +00:00
l10n daemon script
0901c59de9 GIT_SILENT Sync po/docbooks with svn 2023-05-20 01:52:01 +00:00
Nate Graham
69bfa1394c Focus message search window's search field by default
BUG: 469879
2023-05-19 13:16:21 +00:00
l10n daemon script
5b69a3e07c GIT_SILENT Sync po/docbooks with svn 2023-05-19 01:49:45 +00:00
James Graham
37220ab872 Fix notification state in new rooms
Make sure that the `updateNotificationState` function is called when the base state is loaded so that new rooms after startup have a valid notification state.

Fixes network/neochat#583
2023-05-18 19:23:31 +00:00
l10n daemon script
9dd7ceb966 GIT_SILENT Sync po/docbooks with svn 2023-05-18 01:50:45 +00:00
Tobias Fella
ae6056615d Add missing capture 2023-05-18 00:03:07 +02:00
Tobias Fella
d74253d149 Update copyright year 2023-05-17 23:50:57 +02:00
Tobias Fella
805332c599 Don't use implicit lambda captures 2023-05-17 23:49:56 +02:00
Tobias Fella
e42c1c1f69 Use NavigationTabBar for emoji/sticker picker 2023-05-17 14:02:03 +00:00
Tobias Fella
f7881d0661 Fix spacedrawer being visible when there are no spaces
We can't (easily) make this declarative, since there are no spaces on startup, causing the loader to be disabled,
making the repeater not load anything, which means the loader stays disabled.
We should figure out a better solution, since this means that the drawer doesn't open immediately when joining a space,
but for now this fix is better then the current bug.
2023-05-17 15:38:10 +02:00
Carl Schwan
5eb86bbc88 Add neochat mastodon account 2023-05-17 11:30:17 +02:00
l10n daemon script
53dc32fac1 GIT_SILENT Sync po/docbooks with svn 2023-05-17 01:51:56 +00:00
James Graham
a5a2c0b03e Reaction Model
Create a reaction model that provides all the required data for `ReactionDelegate` so that none need to be calculated in QML.

This also cleans up the API for `ReactionDelegate`
2023-05-16 16:44:02 +00:00
Tobias Fella
4d2e64cb80 Cleanup name handling in RoomListModel
Replace NameRole with DisplayNameRole entirely.
2023-05-16 16:38:53 +02:00
Tobias Fella
dee064a758 Fix crash in room switching 2023-05-16 14:37:07 +00:00
Tobias Fella
5bdd67dcc1 Fix background color of TypingPane 2023-05-16 14:36:37 +00:00
Tobias Fella
2ff92bea70 Fix warning for empty avatar source 2023-05-16 14:11:38 +00:00
l10n daemon script
0fbb070bf2 GIT_SILENT Sync po/docbooks with svn 2023-05-16 01:57:02 +00:00
l10n daemon script
1a1c7ef23e GIT_SILENT made messages (after extraction) 2023-05-16 00:47:11 +00:00
Tobias Fella
fabd3da5a7 Fix asan runtime error in texthandler 2023-05-15 23:36:25 +00:00
Tobias Fella
6f90d33f3a Add new messages to bottom of notifications list 2023-05-15 19:49:05 +00:00
Aleix Pol
3bb0ee17cd NotificationsManager: Group notifications per room
Instead of issuing a new notification for every message, bundle them by
room.
It looks like the code was originally designed to do that and somehow we
forgot along the way.
It also fixes the leaking in m_notifications as we were never cleaning
after it.
2023-05-15 19:49:05 +00:00
Tobias Fella
fa8164cdba Fix notifications showing up repeatedly when multiple logged-in accounts are in the same room
What happens is roughly: The notification is received in one account and marked as received locally.
In the other account, the event is marked as "read" in the json, which makes us delete it from the
received messages. Then it is received on the first account...
2023-05-15 21:28:08 +02:00
James Graham
c63f1f0452 Cache last event
Cache the last room event so that the room list can be sorted on startup

Fixes network/neochat#88 \
BUG: 455042
2023-05-15 19:11:44 +00:00
l10n daemon script
e0df447998 GIT_SILENT Sync po/docbooks with svn 2023-05-15 01:50:59 +00:00
l10n daemon script
a64d4d0989 GIT_SILENT made messages (after extraction) 2023-05-15 00:47:14 +00:00
Tobias Fella
4c575f18d1 Fix avatar name 2023-05-14 23:57:32 +02:00
Tobias Fella
b629961a70 Create account sticker editor 2023-05-14 20:33:51 +00:00
l10n daemon script
571d9780b1 GIT_SILENT Sync po/docbooks with svn 2023-05-14 02:06:27 +00:00
l10n daemon script
df2ed04f16 GIT_SILENT made messages (after extraction) 2023-05-14 00:48:05 +00:00
Akseli Lahtinen
3d687a283e Add more bottom margin
Adds more bottom margin so the Now Typing box wont cover the text

BUG: 469616
2023-05-13 17:21:31 +00:00
l10n daemon script
99479b3896 GIT_SILENT Sync po/docbooks with svn 2023-05-13 01:51:06 +00:00
James Graham
7fca14bce1 Fix Chatbar text margin
Make sure that the padding in the chatbar textarea accounts for the x offset
2023-05-12 17:13:40 +00:00
Tobias Fella
afb51497cd Fix autocompletion not working
BUG: 468967
2023-05-12 17:12:28 +00:00
James Graham
88fada89ea Limit the maximum number of avatars shown
Limit the maximum number of avatars shown for other user read markers and collapsed state events

For state events \
![image](/uploads/0d3ec7c3da02a8832dfdb18dc265db92/image.png)

For read markers \
![image](/uploads/5694f14927e5c10b2159e58445c8a0a3/image.png)
2023-05-12 15:54:15 +00:00
James Graham
023c51ac62 Fix QuickSwitcher notification count
Use `notificationcount` instead of unread count in the `quickswitcher` as unread count is removed
2023-05-12 14:09:02 +00:00
Luigi Toscano
c37fa92559 Readd some text removed by the translation system
Restore part of the contents previously introduced by
cc21f8cca9 which was partially
lost, probably due to an extra '>' outside the tags
which confused the translation system.

Credits for the text, see the original commit (Carl Schwan).
2023-05-12 12:44:24 +02:00
l10n daemon script
9dabb890dc GIT_SILENT Sync po/docbooks with svn 2023-05-12 01:55:21 +00:00
l10n daemon script
e40c3b4c03 GIT_SILENT made messages (after extraction) 2023-05-12 00:48:20 +00:00
l10n daemon script
5be7105bb8 GIT_SILENT Sync po/docbooks with svn 2023-05-11 01:50:00 +00:00
l10n daemon script
8dc9541d95 GIT_SILENT made messages (after extraction) 2023-05-11 00:46:56 +00:00
James Graham
6e5b71888d Refresh all reply roles on loadReply
Make sure that all reply roles that depend on a pointer to the reply event being available are refreshed.
2023-05-10 16:41:22 +00:00
James Graham
b362365609 Remove Unread Count
Unread count is deprecated and notification count should be used in all cases. As such remove unreadCount and use notification count in all places it was being used.

Fixes network/neochat#76 \
BUG: 466515
2023-05-10 16:23:14 +00:00
l10n daemon script
1db2e4a333 GIT_SILENT Sync po/docbooks with svn 2023-05-10 01:52:11 +00:00
l10n daemon script
6e8e40c22f GIT_SILENT made messages (after extraction) 2023-05-10 00:47:12 +00:00
Carl Schwan
cc21f8cca9 Update appstream description 2023-05-09 19:32:52 +00:00
Tobias Fella
b545a27bc6 Fix ReplyComponent warnings 2023-05-09 13:22:41 +02:00
Tobias Fella
c9d863335e Disable various tests and examples in the flatpak manifest 2023-05-09 11:14:12 +00:00
Tobias Fella
334e3ac6b4 Delete old space components 2023-05-09 09:57:08 +00:00
James Graham
d424aba0bc Document imagepacksmodel 2023-05-09 09:55:36 +00:00
James Graham
8802753de1 Custom emoji image data
Make sure the imageInfo for custom emojis is set. This ensures that all the data required by imageDelegate is available.
2023-05-09 09:15:07 +00:00
James Graham
40edfef046 Document stickermodel 2023-05-09 08:14:21 +00:00
Tobias Fella
11343e6bdf Improve spaces support 2023-05-09 08:11:47 +00:00
l10n daemon script
30c7d86045 GIT_SILENT Sync po/docbooks with svn 2023-05-09 01:57:26 +00:00
James Graham
58b7b46828 Update README.md
Update README.md ensuring that info is up to date.

The following has been changed:
- Updated about info (intro, features)
- Reference KDE standard docs for building, MRs, etc
2023-05-08 14:16:43 +00:00
James Graham
3d0c0e3ed5 Move stickermodel into the models folder 2023-05-08 09:40:26 +01:00
James Graham
77d8ec04ca Document imagepackevent 2023-05-08 08:34:32 +00:00
James Graham
72de7c6cfb Link preview messageeventmodel parameters
This move the finding of links and the creation of a `linkpreviewer` into c++.

- The links are now extracted from the text in `texthandler`
- The `messageeventmodel` now creates and stores `linkpreviewers` for events that have links in the current room.

Two new model roles have been created to let a text delegate know when the link preview should be shown (`showLinkPreview`) and pass the link previewer (`linkPreviewer`). Empty link previewer are returned where link don't exist so the qml doesn't have to have checks for whether the parameters are undefined.
2023-05-08 08:18:49 +00:00
James Graham
b82d3ab5ad TempInfo Messageeventmodel
Further improvements to the handling of `mediaInfo` in `messageeventmodel`.

`blurhash` and `thumbnailInfo` are now replaced with a single `tempInfo` object that contains a single temp source. The priority is thumbnail > `blurhash` > empty if none exist.

Fixes network/neochat#235
2023-05-08 07:50:20 +00:00
l10n daemon script
20443ba59f GIT_SILENT Sync po/docbooks with svn 2023-05-08 01:54:02 +00:00
Tobias Fella
bfdca9ca9e Fix regressions from RoomPage refactoring
Fixes 581

BUG: 469427
BUG: 469425
2023-05-07 16:17:28 +00:00
Tobias Fella
a12a44b722 Fix crash in media url 2023-05-07 15:36:59 +00:00
James Graham
8d45d4404e Move imagepacksmodel to the models folder 2023-05-07 15:11:08 +00:00
Tobias Fella
42ca128d7f Fix linking against Qt6 libQuotient 2023-05-07 15:10:32 +00:00
l10n daemon script
7cd8e70d55 GIT_SILENT Sync po/docbooks with svn 2023-05-07 01:59:27 +00:00
Tobias Fella
2982d2526a Remove logging statement
Turns out this happens a lot
2023-05-06 22:27:16 +02:00
Tobias Fella
d33a0c6644 Fix another imagepack crash 2023-05-06 20:22:27 +00:00
Tobias Fella
4a29e0d0e1 Add categorized logging to MessageEventModel 2023-05-06 17:53:01 +02:00
Tobias Fella
a89e04b92f Fix merge 2023-05-06 17:28:46 +02:00
James Graham
4b993775c6 Move Neochat specific libQuotient events to their own folder 2023-05-06 15:10:17 +00:00
Tobias Fella
e0983fcc8c Refactor RoomPage into various component 2023-05-06 15:09:00 +00:00
Tobias Fella
c9ddf2f04a Fix crash when there are no account emojis 2023-05-06 15:31:20 +02:00
Heiko Becker
b5764c4d04 GIT_SILENT Update Appstream for new release
(cherry picked from commit 41ce874f77)
2023-05-06 11:19:38 +02:00
James Graham
5f41d275e4 Document runner 2023-05-06 08:22:09 +00:00
l10n daemon script
7f707ae042 GIT_SILENT Sync po/docbooks with svn 2023-05-06 01:55:01 +00:00
James Graham
270a1e3a96 Fix room notifications settings
Make sure that the room property is set for the Push Notification room settings page.
2023-05-05 17:12:33 +00:00
James Graham
65d919876c Document trayicon_sni 2023-05-05 16:53:38 +00:00
Tobias Fella
049ae3602f Fix binding loop in ChatBar 2023-05-05 16:03:50 +00:00
Tobias Fella
d4c8e558e0 Remove empty settings pages 2023-05-05 17:42:45 +02:00
James Graham
0e4d87824e Document windowcontroller 2023-05-05 15:23:18 +00:00
James Graham
cd7f6d52dd document urlhelper 2023-05-05 14:38:48 +00:00
Tobias Fella
96c1b98d02 Implement sending stickers
MSC2545 image packs are used as source.
2023-05-05 14:29:18 +00:00
Tobias Fella
443d709eb8 Save log to file and always save e2ee debug logs
This will hopefully help us debug e2ee problems
2023-05-05 10:15:43 +00:00
James Graham
5107f0e79e document joinruleevent 2023-05-05 07:45:52 +00:00
James Graham
5567f94535 Document filetransferpseudojob 2023-05-05 07:45:05 +00:00
l10n daemon script
8e566e7326 GIT_SILENT Sync po/docbooks with svn 2023-05-05 01:59:44 +00:00
l10n daemon script
43c6172482 GIT_SILENT Sync po/docbooks with svn 2023-05-04 02:00:18 +00:00
James Graham
f453334f63 Document trayicon 2023-05-03 19:58:47 +00:00
James Graham
ac24e06ae2 Document spacehierarchycache 2023-05-03 19:58:27 +00:00
James Graham
eab5abec2f Document roommanager 2023-05-03 18:49:20 +00:00
James Graham
0fc962b147 Document stickerevent 2023-05-03 17:51:36 +00:00
James Graham
10794628ed MessageEventModel media info improvements
Create a `messageeventmodel` role for media info and reply media info that is a QMap with all the required data.

This replaces the MediaUrlRole, FileMimeTypeRole and the ContentTypeRole. The reply role no longer needs the content role.

This also ensures mxc urls are now generated for replies. All the media parameters will now have default values assigned in the model so the QML no longer needs to do this.
2023-05-03 17:50:48 +00:00
l10n daemon script
a6f108d3b8 GIT_SILENT Sync po/docbooks with svn 2023-05-03 02:02:58 +00:00
James Graham
c4e80c1d1c Document pollevent 2023-05-02 18:39:08 +00:00
James Graham
6f231fa916 Document pollhandler 2023-05-02 18:10:49 +00:00
l10n daemon script
5d5f5c4ab7 GIT_SILENT Sync po/docbooks with svn 2023-05-02 02:02:48 +00:00
Gary Wang
034453636d Use MobileForm.FormSpinBoxDelegate for SpinBox in proxy page 2023-05-01 10:00:41 +00:00
Tobias Fella
8e4da42a64 Fix crash in avatar url handling 2023-05-01 11:49:35 +02:00
James Graham
7156bf0711 Link Previewer MXC Links
- Update link preview to get valid mxc links.
- Get the connection from a room.
2023-05-01 09:12:16 +00:00
l10n daemon script
bc317514e6 GIT_SILENT Sync po/docbooks with svn 2023-05-01 02:14:22 +00:00
James Graham
26b2380bb7 Document linkpreviewer 2023-04-30 20:09:35 +00:00
James Graham
685b2a68ba Document notificationsmanager 2023-04-30 19:49:21 +00:00
James Graham
9936c7a8b6 Document login 2023-04-30 19:33:17 +00:00
James Graham
83da52582b Document matriximageprovider 2023-04-30 19:13:13 +00:00
James Graham
fbf918c7d0 Document neochatuser 2023-04-30 18:55:59 +01:00
James Graham
2281fe6f8a Improve User Avatar Model Roles
- Update the message event and user models so that the full source url is output.
- Separate the reply author into its own role
- Create an empty user object that can be passed so that the QML code no longer needs to check if certain parameters exist.
- Make avatarForMember return and empty QUrl if a valid avatar cannot be found and make use in the user and event models

As well as cleaning up the QML this should also stop the QML Image: Media id '' doesn't follow server/mediaId pattern spam in the log.
2023-04-30 13:51:06 +00:00
l10n daemon script
1bb03e115e GIT_SILENT Sync po/docbooks with svn 2023-04-30 02:48:26 +00:00
Tobias Fella
9d6ebf53a9 Fix reply loading 2023-04-29 21:39:16 +02:00
Tobias Fella
9e780b8eb2 Remove warning when event to refresh wasn't found
This can legitimitely happen, e.g. when a reaction is loaded for an event that we haven't loaded
2023-04-29 21:28:32 +02:00
Tobias Fella
01b34c5b8c Get rid of some warnings 2023-04-29 20:56:53 +02:00
Tobias Fella
11233bee3a Fix trayicon disconnect warning 2023-04-29 20:10:11 +02:00
Tobias Fella
e94b3caf51 Run tests guiless 2023-04-29 19:48:57 +02:00
James Graham
e8166f3433 Improve Invitation Flow
- Update the conatainsUser function to use memberState so that invites do not show up as being in the leave state.
- Update the InviteUser page to use Kirigami.BasicListItem and make the invite button remain visible but be untoggleable when the if user has already been invited.

closes network/neochat#202
2023-04-29 17:13:24 +00:00
Tobias Fella
d844945453 Improve RoomDrawer for direct chats
Don't show irrelevant stuff like the member list, description, alias

BUG: 466895
2023-04-29 18:39:40 +02:00
James Graham
85b40ca536 Devtools Improvements
- Now has tabs setup as more features are added
- First extra tab has basic server info
- Use mobileform to make it look nicer
- For the room data tab allow the room to be changed from within devtools
- For the room data tab allow m.room.member events to be filtered out so other event types can be found easily
- For the room data tab allow viewing room account data

network/neochat#557
2023-04-29 15:20:51 +00:00
James Graham
ca805917de Document and Cleanup userlistmodel
Document and cleanup userlist model.

- Remove unneeded enum UserTypes
- Cleanup includes and remove need to include QPointer
- make clear that it is a user or users that are being refreshed

Note: breaks libquotient 0.6 compatibility because of the changes to how m_currentRoom is handled
2023-04-29 14:53:01 +00:00
Tobias Fella
014185c4c9 Prevent crash in SyntaxHighlighter when leaving room
BUG: 467722
2023-04-28 14:14:02 +00:00
Tobias Fella
2b06679be6 Fix handling line separators
BUG: 468977
2023-04-28 13:47:25 +00:00
Tobias Fella
7d2edc7c52 Fix Ctrl+Shift+, opening settings
BUG: 469057
2023-04-28 12:47:53 +00:00
Nicolas Fella
224bc9441b Add 23.04.0 Windows artifact 2023-04-28 12:45:27 +02:00
l10n daemon script
5a7b17a31e GIT_SILENT Sync po/docbooks with svn 2023-04-28 01:54:31 +00:00
Tobias Fella
eea8950afb Fix room search field shortcut
The shortcut was stolen by the search field in the quick switcher

BUG: 469059
2023-04-28 01:03:24 +02:00
James Graham
9f15c7fc53 Fix messageeventmodel message role
Change remaining messageeventmodel message role to plainText
2023-04-27 17:38:42 +00:00
James Graham
4b879be4ea MessageEventModel plain text role
Update the message role to be named plainText and use it the message delegate for openMessageContext.
This removes the need for plainText in controller so it is removed.
2023-04-27 16:58:52 +00:00
James Graham
af078f03d0 Document filetypesingleton 2023-04-27 15:20:36 +00:00
Tobias Fella
cdf2c390ca Don't abandon job when image request is cancelled
Aborting the request causes a lot of logged messages. In theory, not stopping the job causes some overhead,
but that's negligible and the provider is on its way out anyway.
2023-04-27 11:32:46 +00:00
l10n daemon script
77b2186cb6 GIT_SILENT Sync po/docbooks with svn 2023-04-27 01:58:08 +00:00
James Graham
0664ef8ccb Document controller
Document controller and cleanup some unused functions
2023-04-26 19:56:56 +00:00
James Graham
4af7537764 Cleanup Controller
Remove unused functions and use setQuitOnLastWindowClosed as a slot for reacting to the tray icon setting change only.
2023-04-26 19:29:16 +00:00
l10n daemon script
f47e7531fc GIT_SILENT Sync po/docbooks with svn 2023-04-26 02:00:56 +00:00
Tobias Fella
e484a08e8d Fix Keys in QuickSwitcher 2023-04-25 14:54:09 +02:00
l10n daemon script
56f3d0e0d6 GIT_SILENT Sync po/docbooks with svn 2023-04-25 02:08:27 +00:00
l10n daemon script
3797854b0c GIT_SILENT Sync po/docbooks with svn 2023-04-24 02:14:01 +00:00
James Graham
931e91ddba Document emojitones 2023-04-23 18:36:50 +00:00
James Graham
25754bbe22 Document colorschemer 2023-04-23 12:44:52 +00:00
James Graham
53884949d1 Document chatdocumenthandler
Document chatdocumenthandler and cleanup includes
2023-04-23 11:12:29 +00:00
James Graham
abb2a340e2 Document blurhash
Add documentation from the blurhash reference implementation to the code.
2023-04-23 09:56:36 +00:00
James Graham
ed874ed00a Document clipboard 2023-04-23 08:24:09 +00:00
l10n daemon script
a8aec35884 GIT_SILENT Sync po/docbooks with svn 2023-04-23 02:42:19 +00:00
James Graham
0496f6552a Document blurhashimageprovider 2023-04-22 18:50:34 +00:00
James Graham
970cd5cf7a Document actionshandler
Also cleanup some unused includes
2023-04-22 18:50:17 +00:00
Carl Schwan
2fb4fdd18f Port SpellChecking setting page to mobileform 2023-04-22 11:20:37 +00:00
Carl Schwan
fc1dc5c1d6 Bump dependency to kirigami
We need the new settings action api
2023-04-22 09:49:59 +00:00
James Graham
800194c6f5 Document userdirectorylistmodel 2023-04-22 08:34:22 +00:00
James Graham
0cab7b1c85 Document webshortcutmodel 2023-04-22 08:33:12 +00:00
James Graham
983d4c9db2 Document sortfilterspacelistmodel 2023-04-22 08:32:19 +00:00
James Graham
88dfacbbb3 Document sortfilterroomlistmodel 2023-04-22 08:31:54 +00:00
James Graham
3f572c79fa Document statemodel 2023-04-22 08:31:28 +00:00
l10n daemon script
a7ee1fac3c GIT_SILENT Sync po/docbooks with svn 2023-04-22 02:08:02 +00:00
l10n daemon script
068bfc948b GIT_SILENT Sync po/docbooks with svn 2023-04-21 01:58:19 +00:00
l10n daemon script
47470f5a6d GIT_SILENT Sync po/docbooks with svn 2023-04-20 02:05:22 +00:00
James Graham
144dc1f8f4 Use kirigami-addons maximise components
Use new kirigami-addons MaximizeImage.qml to replace local FullScreenImage.qml

depends upon libraries/kirigami-addons!88

TODO
- [x] Remove the old `fullscreenimage.qml` before merging as no longer needed

Implements #571
2023-04-19 21:10:30 +00:00
Tobias Fella
4002bb804c Don't require passing tests on windows Qt6 2023-04-19 21:53:28 +02:00
Carl Schwan
760ed24b37 Add loading title to LoadingPage
Otherwise the page is a bit empty
2023-04-19 07:39:49 +00:00
Carl Schwan
489979af43 Fix Ctrl-PageUp/Down navigation 2023-04-19 07:39:23 +00:00
l10n daemon script
e482e12826 GIT_SILENT Sync po/docbooks with svn 2023-04-19 02:03:35 +00:00
Tobias Fella
fa7b9d54e2 Fix logout from account menu 2023-04-18 13:04:25 +00:00
Tobias Fella
f60114c7f6 Refactor account labels
Move them out of NeoChatUser, where they don't make any sense
2023-04-18 08:29:24 +00:00
l10n daemon script
de55253e54 GIT_SILENT Sync po/docbooks with svn 2023-04-18 01:58:53 +00:00
Shooting Star
8479e51051 Check if room is null before enter room
There will be some case, like the notify is still exist, but user have
logout their account, user leave the room, these cause the room become a
nullptr, and when click the notify message, it make neochat coredump
2023-04-17 19:25:53 +00:00
Tobias Fella
bb2fd7c9c4 Fix dialog button role 2023-04-17 19:34:43 +02:00
Nicolas Fella
a0b0a5d47f Set associated window for tray icon 2023-04-17 09:46:04 +00:00
l10n daemon script
10bdc1d3d1 GIT_SILENT Sync po/docbooks with svn 2023-04-17 02:41:30 +00:00
James Graham
6ec7d8d6b4 Use DelegateTypeRole searchmodel
Change EventTypeRole to DelegateTypeRole to match updated message event model.
2023-04-16 08:32:51 +00:00
l10n daemon script
0dca9588ff GIT_SILENT Sync po/docbooks with svn 2023-04-16 01:56:40 +00:00
Tobias Fella
ca03c530b2 Fix various warnings 2023-04-15 18:07:26 +00:00
James Graham
973ec24674 Document searchmodel 2023-04-15 17:57:21 +00:00
James Graham
1da767ff0a Document roomlistmodel 2023-04-15 17:18:33 +00:00
James Graham
89127876f9 Document serverlistmodel 2023-04-15 16:51:32 +00:00
Tobias Fella
47a738a703 Revert "Revert "Implement sending location messages""
This reverts commit 52dafbb6c8.
2023-04-15 16:01:04 +00:00
James Graham
516b1cff88 Document publicroomlistmodel 2023-04-15 09:00:49 +00:00
James Graham
6438977964 Document messagefiltermodel 2023-04-15 08:46:45 +00:00
James Graham
d750263d39 Document keywordnotificationrulemodel 2023-04-15 08:32:35 +00:00
James Graham
3ed952db9e Document emojimodel 2023-04-15 08:15:23 +00:00
James Graham
f8040a1bf6 Guard getTagType and isCloseTag
Add guard clauses for getTagType and isCloseTag to avoid crashing if the string is empty.

CCBUG: 468448
2023-04-15 07:59:05 +00:00
l10n daemon script
d83b31fd86 GIT_SILENT Sync po/docbooks with svn 2023-04-15 01:59:35 +00:00
James Graham
e0dbb657f6 Document devicesmodel 2023-04-14 13:14:39 +00:00
James Graham
a807cc6143 Document customemojimodel 2023-04-14 12:57:05 +00:00
l10n daemon script
fe064c0ef8 GIT_SILENT Sync po/docbooks with svn 2023-04-14 01:50:25 +00:00
James Graham
6cc773426f Document completionmodel
Document completionmodel and remove unnecessary includes
2023-04-13 17:35:44 +00:00
James Graham
db94408ba6 Document completionproxymodel 2023-04-13 17:15:38 +00:00
James Graham
333bd3cdb9 Document collapsestateproxymodel
Document collapsestateproxymodel and make som public functions private.
2023-04-13 16:41:41 +00:00
l10n daemon script
9a0d82eb31 GIT_SILENT Sync po/docbooks with svn 2023-04-13 01:58:59 +00:00
James Graham
0990c0507c Document actionsmodel and cleanup includes 2023-04-12 21:12:14 +00:00
Heiko Becker
9f76ce22c1 GIT_SILENT Update Appstream for new release
(cherry picked from commit 2c3ce1e88b)
2023-04-12 19:09:48 +02:00
l10n daemon script
6acd6075ff GIT_SILENT Sync po/docbooks with svn 2023-04-12 01:55:28 +00:00
484 changed files with 183730 additions and 122790 deletions

10
.craft.ini Normal file
View File

@@ -0,0 +1,10 @@
; SPDX-FileCopyrightText: None
; SPDX-License-Identifier: CC0-1.0
[BlueprintSettings]
kde/unreleased/kirigami-addons.version=master
kde/frameworks.version=master
kde/libs.version=master
kde/plasma.version=master
kde/unreleased.version=master
libs/qt.qtMajorVersion=6

View File

@@ -2,7 +2,7 @@
"id": "org.kde.neochat",
"branch": "master",
"runtime": "org.kde.Platform",
"runtime-version": "5.15-22.08",
"runtime-version": "6.6-kf6preview",
"sdk": "org.kde.Sdk",
"command": "neochat",
"tags": [
@@ -12,13 +12,14 @@
"finish-args": [
"--share=network",
"--share=ipc",
"--socket=x11",
"--socket=fallback-x11",
"--socket=wayland",
"--device=dri",
"--filesystem=xdg-download",
"--talk-name=org.freedesktop.Notifications",
"--talk-name=org.kde.kwalletd5",
"--talk-name=org.kde.StatusNotifierWatcher",
"--talk-name=org.freedesktop.secrets",
"--own-name=org.kde.StatusNotifierItem-2-2"
],
"modules": [
@@ -30,6 +31,7 @@
},
{
"name": "kquickimageeditor",
"config-opts": [ "-DBUILD_WITH_QT6=ON" ],
"buildsystem": "cmake-ninja",
"sources": [
{
@@ -41,6 +43,7 @@
{
"name": "olm",
"buildsystem": "cmake-ninja",
"config-opts": [ "-DOLM_TESTS=OFF" ],
"sources": [
{
"type": "git",
@@ -83,8 +86,8 @@
"sources": [
{
"type": "archive",
"url": "https://github.com/frankosterfeld/qtkeychain/archive/v0.13.2.tar.gz",
"sha256": "20beeb32de7c4eb0af9039b21e18370faf847ac8697ab3045906076afbc4caa5",
"url": "https://github.com/frankosterfeld/qtkeychain/archive/0.14.2.tar.gz",
"sha256": "cf2e972b783ba66334a79a30f6b3a1ea794a1dc574d6c3bebae5ffd2f0399571",
"x-checker-data": {
"type": "anitya",
"project-id": 4138,
@@ -94,6 +97,7 @@
}
],
"config-opts": [
"-DBUILD_WITH_QT6=ON",
"-DCMAKE_INSTALL_LIBDIR=/app/lib",
"-DLIB_INSTALL_DIR=/app/lib",
"-DBUILD_TRANSLATIONS=NO"
@@ -111,12 +115,15 @@
}
],
"config-opts": [
"-DQuotient_ENABLE_E2EE=ON"
"-DBUILD_WITH_QT6=ON",
"-DQuotient_ENABLE_E2EE=ON",
"-DBUILD_TESTING=OFF"
]
},
{
"name": "cmark",
"buildsystem": "cmake-ninja",
"config-opts": [ "-DCMARK_TESTS=OFF" ],
"sources": [
{
"type": "git",
@@ -133,6 +140,7 @@
{
"name": "qcoro",
"buildsystem": "cmake-ninja",
"config-opts": [ "-DQCORO_BUILD_EXAMPLES=OFF", "-DBUILD_TESTING=OFF" ],
"sources": [
{
"type": "archive",

3
.gitignore vendored
View File

@@ -1,4 +1,4 @@
build
build*
.clang-format
.DS_Store
.kdev4/
@@ -11,3 +11,4 @@ kate.project.ctags.*
.flatpak-builder/
.idea/
cmake-build-*
src/res.generated.qrc

View File

@@ -2,13 +2,12 @@
# SPDX-License-Identifier: CC0-1.0
include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/reuse-lint.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android-qt6.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows-qt6.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
# - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd-qt6.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/flatpak.yml
- project: sysadmin/ci-utilities
file:
- /gitlab-templates/reuse-lint.yml
- /gitlab-templates/android-qt6.yml
- /gitlab-templates/linux-qt6.yml
- /gitlab-templates/windows-qt6.yml
- /gitlab-templates/freebsd-qt6.yml
- /gitlab-templates/flatpak.yml
- /gitlab-templates/craft-android-qt6-apks.yml

View File

@@ -2,35 +2,7 @@
# SPDX-License-Identifier: BSD-2-Clause
Dependencies:
- 'on': ['Linux/Qt5', 'Android/Qt5', 'FreeBSD/Qt5', 'Windows/Qt5']
'require':
'frameworks/extra-cmake-modules': '@stable'
'frameworks/kcoreaddons': '@stable'
'frameworks/kirigami': '@stable'
'frameworks/ki18n': '@stable'
'frameworks/kconfig': '@stable'
'frameworks/syntax-highlighting': '@stable'
'frameworks/kitemmodels': '@stable'
'frameworks/kquickcharts': '@stable'
'frameworks/knotifications': '@stable'
'libraries/kquickimageeditor': '@stable'
'frameworks/sonnet': '@stable'
'libraries/kirigami-addons': '@latest'
'third-party/libquotient': '@latest'
'third-party/qtkeychain': '@latest'
'third-party/cmark': '@latest'
'third-party/qcoro': '@latest'
- 'on': ['Windows/Qt5', 'Linux/Qt5', 'FreeBSD/Qt5']
'require':
'frameworks/qqc2-desktop-style': '@stable'
'frameworks/kio': '@stable'
'frameworks/kwindowsystem': '@stable'
'frameworks/kconfigwidgets': '@stable'
- 'on': ['Linux/Qt5', 'FreeBSD/Qt5']
'require':
'frameworks/kdbusaddons': '@stable'
- 'on': ['Linux/Qt6', 'Android/Qt6', 'FreeBSD/Qt6', 'Windows/Qt6']
- 'on': ['Linux', 'Android', 'FreeBSD', 'Windows']
'require':
'frameworks/extra-cmake-modules': '@latest-kf6'
'frameworks/kcoreaddons': '@latest-kf6'
@@ -41,22 +13,29 @@ Dependencies:
'frameworks/kitemmodels': '@latest-kf6'
'frameworks/kquickcharts': '@latest-kf6'
'frameworks/knotifications': '@latest-kf6'
'frameworks/kcolorscheme': '@latest-kf6'
'libraries/kquickimageeditor': '@latest-kf6'
'frameworks/sonnet': '@latest-kf6'
'frameworks/prison': '@latest-kf6'
'libraries/kirigami-addons': '@latest-kf6'
'third-party/libquotient': '@latest'
'third-party/qtkeychain': '@latest'
'third-party/cmark': '@latest'
'third-party/qcoro': '@latest'
- 'on': ['Windows/Qt6', 'Linux/Qt6', 'FreeBSD/Qt6']
- 'on': ['Windows', 'Linux', 'FreeBSD']
'require':
'frameworks/qqc2-desktop-style': '@latest-kf6'
'frameworks/kio': '@latest-kf6'
'frameworks/kwindowsystem': '@latest-kf6'
'frameworks/kconfigwidgets': '@latest-kf6'
- 'on': ['Linux/Qt6', 'FreeBSD/Qt6']
'frameworks/kstatusnotifieritem': '@latest-kf6'
- 'on': ['Linux', 'FreeBSD']
'require':
'frameworks/kdbusaddons': '@latest-kf6'
- 'on': ['Linux']
'require':
'sdk/selenium-webdriver-at-spi': '@latest-kf6'
Options:
require-passing-tests-on: [ 'Linux/Qt5', 'FreeBSD', 'Windows' ]
per-test-timeout: 90
require-passing-tests-on: [ '@all' ]

View File

@@ -34,10 +34,18 @@ Files: src/neochat.notifyrc
Copyright: 2020 Tobias Fella <tobias.fella@kde.org>
License: BSD-2-Clause
Files: src/qml/Component/confetti.png src/qml/Component/glowdot.png
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

View File

@@ -7,18 +7,15 @@
cmake_minimum_required(VERSION 3.16)
# KDE Applications version, managed by release script.
set(RELEASE_SERVICE_VERSION_MAJOR "23")
set(RELEASE_SERVICE_VERSION_MINOR "07")
set(RELEASE_SERVICE_VERSION_MICRO "70")
set(RELEASE_SERVICE_VERSION_MAJOR "24")
set(RELEASE_SERVICE_VERSION_MINOR "01")
set(RELEASE_SERVICE_VERSION_MICRO "90")
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
set(KF_MIN_VERSION "5.91.0")
set(QT_MIN_VERSION "5.15.2")
if (ANDROID)
set(QT_MIN_VERSION "5.15.8")
endif()
set(KF_MIN_VERSION "5.240.0")
set(QT_MIN_VERSION "6.5")
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
@@ -27,7 +24,7 @@ set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(KDE_COMPILERSETTINGS_LEVEL 5.84)
set(KDE_COMPILERSETTINGS_LEVEL 5.105)
include(FeatureSummary)
include(ECMSetupVersion)
@@ -39,6 +36,8 @@ include(KDECompilerSettings NO_POLICY_SCOPE)
include(ECMAddAppIcon)
include(KDEGitCommitHooks)
include(ECMCheckOutboundLicense)
include(ECMQtDeclareLoggingCategory)
include(ECMAddAndroidApk)
if (NOT ANDROID)
include(KDEClangFormat)
endif()
@@ -47,32 +46,28 @@ if(NEOCHAT_FLATPAK)
include(cmake/Flatpak.cmake)
endif()
set(QUOTIENT_FORCE_NAMESPACED_INCLUDES TRUE)
ecm_setup_version(${PROJECT_VERSION}
VARIABLE_PREFIX NEOCHAT
VERSION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/neochat-version.h
)
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} NO_MODULE COMPONENTS Core Quick Gui QuickControls2 Multimedia Svg)
set_package_properties(Qt${QT_MAJOR_VERSION} PROPERTIES
find_package(Qt6 ${QT_MIN_VERSION} NO_MODULE COMPONENTS Core Quick Gui QuickControls2 Multimedia Svg WebView)
set_package_properties(Qt6 PROPERTIES
TYPE REQUIRED
PURPOSE "Basic application components"
)
find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} COMPONENTS Kirigami2 I18n Notifications Config CoreAddons Sonnet ItemModels)
set_package_properties(KF${QT_MAJOR_VERSION} PROPERTIES
find_package(KF6 ${KF_MIN_VERSION} COMPONENTS Kirigami I18n Notifications Config CoreAddons Sonnet ItemModels ColorScheme)
set_package_properties(KF6 PROPERTIES
TYPE REQUIRED
PURPOSE "Basic application components"
)
set_package_properties(KF${QT_MAJOR_VERSION}Kirigami2 PROPERTIES
TYPE REQUIRED
PURPOSE "Kirigami application UI framework"
)
find_package(KF${QT_MAJOR_VERSION}KirigamiAddons 0.7.2 REQUIRED)
find_package(Qt${QT_MAJOR_VERSION}Keychain)
set_package_properties(Qt${QT_MAJOR_VERSION}Keychain PROPERTIES
set_package_properties(KF6Kirigami PROPERTIES
TYPE REQUIRED
PURPOSE "Secure storage of account secrets"
PURPOSE "Kirigami application UI framework"
)
find_package(KF6KirigamiAddons 0.7.2 REQUIRED)
if(ANDROID)
find_package(OpenSSL)
@@ -81,26 +76,37 @@ if(ANDROID)
PURPOSE "Encrypted communications"
)
else()
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} COMPONENTS Widgets)
find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle ConfigWidgets KIO WindowSystem)
set_package_properties(KF${QT_MAJOR_VERSION}QQC2DesktopStyle PROPERTIES
find_package(Qt6 ${QT_MIN_VERSION} COMPONENTS Widgets)
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle KIO WindowSystem StatusNotifierItem)
set_package_properties(KF6QQC2DesktopStyle PROPERTIES
TYPE RUNTIME
)
ecm_find_qmlmodule(org.kde.syntaxhighlighting 1.0)
find_package(ICU 61.0 COMPONENTS uc)
set_package_properties(ICU PROPERTIES
TYPE REQUIRED
PURPOSE "Unicode library"
)
endif()
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
find_package(KF${QT_MAJOR_VERSION}DBusAddons ${KF_MIN_VERSION} REQUIRED)
find_package(KF6DBusAddons ${KF_MIN_VERSION} REQUIRED)
endif()
find_package(Quotient 0.6)
set_package_properties(Quotient PROPERTIES
find_package(QuotientQt6 0.7)
set_package_properties(QuotientQt6 PROPERTIES
TYPE REQUIRED
DESCRIPTION "Qt wrapper around Matrix API"
URL "https://github.com/quotient-im/libQuotient/"
PURPOSE "Talk with matrix server"
)
if (NOT TARGET Olm::Olm)
message(FATAL_ERROR "NeoChat requires Quotient with the E2EE feature enabled")
endif()
find_package(cmark)
set_package_properties(cmark PROPERTIES
TYPE REQUIRED
@@ -112,6 +118,8 @@ set_package_properties(cmark PROPERTIES
ecm_find_qmlmodule(org.kde.kquickimageeditor 1.0)
ecm_find_qmlmodule(org.kde.kitemmodels 1.0)
ecm_find_qmlmodule(org.kde.quickcharts 1.0)
ecm_find_qmlmodule(QtLocation)
ecm_find_qmlmodule(org.kde.prison)
find_package(KQuickImageEditor COMPONENTS)
set_package_properties(KQuickImageEditor PROPERTIES
@@ -121,19 +129,22 @@ set_package_properties(KQuickImageEditor PROPERTIES
PURPOSE "Add image editing capability to image attachments"
)
find_package(QCoro${QT_MAJOR_VERSION} 0.4 COMPONENTS Core REQUIRED)
find_package(QCoro6 0.4 COMPONENTS Core Network REQUIRED)
qcoro_enable_coroutines()
find_package(KF${QT_MAJOR_VERSION}DocTools ${KF_MIN_VERSION})
set_package_properties(KF${QT_MAJOR_VERSION}DocTools PROPERTIES DESCRIPTION
find_package(KF6DocTools ${KF_MIN_VERSION})
set_package_properties(KF6DocTools PROPERTIES DESCRIPTION
"Tools to generate documentation"
TYPE OPTIONAL
)
if(NOT Quotient_VERSION_MINOR GREATER 6)
cmake_policy(SET CMP0063 OLD)
endif()
find_package(KUnifiedPush QUIET)
set_package_properties(KUnifiedPush PROPERTIES
TYPE OPTIONAL
PURPOSE "Push notification support"
URL "https://invent.kde.org/libraries/kunifiedpush"
)
if(ANDROID)
find_package(Sqlite3)
@@ -150,12 +161,14 @@ install(FILES org.kde.neochat.tray.svg DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/h
add_definitions(-DQT_NO_FOREACH)
add_subdirectory(src)
if (BUILD_TESTING AND Quotient_VERSION_MINOR GREATER 6)
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} NO_MODULE COMPONENTS Test)
if (BUILD_TESTING)
find_package(Qt6 ${QT_MIN_VERSION} NO_MODULE COMPONENTS Test)
add_subdirectory(autotests)
add_subdirectory(appiumtests)
endif()
if(KF${QT_MAJOR_VERSION}DocTools_FOUND)
if(KF6DocTools_FOUND)
kdoctools_install(po)
add_subdirectory(doc)
endif()
@@ -173,3 +186,9 @@ file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h *.qml)
# Fixes the test by excluding this directory
list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX [[_(install|build)/.*]])
ecm_check_outbound_license(LICENSES GPL-3.0-only FILES ${ALL_SOURCE_FILES})
ecm_qt_install_logging_categories(
EXPORT NEOCHAT
FILE neochat.categories
DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}
)

101
README.md
View File

@@ -1,24 +1,52 @@
<!--
SPDX-FileCopyrightText: 2020-2021 Carl Schwan <carlschwan@kde.org>
SPDX-FileCopyrightText: 2020-2021 Tobias Fella <tobias.fella@kde.org>
SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
SPDX-License-Identifier: CC0-1.0
-->
# NeoChat
NeoChat is a client for Matrix, the decentralized communication protocol for instant
messaging. It is a fork of Spectral, using KDE frameworks, most notably Kirigami,
KConfig and KI18n.
A Qt/QML based Matrix client.
<a href='https://matrix.org'><img src='https://matrix.org/docs/legacy/made-for-matrix.png' alt='Made for Matrix' height=64 target=_blank /></a>
<a href='https://flathub.org/apps/details/org.kde.neochat'><img width='190px' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-i-en.png'/></a>
<a href='https://snapcraft.io/neochat'><img width='190px' alt='Download on the Snap Store' src='https://snapcraft.io/static/images/badges/en/snap-store-black.svg'/></a>
## Introduction
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)
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
Qt-based SDK for the [Matrix Protocol](https://spec.matrix.org/).
![Timeline](https://cdn.kde.org/screenshots/neochat/application.png)
## 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
of VoIP, threads and some aspects of End-to-End Encryption are supported. There are a few other smaller omissions due to the fact that the Matrix spec is constantly
evolving but the aim remains to provide eventual support for the entire spec.
Due to the nature of the Matrix specification development NeoChat also supports numerous unstable features. Currently these are:
- Polls - MSC3381
- Sticker Packs - MSC2545
- Location Events - MSC3488
## Get it
A stable release [is available](https://apps.kde.org/neochat) for download for Linux distributions.
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
from the [binary factory](https://binary-factory.kde.org/). There are unstable versions for the following platforms
in addition to stable ones:
- Android
- MacOS
- Windows
Along with the stable release, a Flatpak version is available for the nightly
version:
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
@@ -26,42 +54,53 @@ flatpak remote-add --if-not-exists kdeapps --from https://distribute.kde.org/kde
flatpak install kdeapps org.kde.neochat
```
A nightly build is also available for Android in the [KDE nightly F-Droid repo](https://community.kde.org/Android/FDroid)
and can also directly be downloaded from the [binary factory](https://binary-factory.kde.org/view/Android/job/NeoChat_Nightly_android-arm64/).
The unstable Android version can also be obtained from the [KDE nightly F-Droid repo](https://community.kde.org/Android/FDroid).
Nightly builds for [Windows](https://binary-factory.kde.org/job/NeoChat_Nightly_win64/), [MacOS](https://binary-factory.kde.org/job/NeoChat_Nightly_macos/) and [AppImages](https://binary-factory.kde.org/job/NeoChat_Nightly_appimage/) can also be downloaded from the [binary factory](https://binary-factory.kde.org/search/?q=neochat).
## Running
![Timeline](https://cdn.kde.org/screenshots/neochat/application.png)
Just start the executable in your preferred way - either from the build directory or from the installed location.
## Features
## Building NeoChat
* Sending messages
* Sending files from clipboard and filesystem
* Reply to message (right-click on a message to access menu)
* Start a private chat (but not encrypted)
* Show notifications, for the moment there is only a global switch
to disable it. We plan to implement the configuration part of the
specification soon.
* Autocompletion of usernames in chat
* Emoji picker
* Basic room setting page
* Send and accept invitations
* /rainbow <message> (very important)
* /me <message>
The best way to build KDE apps during development is to use `kdesrc-build`. The full instructions for this can be found on
the KDE community website's get involved section under [development](https://community.kde.org/Get_Involved/development). This
is primarily aimed at Linux development.
NeoChat is still missing a few features to become a full-featured
Matrix client (most notably encryption support and video chat support).
We welcome contributions in this direction.
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/).
## Tests
Tests are in the repository under [autotests](autotests) and should all pass for any contribution.
The project has CI setup to test new commits to the repository. All tests are expected to pass for a merge request to
be complete.
Current build status
![coverage](https://invent.kde.org/network/neochat/badges/master/pipeline.svg)
Currently the number of tests is limited, but growing. If anyone wants to help improve this, those
contributions would be especially welcome.
## Contributing
As is the case throughout the KDE ecosystem contributions are welcome from all. The code base is managed in the
[NeoChat repository](https://invent.kde.org/network/neochat) of the KDE Gitlab instance.
- [Code of Conduct](https://kde.org/code-of-conduct)
- [Report a Bug](https://bugs.kde.org/enter_bug.cgi?format=guided&product=neochat)
- [Feature Request](https://community.kde.org/Infrastructure/GitLab#Submitting_a_merge_request)
- [Create a Merge Request](https://community.kde.org/Infrastructure/GitLab#Submitting_a_merge_request)
- [Translation](https://community.kde.org/Get_Involved/translation)
## Contact
You can reach the maintainers at [#neochat:kde.org](https://matrix.to/#/#neochat:kde.org), if you are already on Matrix.
Development happens in http://invent.kde.org/network/neochat (not in GitHub).
The best place to reach the maintainers is on the KDE Matrix instance in the NeoChat channel, [#neochat:kde.org](https://go.kde.org/matrix/#/#neochat:kde.org). See [Matrix](https://community.kde.org/Matrix) for more details.
## Acknowledgement
This program utilizes [libQuotient](https://github.com/quotient-im/libQuotient/)
library and some C++ models from [Quaternion](https://github.com/quotient-im/Quaternion/).
This program 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/).

View File

@@ -9,9 +9,9 @@
android:versionName="${versionName}"
android:versionCode="${versionCode}"
android:installLocation="auto">
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="NeoChat" android:icon="@drawable/neochat">
<application android:name="org.qtproject.qt.android.bindings.QtApplication" android:label="NeoChat" android:icon="@drawable/neochat" android:usesCleartextTraffic="true">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation"
android:name="org.qtproject.qt5.android.bindings.QtActivity"
android:name="org.qtproject.qt.android.bindings.QtActivity"
android:label="NeoChat"
android:windowSoftInputMode="adjustResize"
android:launchMode="singleTop"

View File

@@ -12,7 +12,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.2'
classpath 'com.android.tools.build:gradle:7.4.1'
}
}
@@ -35,7 +35,7 @@ android {
* The following variables:
* - androidBuildToolsVersion,
* - androidCompileSdkVersion
* - qt5AndroidDir - holds the path to qt android files
* - qtAndroidDir - holds the path to qt android files
* needed to build any Qt application
* on Android.
*
@@ -44,16 +44,20 @@ android {
* Changing them manually might break the compilation!
*******************************************************/
compileSdkVersion androidCompileSdkVersion.toInteger()
compileSdkVersion androidCompileSdkVersion
buildToolsVersion androidBuildToolsVersion
ndkVersion androidNdkVersion
// Extract native libraries from the APK
packagingOptions.jniLibs.useLegacyPackaging true
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qt5AndroidDir + '/res', 'res']
java.srcDirs = [qtAndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qtAndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qtAndroidDir + '/res', 'res']
resources.srcDirs = ['src']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
@@ -88,6 +92,7 @@ android {
exclude 'lib/*/*_imageformats_qtga_*'
exclude 'lib/*/*_imageformats_qtiff_*'
exclude 'lib/*/*_qmltooling_*'
exclude 'lib/*/*_multimedia_ffmpeg*' // temporary qt6 android fix
}
aaptOptions {

View File

@@ -0,0 +1,28 @@
# SPDX-License-Identifier: BSD-3-Clause
# SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org>
if(NOT BUILD_TESTING OR NOT CMAKE_SYSTEM_NAME MATCHES "Linux")
return()
endif()
find_package(SeleniumWebDriverATSPI)
set_package_properties(SeleniumWebDriverATSPI PROPERTIES
DESCRIPTION "Server component for selenium tests using Linux accessibility infrastructure"
PURPOSE "Needed for GUI tests"
URL "https://invent.kde.org/sdk/selenium-webdriver-at-spi"
TYPE OPTIONAL
)
if(NOT SeleniumWebDriverATSPI_FOUND)
return()
endif()
add_test(
NAME logintest
COMMAND selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/logintest.py
)
add_test(
NAME openuserdetailstest
COMMAND selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/openuserdetailstest.py
)

View File

@@ -0,0 +1,3 @@
{
"next_batch": "batch1234"
}

View File

@@ -0,0 +1,50 @@
{
"next_batch": "batch1234",
"rooms": {
"join": {
"!room_id_1234: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": "!room_id_1234:localhost:1234",
"content": {
"avatar_url": "",
"displayname": "A Display Name",
"membership": "join",
"reason": "Nothing"
},
"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": "!room_id_1234: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
}
}
]
}
}
}
}
}

View File

@@ -0,0 +1,70 @@
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
import json
from flask import Flask, request, abort
import os
app = Flask(__name__)
@app.route("/_matrix/client/v3/login", methods=["GET"])
def login_get():
result = dict()
result["flows"] = [dict()]
result["flows"][0]["type"] = "m.login.password"
return result
@app.route("/_matrix/client/v3/account/whoami", methods=["GET"])
def whoami():
result = dict()
result["device_id"] = "device_id_1234"
result["user_id"] = "@user:localhost:1234"
return result
@app.route("/_matrix/client/v3/login", methods=["POST"])
def login_post():
data = request.get_json()
if data["identifier"]["user"] != "user" or data["password"] != "1234":
abort(403)
print(data)
result = dict()
result["access_token"] = "token_login"
result["device_id"] = "device_1234"
result["user_id"] = "@user:localhost:1234"
return result
def load_json(name):
parts = __file__.split("/")
parts.pop()
datadir = "/".join(parts)
return json.loads(open(f"{datadir}/data/{name}.json").read())
@app.route("/_matrix/client/r0/sync")
def sync():
result = load_json("sync_response_no_rooms") if ("login" in request.headers.get("Authorization")) else load_json("sync_response_rooms")
return result
@app.route("/.well-known/matrix/client")
def well_known():
reply = dict()
reply["m.homeserver"] = dict()
reply["m.homeserver"]["base_url"] = "https://localhost:1234"
return reply
@app.route("/_matrix/client/v3/profile/<id>")
def profile(id):
reply = dict()
reply["avatar_url"] = "mxc://localhost:1234/asdf1234"
reply["displayname"] = "User123"
return reply
@app.route("/_matrix/client/v3/keys/upload", methods=["POST"])
def upload_keys():
reply = dict()
return reply
if __name__ == "__main__":
app.run(ssl_context='adhoc', port=1234)

51
appiumtests/logintest.py Executable file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sitter@kde.org>
# SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
import os
import subprocess
import sys
import unittest
from appium import webdriver
from appium.options.common.base import AppiumOptions
from appium.webdriver.common.appiumby import AppiumBy
class LoginTest(unittest.TestCase):
mockServerProcess: subprocess.Popen
@classmethod
def setUpClass(cls):
options = AppiumOptions()
options.set_capability("app", "neochat --ignore-ssl-errors")
cls.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', options=options)
cls.mockServerProcess = subprocess.Popen([sys.executable, os.path.join(os.path.dirname(__file__), "login-server.py")])
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_login(self):
self.driver.find_element(by=AppiumBy.NAME, value="Login").click()
self.driver.find_element(by=AppiumBy.NAME, value="Matrix ID").send_keys("@user:localhost:1234")
self.driver.find_element(by=AppiumBy.NAME, value="Continue").click()
self.driver.find_element(by=AppiumBy.NAME, value="Password").send_keys("1234")
self.driver.find_element(by=AppiumBy.NAME, value="Login").click()
self.driver.find_element(by=AppiumBy.NAME, value="Join some rooms to get started").click()
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,48 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sitter@kde.org>
# SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
import os
import subprocess
import sys
import unittest
from appium import webdriver
from appium.options.common.base import AppiumOptions
from appium.webdriver.common.appiumby import AppiumBy
class OpenUserDetailsTest(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_open_sheet(self):
self.driver.find_element(by=AppiumBy.NAME, value="@user: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="Account Details")
if __name__ == '__main__':
unittest.main()

View File

@@ -3,9 +3,11 @@
enable_testing()
add_definitions(-DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" )
ecm_add_test(
neochatroomtest.cpp
LINK_LIBRARIES neochat Qt::Test Quotient
LINK_LIBRARIES neochat Qt::Test
TEST_NAME neochatroomtest
)
@@ -14,3 +16,69 @@ ecm_add_test(
LINK_LIBRARIES neochat Qt::Test
TEST_NAME texthandlertest
)
ecm_add_test(
delegatesizehelpertest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME delegatesizehelpertest
)
ecm_add_test(
mediasizehelpertest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME mediasizehelpertest
)
ecm_add_test(
eventhandlertest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME eventhandlertest
)
ecm_add_test(
chatbarcachetest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME chatbarcachetest
)
ecm_add_test(
chatdocumenthandlertest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME chatdocumenthandlertest
)
ecm_add_test(
messageeventmodeltest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME messageeventmodeltest
)
ecm_add_test(
actionshandlertest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME actionshandlertest
)
ecm_add_test(
windowcontrollertest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME windowcontrollertest
)
ecm_add_test(
pollhandlertest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME pollhandlertest
)
ecm_add_test(
reactionmodeltest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME reactionmodeltest
)
ecm_add_test(
linkpreviewertest.cpp
LINK_LIBRARIES neochat Qt::Test
TEST_NAME linkpreviewertest
)

View File

@@ -0,0 +1,43 @@
// 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"

View File

@@ -0,0 +1,141 @@
// 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 <QJsonDocument>
#include <QJsonObject>
#include <QObject>
#include <QTest>
#include <Quotient/syncdata.h>
#include <qtestcase.h>
#include "chatbarcache.h"
#include "neochatroom.h"
#include "testutils.h"
using namespace Quotient;
class ChatBarCacheTest : public QObject
{
Q_OBJECT
private:
Connection *connection = nullptr;
TestUtils::TestRoom *room = nullptr;
private Q_SLOTS:
void initTestCase();
void empty();
void noRoom();
void badParent();
void reply();
void edit();
void attachment();
};
void ChatBarCacheTest::initTestCase()
{
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-min-sync.json"));
}
void ChatBarCacheTest::empty()
{
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
QCOMPARE(chatBarCache->text(), QString());
QCOMPARE(chatBarCache->isReplying(), false);
QCOMPARE(chatBarCache->replyId(), QString());
QCOMPARE(chatBarCache->isEditing(), false);
QCOMPARE(chatBarCache->editId(), QString());
QCOMPARE(chatBarCache->relationUser(), room->getUser(nullptr));
QCOMPARE(chatBarCache->relationMessage(), QString());
QCOMPARE(chatBarCache->attachmentPath(), QString());
}
void ChatBarCacheTest::noRoom()
{
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache());
chatBarCache->setReplyId(QLatin1String("$153456789:example.org"));
// These should return empty even though a reply ID has been set because the
// ChatBarCache has no parent.
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.");
QCOMPARE(chatBarCache->relationUser(), QVariantMap());
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation.");
QCOMPARE(chatBarCache->relationMessage(), QString());
}
void ChatBarCacheTest::badParent()
{
QScopedPointer<QObject> badParent(new QObject());
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(badParent.get()));
chatBarCache->setReplyId(QLatin1String("$153456789:example.org"));
// These should return empty even though a reply ID has been set because the
// ChatBarCache has no parent.
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.");
QCOMPARE(chatBarCache->relationUser(), QVariantMap());
QTest::ignoreMessage(QtWarningMsg, "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation.");
QCOMPARE(chatBarCache->relationMessage(), QString());
}
void ChatBarCacheTest::reply()
{
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
chatBarCache->setText(QLatin1String("some text"));
chatBarCache->setAttachmentPath(QLatin1String("some/path"));
chatBarCache->setReplyId(QLatin1String("$153456789:example.org"));
QCOMPARE(chatBarCache->text(), QLatin1String("some text"));
QCOMPARE(chatBarCache->isReplying(), true);
QCOMPARE(chatBarCache->replyId(), QLatin1String("$153456789:example.org"));
QCOMPARE(chatBarCache->isEditing(), false);
QCOMPARE(chatBarCache->editId(), QString());
QCOMPARE(chatBarCache->relationUser(), room->getUser(room->user(QLatin1String("@example:example.org"))));
QCOMPARE(chatBarCache->relationMessage(), QLatin1String("This is an example\ntext message"));
QCOMPARE(chatBarCache->attachmentPath(), QString());
}
void ChatBarCacheTest::edit()
{
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"));
QCOMPARE(chatBarCache->isReplying(), false);
QCOMPARE(chatBarCache->replyId(), QString());
QCOMPARE(chatBarCache->isEditing(), true);
QCOMPARE(chatBarCache->editId(), QLatin1String("$153456789:example.org"));
QCOMPARE(chatBarCache->relationUser(), room->getUser(room->user(QLatin1String("@example:example.org"))));
QCOMPARE(chatBarCache->relationMessage(), QLatin1String("This is an example\ntext message"));
QCOMPARE(chatBarCache->attachmentPath(), QString());
}
void ChatBarCacheTest::attachment()
{
QScopedPointer<ChatBarCache> chatBarCache(new ChatBarCache(room));
chatBarCache->setText(QLatin1String("some text"));
chatBarCache->setEditId(QLatin1String("$153456789:example.org"));
chatBarCache->setAttachmentPath(QLatin1String("some/path"));
QCOMPARE(chatBarCache->text(), QLatin1String("some text"));
QCOMPARE(chatBarCache->isReplying(), false);
QCOMPARE(chatBarCache->replyId(), QString());
QCOMPARE(chatBarCache->isEditing(), false);
QCOMPARE(chatBarCache->editId(), QString());
QCOMPARE(chatBarCache->relationUser(), room->getUser(nullptr));
QCOMPARE(chatBarCache->relationMessage(), QString());
QCOMPARE(chatBarCache->attachmentPath(), QLatin1String("some/path"));
}
QTEST_MAIN(ChatBarCacheTest)
#include "chatbarcachetest.moc"

View File

@@ -0,0 +1,36 @@
// 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 <QObject>
#include <QTest>
#include "chatdocumenthandler.h"
#include "neochatconfig.h"
class ChatDocumentHandlerTest : public QObject
{
Q_OBJECT
private:
ChatDocumentHandler emptyHandler;
private Q_SLOTS:
void initTestCase();
void nullComplete();
};
void ChatDocumentHandlerTest::initTestCase()
{
// HACK: this is to stop KStatusNotifierItem SEGFAULTING on cleanup.
NeoChatConfig::self()->setSystemTray(false);
}
void ChatDocumentHandlerTest::nullComplete()
{
QTest::ignoreMessage(QtWarningMsg, "complete called with m_document set to nullptr.");
emptyHandler.complete(0);
}
QTEST_MAIN(ChatDocumentHandlerTest)
#include "chatdocumenthandlertest.moc"

View File

@@ -0,0 +1,410 @@
{
"account_data": {
"events": [
{
"content": {
"tags": {
"u.work": {
"order": 0.9
}
}
},
"type": "m.tag"
},
{
"content": {
"custom_config_key": "custom_config_value"
},
"type": "org.example.custom.room.config"
}
]
},
"ephemeral": {
"events": [
{
"content": {
"user_ids": [
"@alice:matrix.org",
"@bob:example.com"
]
},
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"type": "m.typing"
},
{
"content": {
"$153456789:example.org": {
"m.read": {
"@alice:matrix.org": {
"ts": 1436451550453
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@bob:example.com": {
"ts": 1436451550453
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@tim:example.com": {
"ts": 1436451550454
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@jeff:example.com": {
"ts": 1436451550455
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@tina:example.com": {
"ts": 1436451550456
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@sally:example.com": {
"ts": 1436451550457
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@fred:example.com": {
"ts": 1436451550458
}
}
}
},
"type": "m.receipt"
}
]
},
"state": {
"events": [
{
"content": {
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
"displayname": "Alice Margatroid",
"membership": "join",
"reason": "Looking for support"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "@alice:example.org",
"type": "m.room.member",
"unsigned": {
"age": 1234
}
},
{
"content": {
"displayname": "Look\nat\nme\nI\nput\nnewlines\nin\nmy\ndisplay name",
"membership": "join"
},
"event_id": "$143273582443PhrSh:example.org",
"origin_server_ts": 1432735824659,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@newline:example.org",
"state_key": "@newline:example.org",
"type": "m.room.member",
"unsigned": {
"age": 12345
}
}
]
},
"summary": {
"m.heroes": [
"@alice:example.com",
"@bob:example.com"
],
"m.invited_member_count": 0,
"m.joined_member_count": 2
},
"timeline": {
"events": [
{
"content": {
"body": "This is an example\ntext message",
"format": "org.matrix.custom.html",
"formatted_body": "<b>This is an example<br>text message</b>",
"msgtype": "m.text"
},
"event_id": "$153456789:example.org",
"origin_server_ts": 1432735824654,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1232
}
},
{
"content": {
"avatar_url": "mxc://kde.org/123456",
"displayname": "after",
"membership": "join"
},
"origin_server_ts": 1690651134736,
"sender": "@example:example.org",
"state_key": "@example:example.org",
"type": "m.room.member",
"unsigned": {
"replaces_state": "$1234567890:example.org",
"prev_content": {
"avatar_url": "mxc://kde.org/12345",
"displayname": "before",
"membership": "join"
},
"prev_sender": "@example:example.orgg",
"age": 1234
},
"event_id": "$143273583553PhrSn:example.org",
"room_id": "!jEsUZKDJdhlrceRyVU:example.org"
},
{
"content": {
"body": "This is a highlight @bob:kde.org and this is a link https://kde.org",
"format": "org.matrix.custom.html",
"msgtype": "m.text"
},
"event_id": "$1532735824654:example.org",
"origin_server_ts": 1532735824654,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1233
}
},
{
"content": {
"m.relates_to": {
"event_id": "$153456789:example.org",
"key": "👍",
"rel_type": "m.annotation"
}
},
"origin_server_ts": 1690322545182,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@alice:matrix.org",
"type": "m.reaction",
"unsigned": {
"age": 390159120
},
"event_id": "$163456789:example.org",
"age": 390159120
},
{
"age": 4926305285,
"content": {
"body": "video caption",
"filename": "video.mp4",
"info": {
"duration": 10,
"h": 1080,
"mimetype": "video/mp4",
"size": 62650636,
"w": 1920,
"thumbnail_info": {
"h": 450,
"mimetype": "image/jpeg",
"size": 382249,
"w": 800
},
"thumbnail_url": "mxc://kde.org/2234567"
},
"msgtype": "m.video",
"url": "mxc://kde.org/1234567"
},
"event_id": "$263456789:example.org",
"origin_server_ts": 1685793783330,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 4926305285
},
"user_id": "@example:example.org"
},
{
"content": {
"body": "> <@example:example.org> This is an example\ntext message\n\nreply",
"format": "org.matrix.custom.html",
"formatted_body": "<mx-reply><blockquote><a href=\"https://matrix.to/#/!jEsUZKDJdhlrceRyVU:example.org/$153456789:example.org?via=kde.org&via=matrix.org\">In reply to</a> <a href=\"https://matrix.to/#/@example:example.org\">@example:example.org</a><br><b>This is an example<br>text message</b></blockquote></mx-reply>reply",
"m.relates_to": {
"m.in_reply_to": {
"event_id": "$153456789:example.org"
}
},
"msgtype": "m.text"
},
"origin_server_ts": 1690725965572,
"sender": "@alice:matrix.org",
"type": "m.room.message",
"unsigned": {
"age": 98
},
"event_id": "$154456789:example.org",
"room_id": "!jEsUZKDJdhlrceRyVU:example.org"
},
{
"content": {
"body": "> <@example:example.org> video caption\n\nreply",
"m.relates_to": {
"m.in_reply_to": {
"event_id": "$263456789:example.org"
}
},
"msgtype": "m.text"
},
"origin_server_ts": 1690725965573,
"sender": "@alice:matrix.org",
"type": "m.room.message",
"unsigned": {
"age": 98
},
"event_id": "$154456799:example.org",
"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": "$1544567999:example.org",
"origin_server_ts": 1690821582876,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 96845207
}
},
{
"content": {
"body": "Thread root",
"format": "org.matrix.custom.html",
"msgtype": "m.text"
},
"event_id": "$threadroot:example.org",
"origin_server_ts": 1690821582879,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1232
}
},
{
"content": {
"body": "Thread message 1",
"msgtype": "m.text",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$threadroot:example.org",
"m.in_reply_to": {
"event_id": "$threadroot:example.org"
},
"is_falling_back": true
}
},
"event_id": "$threadmessage1:example.org",
"origin_server_ts": 1690821582890,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1238
}
},
{
"content": {
"body": "Thread message 2",
"msgtype": "m.text",
"m.relates_to": {
"rel_type": "m.thread",
"event_id": "$threadroot:example.org",
"m.in_reply_to": {
"event_id": "$threadmessage1:example.org"
},
"is_falling_back": true
}
},
"event_id": "$threadmessage2:example.org",
"origin_server_ts": 1690821582890,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1238
}
},
{
"content": {
"body": "A message from someone who thought it was a good idea to put newlines in their display name.",
"msgtype": "m.text"
},
"event_id": "$153456889:example.org",
"origin_server_ts": 14327358246589,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@newline:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1230
}
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
}

View File

@@ -0,0 +1,14 @@
{
"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
}
}

View File

@@ -0,0 +1,14 @@
{
"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
}
}

View File

@@ -0,0 +1,14 @@
{
"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
}
}

View File

@@ -0,0 +1,24 @@
{
"timeline": {
"events": [
{
"content": {
"body": "https://kde.org",
"format": "org.matrix.custom.html",
"formatted_body": "https://kde.org",
"msgtype": "m.text"
},
"origin_server_ts": 1704648567967,
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 112
},
"event_id": "$validlink:example.org",
"room_id": "!test:example.org"
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
}

View File

@@ -0,0 +1,35 @@
{
"timeline": {
"events": [
{
"content": {
"body": "* ",
"format": "org.matrix.custom.html",
"formatted_body": "no link",
"m.new_content": {
"body": "",
"format": "org.matrix.custom.html",
"formatted_body": "no link",
"msgtype": "m.text"
},
"m.relates_to": {
"event_id": "$validlink:example.org",
"rel_type": "m.replace"
},
"msgtype": "m.text",
"type": "m.room.message"
},
"origin_server_ts": 1704648614969,
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 65
},
"event_id": "$nolink:example.org",
"room_id": "!test:example.org"
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
}

View File

@@ -0,0 +1,105 @@
{
"account_data": {
"events": [
{
"content": {
"tags": {
"u.work": {
"order": 0.9
}
}
},
"type": "m.tag"
},
{
"content": {
"custom_config_key": "custom_config_value"
},
"type": "org.example.custom.room.config"
}
]
},
"ephemeral": {
"events": [
{
"content": {
"user_ids": [
"@alice:matrix.org",
"@bob:example.com"
]
},
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"type": "m.typing"
}
]
},
"state": {
"events": [
{
"content": {
"displayname": "Example",
"membership": "join"
},
"event_id": "$exampleMember: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
}
}
]
},
"summary": {
"m.heroes": [
"@example:example.org"
],
"m.invited_member_count": 0,
"m.joined_member_count": 2
},
"timeline": {
"events": [
{
"content": {
"body": "This is an example\ntext message",
"format": "org.matrix.custom.html",
"formatted_body": "<b>This is an example<br>text message</b>",
"msgtype": "m.text"
},
"event_id": "$153456789:example.org",
"origin_server_ts": 1,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1232
}
},
{
"content": {
"displayname": "Example Changed",
"membership": "join"
},
"event_id": "$exampleMemberChnage:example.org",
"origin_server_ts": 2,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "@example:example.org",
"type": "m.room.member",
"unsigned": {
"replaces_state": "$exampleMember:example.org",
"prev_content": {
"displayname": "Example",
"membership": "join"
},
"prev_sender": "@example:example.org",
"age": 1234
}
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
}

View File

@@ -0,0 +1,87 @@
{
"account_data": {
"events": [
{
"content": {
"tags": {
"u.work": {
"order": 0.9
}
}
},
"type": "m.tag"
},
{
"content": {
"custom_config_key": "custom_config_value"
},
"type": "org.example.custom.room.config"
}
]
},
"ephemeral": {
"events": [
{
"content": {
"user_ids": [
"@alice:matrix.org",
"@bob:example.com"
]
},
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"type": "m.typing"
}
]
},
"state": {
"events": [
{
"content": {
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
"displayname": "Alice Margatroid",
"membership": "join",
"reason": "Looking for support"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "@alice:example.org",
"type": "m.room.member",
"unsigned": {
"age": 1234
}
}
]
},
"summary": {
"m.heroes": [
"@alice:example.com",
"@bob:example.com"
],
"m.invited_member_count": 0,
"m.joined_member_count": 2
},
"timeline": {
"events": [
{
"content": {
"body": "This is an example\ntext message",
"format": "org.matrix.custom.html",
"formatted_body": "<b>This is an example<br>text message</b>",
"msgtype": "m.text"
},
"event_id": "$153456789:example.org",
"origin_server_ts": 1432735824654,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1232
}
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
}

View File

@@ -0,0 +1,14 @@
{
"content": {
"body": "www.example.org 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
}
}

View File

@@ -0,0 +1,22 @@
{
"timeline": {
"events": [
{
"content": {
"body": "New plain message",
"msgtype": "m.text"
},
"event_id": "$pendingmerge:example.org",
"origin_server_ts": 123456,
"room_id":"#myroom:kde.org",
"sender":"@bob:kde.org",
"type":"m.room.message",
"unsigned": {
"transaction_id": "17017181543521"
}
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
}

View File

@@ -0,0 +1,38 @@
{
"timeline": {
"events": [
{
"content": {
"org.matrix.msc1767.text": "test\n1. option1\n2. option 2",
"org.matrix.msc3381.poll.start": {
"answers": [
{
"id": "option1",
"org.matrix.msc1767.text": "option1"
},
{
"id": "option2",
"org.matrix.msc1767.text": "option2"
}
],
"kind": "org.matrix.msc3381.poll.disclosed",
"max_selections": 1,
"question": {
"body": "test",
"msgtype": "m.text",
"org.matrix.msc1767.text": "test"
}
}
},
"event_id": "$153456789:example.org",
"origin_server_ts": 1432735824654,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "org.matrix.msc3381.poll.start",
"unsigned": {
"age": 1232
}
}
]
}
}

View File

@@ -0,0 +1,44 @@
{
"timeline": {
"events": [
{
"content": {
"m.relates_to": {
"event_id": "$153456789:example.org",
"key": "👍",
"rel_type": "m.annotation"
}
},
"origin_server_ts": 1690322545183,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@bob:example.org",
"type": "m.reaction",
"unsigned": {
"age": 390159121
},
"event_id": "$163456790:example.org",
"age": 390159121
},
{
"content": {
"m.relates_to": {
"event_id": "$153456789:example.org",
"key": "😆",
"rel_type": "m.annotation"
}
},
"origin_server_ts": 1690322545184,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@bob:example.org",
"type": "m.reaction",
"unsigned": {
"age": 390159122
},
"event_id": "$163456791:example.org",
"age": 390159122
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
}

View File

@@ -0,0 +1,204 @@
{
"account_data": {
"events": [
{
"content": {
"tags": {
"u.work": {
"order": 0.9
}
}
},
"type": "m.tag"
},
{
"content": {
"custom_config_key": "custom_config_value"
},
"type": "org.example.custom.room.config"
}
]
},
"ephemeral": {
"events": [
{
"content": {
"user_ids": [
"@alice:matrix.org",
"@bob:example.com"
]
},
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"type": "m.typing"
},
{
"content": {
"$153456789:example.org": {
"m.read": {
"@alice:matrix.org": {
"ts": 1436451550453
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@bob:example.com": {
"ts": 1436451550453
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@tim:example.com": {
"ts": 1436451550454
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@jeff:example.com": {
"ts": 1436451550455
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@tina:example.com": {
"ts": 1436451550456
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@sally:example.com": {
"ts": 1436451550457
}
}
}
},
"type": "m.receipt"
},
{
"content": {
"$1532735824654:example.org": {
"m.read": {
"@fred:example.com": {
"ts": 1436451550458
}
}
}
},
"type": "m.receipt"
}
]
},
"state": {
"events": [
{
"content": {
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
"displayname": "Alice Margatroid",
"membership": "join",
"reason": "Looking for support"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "@alice:example.org",
"type": "m.room.member",
"unsigned": {
"age": 1234
}
},
{
"content": {
"displayname": "Look\nat\nme\nI\nput\nnewlines\nin\nmy\ndisplay name",
"membership": "join"
},
"event_id": "$143273582443PhrSh:example.org",
"origin_server_ts": 1432735824659,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@newline:example.org",
"state_key": "@newline:example.org",
"type": "m.room.member",
"unsigned": {
"age": 12345
}
}
]
},
"summary": {
"m.heroes": [
"@alice:example.com",
"@bob:example.com"
],
"m.invited_member_count": 0,
"m.joined_member_count": 2
},
"timeline": {
"events": [
{
"content": {
"body": "This is an example\ntext message",
"format": "org.matrix.custom.html",
"formatted_body": "<b>This is an example<br>text message</b>",
"msgtype": "m.text"
},
"event_id": "$153456789:example.org",
"origin_server_ts": 1432735824654,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1232
}
},
{
"content": {
"m.relates_to": {
"event_id": "$153456789:example.org",
"key": "👍",
"rel_type": "m.annotation"
}
},
"origin_server_ts": 1690322545182,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@alice:matrix.org",
"type": "m.reaction",
"unsigned": {
"age": 390159120
},
"event_id": "$163456789:example.org",
"age": 390159120
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
}

View File

@@ -0,0 +1,124 @@
{
"account_data": {
"events": [
{
"content": {
"tags": {
"u.work": {
"order": 0.9
}
}
},
"type": "m.tag"
},
{
"content": {
"custom_config_key": "custom_config_value"
},
"type": "org.example.custom.room.config"
}
]
},
"ephemeral": {
"events": [
{
"content": {
"user_ids": [
"@alice:matrix.org",
"@bob:example.com"
]
},
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"type": "m.typing"
}
]
},
"state": {
"events": [
{
"content": {
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
"displayname": "Alice Margatroid",
"membership": "join",
"reason": "Looking for support"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "@alice:example.org",
"type": "m.room.member",
"unsigned": {
"age": 1234
}
}
]
},
"summary": {
"m.heroes": [
"@alice:example.com",
"@bob:example.com"
],
"m.invited_member_count": 0,
"m.joined_member_count": 2
},
"timeline": {
"events": [
{
"content": {
"body": "This is an **example** text message",
"format": "org.matrix.custom.html",
"formatted_body": "<b>This is an example text message</b>",
"msgtype": "m.text"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824654,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1232
}
},
{
"content": {
"body": "/me This is an emote.",
"format": "org.matrix.custom.html",
"formatted_body": "This is an emote.",
"msgtype": "m.emote"
},
"event_id": "$153273582443PhrSn:example.org",
"origin_server_ts": 1532735824654,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1231
}
},
{
"content": {
"body": "tested",
"msgtype": "m.text"
},
"event_id": "$zrCiBxBnqqTn0Z5FY78qSZAszno_w8nJJXzfBULG-3E",
"origin_server_ts": 1680948575928,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1747776,
"m.relations": {
"m.replace": {
"event_id": "$UX0PlpyI7vYO32iHMuuYEP7ECMh4sX3XLGiB2SwM4mQ",
"origin_server_ts": 1680948580992,
"sender": "@example:example.org"
}
}
}
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
}

View File

@@ -0,0 +1,14 @@
{
"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
}
}

View File

@@ -0,0 +1,14 @@
{
"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
}
}

View File

@@ -0,0 +1,16 @@
{
"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
}
}

View File

@@ -0,0 +1,156 @@
// 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 <QObject>
#include <QTest>
#include "delegatesizehelper.h"
class DelegateSizeHelperTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void risingPercentage_data();
void risingPercentage();
void fallingPercentage_data();
void fallingPercentage();
void equalPercentage_data();
void equalPercentage();
void equalBreakpoint_data();
void equalBreakpoint();
};
void DelegateSizeHelperTest::risingPercentage_data()
{
QTest::addColumn<qreal>("parentWidth");
QTest::addColumn<int>("currentPercentageWidth");
QTest::addColumn<qreal>("currentWidth");
QTest::newRow("zero") << qreal(0) << 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("two hundred") << qreal(200) << int(100) << qreal(200);
QTest::newRow("three hundred") << qreal(300) << int(100) << qreal(300);
}
void DelegateSizeHelperTest::risingPercentage()
{
QFETCH(qreal, parentWidth);
QFETCH(int, currentPercentageWidth);
QFETCH(qreal, currentWidth);
DelegateSizeHelper delegateSizeHelper;
delegateSizeHelper.setStartBreakpoint(100);
delegateSizeHelper.setEndBreakpoint(200);
delegateSizeHelper.setStartPercentWidth(0);
delegateSizeHelper.setEndPercentWidth(100);
delegateSizeHelper.setParentWidth(parentWidth);
QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth);
QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth);
}
void DelegateSizeHelperTest::fallingPercentage_data()
{
QTest::addColumn<qreal>("parentWidth");
QTest::addColumn<int>("currentPercentageWidth");
QTest::addColumn<qreal>("currentWidth");
QTest::newRow("zero") << qreal(0) << int(100) << qreal(0);
QTest::newRow("one hundred") << qreal(100) << int(100) << qreal(100);
QTest::newRow("one fifty") << qreal(150) << int(50) << qreal(75);
QTest::newRow("two hundred") << qreal(200) << int(0) << qreal(0);
QTest::newRow("three hundred") << qreal(300) << int(0) << qreal(0);
}
void DelegateSizeHelperTest::fallingPercentage()
{
QFETCH(qreal, parentWidth);
QFETCH(int, currentPercentageWidth);
QFETCH(qreal, currentWidth);
DelegateSizeHelper delegateSizeHelper;
delegateSizeHelper.setStartBreakpoint(100);
delegateSizeHelper.setEndBreakpoint(200);
delegateSizeHelper.setStartPercentWidth(100);
delegateSizeHelper.setEndPercentWidth(0);
delegateSizeHelper.setParentWidth(parentWidth);
QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth);
QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth);
}
void DelegateSizeHelperTest::equalPercentage_data()
{
QTest::addColumn<qreal>("parentWidth");
QTest::addColumn<int>("currentPercentageWidth");
QTest::addColumn<qreal>("currentWidth");
QTest::newRow("zero") << qreal(0) << int(50) << qreal(0);
QTest::newRow("one hundred") << qreal(100) << int(50) << qreal(50);
QTest::newRow("one fifty") << qreal(150) << int(50) << qreal(75);
QTest::newRow("two hundred") << qreal(200) << int(50) << qreal(100);
QTest::newRow("three hundred") << qreal(300) << int(50) << qreal(150);
}
void DelegateSizeHelperTest::equalPercentage()
{
QFETCH(qreal, parentWidth);
QFETCH(int, currentPercentageWidth);
QFETCH(qreal, currentWidth);
DelegateSizeHelper delegateSizeHelper;
delegateSizeHelper.setStartBreakpoint(100);
delegateSizeHelper.setEndBreakpoint(200);
delegateSizeHelper.setStartPercentWidth(50);
delegateSizeHelper.setEndPercentWidth(50);
delegateSizeHelper.setParentWidth(parentWidth);
QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth);
QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth);
}
void DelegateSizeHelperTest::equalBreakpoint_data()
{
QTest::addColumn<int>("startPercentageWidth");
QTest::addColumn<int>("endPercentageWidth");
QTest::addColumn<int>("currentPercentageWidth");
QTest::addColumn<qreal>("currentWidth");
QTest::newRow("start higher") << int(100) << int(0) << int(-1) << qreal(0);
QTest::newRow("equal") << int(50) << int(50) << int(50) << qreal(500);
QTest::newRow("end higher") << int(0) << int(100) << int(-1) << qreal(0);
}
/**
* We expect a default return except in the case where the the two percentages are
* equal as that case can be calculated without dividing by zero.
*/
void DelegateSizeHelperTest::equalBreakpoint()
{
QFETCH(int, startPercentageWidth);
QFETCH(int, endPercentageWidth);
QFETCH(int, currentPercentageWidth);
QFETCH(qreal, currentWidth);
DelegateSizeHelper delegateSizeHelper;
delegateSizeHelper.setStartBreakpoint(100);
delegateSizeHelper.setEndBreakpoint(100);
delegateSizeHelper.setStartPercentWidth(startPercentageWidth);
delegateSizeHelper.setEndPercentWidth(endPercentageWidth);
delegateSizeHelper.setParentWidth(1000);
QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth);
QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth);
}
QTEST_GUILESS_MAIN(DelegateSizeHelperTest)
#include "delegatesizehelpertest.moc"

View File

@@ -0,0 +1,661 @@
// 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 <QObject>
#include <QTest>
#include "eventhandler.h"
#include <KFormat>
#include <Quotient/connection.h>
#include <Quotient/quotient_common.h>
#include <Quotient/syncdata.h>
#include "enums/delegatetype.h"
#include "linkpreviewer.h"
#include "models/reactionmodel.h"
#include "neochatroom.h"
#include "utils.h"
#include "testutils.h"
using namespace Quotient;
class EventHandlerTest : public QObject
{
Q_OBJECT
private:
Connection *connection = nullptr;
TestUtils::TestRoom *room = nullptr;
EventHandler eventHandler;
EventHandler emptyHandler;
EventHandler noEventHandler;
private Q_SLOTS:
void initTestCase();
void nullSetEvent();
void eventId();
void nullEventId();
void delegateType_data();
void delegateType();
void nullDelegateType();
void author();
void nullAuthor();
void authorDisplayName();
void nullAuthorDisplayName();
void singleLineSidplayName();
void nullSingleLineDisplayName();
void time();
void nullTime();
void timeString();
void nullTimeString();
void highlighted();
void nullHighlighted();
void hidden();
void nullHidden();
void body();
void nullBody();
void genericBody_data();
void genericBody();
void nullGenericBody();
void subtitle();
void nullSubtitle();
void mediaInfo();
void nullMediaInfo();
void hasReply();
void nullHasReply();
void replyId();
void nullReplyId();
void replyDelegateType();
void nullReplyDelegateType();
void replyAuthor();
void nullReplyAuthor();
void replyBody();
void nullReplyBody();
void replyMediaInfo();
void nullReplyMediaInfo();
void thread();
void nullThread();
void location();
void nullLocation();
void readMarkers();
void nullReadMarkers();
void cleanup();
};
void EventHandlerTest::initTestCase()
{
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-eventhandler-sync.json"));
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()
{
auto event = room->messageEvents().at(1).get();
eventHandler.setEvent(event);
QCOMPARE(eventHandler.getAuthorDisplayName(), QStringLiteral("before"));
}
void EventHandlerTest::nullAuthorDisplayName()
{
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_room set to nullptr.");
QCOMPARE(emptyHandler.getAuthorDisplayName(), QString());
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_event set to nullptr.");
QCOMPARE(noEventHandler.getAuthorDisplayName(), QString());
}
void EventHandlerTest::singleLineSidplayName()
{
auto event = room->messageEvents().at(11).get();
eventHandler.setEvent(event);
QCOMPARE(eventHandler.singleLineAuthorDisplayname(), QStringLiteral("Look at me I put newlines in my display name"));
}
void EventHandlerTest::nullSingleLineDisplayName()
{
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_room set to nullptr.");
QCOMPARE(emptyHandler.singleLineAuthorDisplayname(), QString());
QTest::ignoreMessage(QtWarningMsg, "getAuthorDisplayName called with m_event set to nullptr.");
QCOMPARE(noEventHandler.singleLineAuthorDisplayname(), QString());
}
void EventHandlerTest::time()
{
auto event = room->messageEvents().at(0).get();
eventHandler.setEvent(event);
QCOMPARE(eventHandler.getTime(), QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC));
QCOMPARE(eventHandler.getTime(true, QDateTime::fromMSecsSinceEpoch(1234, Qt::UTC)), QDateTime::fromMSecsSinceEpoch(1234, Qt::UTC));
}
void EventHandlerTest::nullTime()
{
QTest::ignoreMessage(QtWarningMsg, "getTime called with m_event set to nullptr.");
QCOMPARE(noEventHandler.getTime(), QDateTime());
eventHandler.setEvent(room->messageEvents().at(0).get());
QTest::ignoreMessage(QtWarningMsg, "a value must be provided for lastUpdated for a pending event.");
QCOMPARE(eventHandler.getTime(true), QDateTime());
}
void EventHandlerTest::timeString()
{
auto event = room->messageEvents().at(0).get();
eventHandler.setEvent(event);
KFormat format;
QCOMPARE(eventHandler.getTimeString(false),
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC).toLocalTime().time(), QLocale::ShortFormat));
QCOMPARE(eventHandler.getTimeString(true),
format.formatRelativeDate(QDateTime::fromMSecsSinceEpoch(1432735824654, Qt::UTC).toLocalTime().date(), QLocale::ShortFormat));
QCOMPARE(eventHandler.getTimeString(false, QLocale::ShortFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
QLocale().toString(QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC).toLocalTime().time(), QLocale::ShortFormat));
QCOMPARE(eventHandler.getTimeString(true, QLocale::ShortFormat, true, QDateTime::fromMSecsSinceEpoch(1690699214545, Qt::UTC)),
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()
{
QTest::ignoreMessage(QtWarningMsg, "getTimeString called with m_event set to nullptr.");
QCOMPARE(noEventHandler.getTimeString(false), QString());
eventHandler.setEvent(room->messageEvents().at(0).get());
QTest::ignoreMessage(QtWarningMsg, "a value must be provided for lastUpdated for a pending event.");
QCOMPARE(eventHandler.getTimeString(false, QLocale::ShortFormat, true), QString());
}
void EventHandlerTest::highlighted()
{
auto event = room->messageEvents().at(2).get();
eventHandler.setEvent(event);
QCOMPARE(eventHandler.isHighlighted(), true);
event = room->messageEvents().at(0).get();
eventHandler.setEvent(event);
QCOMPARE(eventHandler.isHighlighted(), false);
}
void EventHandlerTest::nullHighlighted()
{
QTest::ignoreMessage(QtWarningMsg, "isHighlighted called with m_room set to nullptr.");
QCOMPARE(emptyHandler.isHighlighted(), false);
QTest::ignoreMessage(QtWarningMsg, "isHighlighted called with m_event set to nullptr.");
QCOMPARE(noEventHandler.isHighlighted(), false);
}
void EventHandlerTest::hidden()
{
auto event = room->messageEvents().at(3).get();
eventHandler.setEvent(event);
QCOMPARE(eventHandler.isHidden(), true);
event = room->messageEvents().at(0).get();
eventHandler.setEvent(event);
QCOMPARE(eventHandler.isHidden(), false);
}
void EventHandlerTest::nullHidden()
{
QTest::ignoreMessage(QtWarningMsg, "isHidden called with m_room set to nullptr.");
QCOMPARE(emptyHandler.isHidden(), false);
QTest::ignoreMessage(QtWarningMsg, "isHidden called with m_event set to nullptr.");
QCOMPARE(noEventHandler.isHidden(), false);
}
void EventHandlerTest::body()
{
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.getRichBody(true), QStringLiteral("<b>This is an example text message</b>"));
QCOMPARE(eventHandler.getPlainBody(), QStringLiteral("This is an example\ntext message"));
QCOMPARE(eventHandler.getPlainBody(true), QStringLiteral("This is an example text message"));
}
void EventHandlerTest::nullBody()
{
QTest::ignoreMessage(QtWarningMsg, "getRichBody called with m_event set to nullptr.");
QCOMPARE(noEventHandler.getRichBody(), QString());
QTest::ignoreMessage(QtWarningMsg, "getPlainBody called with m_event set to nullptr.");
QCOMPARE(noEventHandler.getPlainBody(), QString());
}
void EventHandlerTest::genericBody_data()
{
QTest::addColumn<int>("eventNum");
QTest::addColumn<QString>("output");
QTest::newRow("message") << 0 << QStringLiteral("sent a message");
QTest::newRow("member") << 1 << QStringLiteral("changed their display name and updated their avatar");
QTest::newRow("message 2") << 2 << QStringLiteral("sent a message");
QTest::newRow("reaction") << 3 << QStringLiteral("Unknown event");
QTest::newRow("video") << 4 << QStringLiteral("sent a message");
}
void EventHandlerTest::genericBody()
{
QFETCH(int, eventNum);
QFETCH(QString, output);
eventHandler.setEvent(room->messageEvents().at(eventNum).get());
QCOMPARE(eventHandler.getGenericBody(), output);
}
void EventHandlerTest::nullGenericBody()
{
QTest::ignoreMessage(QtWarningMsg, "getGenericBody called with m_event set to nullptr.");
QCOMPARE(noEventHandler.getGenericBody(), QString());
}
void EventHandlerTest::subtitle()
{
auto event = room->messageEvents().at(0).get();
eventHandler.setEvent(event);
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()
{
QTest::ignoreMessage(QtWarningMsg, "subtitleText called with m_event set to nullptr.");
QCOMPARE(noEventHandler.subtitleText(), QString());
}
void EventHandlerTest::mediaInfo()
{
auto event = room->messageEvents().at(4).get();
eventHandler.setEvent(event);
auto mediaInfo = eventHandler.getMediaInfo();
auto thumbnailInfo = mediaInfo["tempInfo"_ls].toMap();
QCOMPARE(mediaInfo["source"_ls], room->makeMediaUrl(event->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(event->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::nullMediaInfo()
{
QTest::ignoreMessage(QtWarningMsg, "getMediaInfo called with m_room set to nullptr.");
QCOMPARE(emptyHandler.getMediaInfo(), QVariantMap());
QTest::ignoreMessage(QtWarningMsg, "getMediaInfo called with m_event set to nullptr.");
QCOMPARE(noEventHandler.getMediaInfo(), 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()
{
auto event = room->messageEvents().at(5).get();
auto replyEvent = room->messageEvents().at(0).get();
auto replyAuthor = room->user(replyEvent->senderId());
eventHandler.setEvent(event);
auto eventHandlerReplyAuthor = eventHandler.getReplyAuthor();
QCOMPARE(eventHandlerReplyAuthor["isLocalUser"_ls], replyAuthor->id() == room->localUser()->id());
QCOMPARE(eventHandlerReplyAuthor["id"_ls], replyAuthor->id());
QCOMPARE(eventHandlerReplyAuthor["displayName"_ls], replyAuthor->displayname(room));
QCOMPARE(eventHandlerReplyAuthor["avatarSource"_ls], room->avatarForMember(replyAuthor));
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()
{
QTest::ignoreMessage(QtWarningMsg, "getReplyAuthor called with m_room set to nullptr.");
QCOMPARE(emptyHandler.getReplyAuthor(), QVariantMap());
QTest::ignoreMessage(QtWarningMsg, "getReplyAuthor called with m_event set to nullptr. Returning empty user.");
QCOMPARE(noEventHandler.getReplyAuthor(), room->getUser(nullptr));
}
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()
{
auto event = room->messageEvents().at(7).get();
eventHandler.setEvent(event);
QCOMPARE(eventHandler.getLatitude(), QStringLiteral("51.7035").toFloat());
QCOMPARE(eventHandler.getLongitude(), QStringLiteral("-1.14394").toFloat());
QCOMPARE(eventHandler.getLocationAssetType(), QStringLiteral("m.pin"));
}
void EventHandlerTest::nullLocation()
{
QTest::ignoreMessage(QtWarningMsg, "getLatitude called with m_event set to nullptr.");
QCOMPARE(emptyHandler.getLatitude(), -100.0);
QTest::ignoreMessage(QtWarningMsg, "getLongitude called with m_event set to nullptr.");
QCOMPARE(emptyHandler.getLongitude(), -200.0);
QTest::ignoreMessage(QtWarningMsg, "getLocationAssetType called with m_event set to nullptr.");
QCOMPARE(emptyHandler.getLocationAssetType(), 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)
#include "eventhandlertest.moc"

View File

@@ -0,0 +1,104 @@
// 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 <QObject>
#include <QTest>
#include "linkpreviewer.h"
#include <Quotient/events/roommessageevent.h>
#include <Quotient/quotient_common.h>
#include <Quotient/syncdata.h>
#include "utils.h"
#include "testutils.h"
using namespace Quotient;
class LinkPreviewerTest : public QObject
{
Q_OBJECT
private:
Connection *connection = nullptr;
TestUtils::TestRoom *room = nullptr;
private Q_SLOTS:
void initTestCase();
void linkPreviewsMatch_data();
void linkPreviewsMatch();
void linkPreviewsReject_data();
void linkPreviewsReject();
void editedLink();
};
void LinkPreviewerTest::initTestCase()
{
connection = Connection::makeMockConnection(QStringLiteral("@bob:example.org"));
room = new TestUtils::TestRoom(connection, QStringLiteral("!test:example.org"));
}
void LinkPreviewerTest::linkPreviewsMatch_data()
{
QTest::addColumn<QString>("eventSource");
QTest::addColumn<QUrl>("testOutputLink");
QTest::newRow("plainHttps") << QStringLiteral("test-validplainlink-event.json") << QUrl("https://kde.org"_ls);
QTest::newRow("richHttps") << QStringLiteral("test-validrichlink-event.json") << QUrl("https://kde.org"_ls);
QTest::newRow("plainWww") << QStringLiteral("test-validplainwwwlink-event.json") << QUrl("www.example.org"_ls);
QTest::newRow("multipleHttps") << QStringLiteral("test-multiplelink-event.json") << QUrl("www.example.org"_ls);
}
void LinkPreviewerTest::linkPreviewsMatch()
{
QFETCH(QString, eventSource);
QFETCH(QUrl, testOutputLink);
auto event = TestUtils::loadEventFromFile<RoomMessageEvent>(eventSource);
auto linkPreviewer = LinkPreviewer(room, event.get());
QCOMPARE(linkPreviewer.empty(), false);
QCOMPARE(linkPreviewer.url(), testOutputLink);
}
void LinkPreviewerTest::linkPreviewsReject_data()
{
QTest::addColumn<QString>("eventSource");
QTest::newRow("mxc") << QStringLiteral("test-invalidmxclink-event.json");
QTest::newRow("matrixTo") << QStringLiteral("test-invalidmatrixtolink-event.json");
QTest::newRow("noSpace") << QStringLiteral("test-invalidnospacelink-event.json");
}
void LinkPreviewerTest::linkPreviewsReject()
{
QFETCH(QString, eventSource);
auto event = TestUtils::loadEventFromFile<RoomMessageEvent>(eventSource);
auto linkPreviewer = LinkPreviewer(room, event.get());
QCOMPARE(linkPreviewer.empty(), true);
QCOMPARE(linkPreviewer.url(), QUrl());
}
void LinkPreviewerTest::editedLink()
{
room->syncNewEvents(QStringLiteral("test-linkpreviewerintial-sync.json"));
auto event = eventCast<const RoomMessageEvent>(room->messageEvents().at(0).get());
auto linkPreviewer = LinkPreviewer(room, event);
QCOMPARE(linkPreviewer.empty(), false);
QCOMPARE(linkPreviewer.url(), QUrl("https://kde.org"_ls));
room->syncNewEvents(QStringLiteral("test-linkpreviewerreplace-sync.json"));
QCOMPARE(linkPreviewer.empty(), true);
QCOMPARE(linkPreviewer.url(), QUrl());
}
QTEST_MAIN(LinkPreviewerTest)
#include "linkpreviewertest.moc"

View File

@@ -0,0 +1,72 @@
// 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 <QObject>
#include <QTest>
#include <qglobal.h>
#include <qtestcase.h>
#include <cmath>
#include "mediasizehelper.h"
#include "neochatconfig.h"
class MediaSizeHelperTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void uninitialized();
void limits_data();
void limits();
};
void MediaSizeHelperTest::uninitialized()
{
MediaSizeHelper mediasizehelper;
QCOMPARE(mediasizehelper.currentSize(), QSize(540, qRound(qreal(NeoChatConfig::self()->mediaMaxWidth()) / qreal(16.0) * qreal(9.0))));
}
void MediaSizeHelperTest::limits_data()
{
QTest::addColumn<qreal>("mediaWidth");
QTest::addColumn<qreal>("mediaHeight");
QTest::addColumn<qreal>("contentMaxWidth");
QTest::addColumn<qreal>("contentMaxHeight");
QTest::addColumn<QSize>("currentSize");
QTest::newRow("media smaller than content limits") << qreal(200) << qreal(150) << qreal(400) << qreal(900) << QSize(200, 150);
QTest::newRow("media smaller than max limits") << qreal(200) << qreal(150) << qreal(-1) << qreal(-1) << QSize(200, 150);
QTest::newRow("limit by max width") << qreal(600) << qreal(50) << qreal(-1) << qreal(-1) << QSize(540, qRound(qreal(540) / (qreal(600) / qreal(50))));
QTest::newRow("limit by max height") << qreal(50) << qreal(600) << qreal(-1) << qreal(-1) << QSize(qRound(qreal(540) * (qreal(50) / qreal(600))), 540);
QTest::newRow("limit by content width") << qreal(600) << qreal(50) << qreal(300) << qreal(-1) << QSize(300, qRound(qreal(300) / (qreal(600) / qreal(50))));
QTest::newRow("limit by content height") << qreal(50) << qreal(600) << qreal(-1) << qreal(300) << QSize(qRound(qreal(300) * (qreal(50) / qreal(600))), 300);
QTest::newRow("limit by content width tall media")
<< qreal(400) << qreal(600) << qreal(100) << qreal(400) << QSize(100, qRound(qreal(100) / (qreal(400) / qreal(600))));
QTest::newRow("limit by content height wide media")
<< qreal(1000) << qreal(600) << qreal(400) << qreal(100) << QSize(qRound(qreal(100) * (qreal(1000) / qreal(600))), 100);
}
void MediaSizeHelperTest::limits()
{
QFETCH(qreal, mediaWidth);
QFETCH(qreal, mediaHeight);
QFETCH(qreal, contentMaxWidth);
QFETCH(qreal, contentMaxHeight);
QFETCH(QSize, currentSize);
MediaSizeHelper mediasizehelper;
mediasizehelper.setMediaWidth(mediaWidth);
mediasizehelper.setMediaHeight(mediaHeight);
mediasizehelper.setContentMaxWidth(contentMaxWidth);
mediasizehelper.setContentMaxHeight(contentMaxHeight);
QCOMPARE(mediasizehelper.currentSize(), currentSize);
}
QTEST_GUILESS_MAIN(MediaSizeHelperTest)
#include "mediasizehelpertest.moc"

View File

@@ -0,0 +1,215 @@
// 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 <QObject>
#include <QSignalSpy>
#include <QTest>
#include <Quotient/connection.h>
#include <Quotient/quotient_common.h>
#include <Quotient/syncdata.h>
#include "enums/delegatetype.h"
#include "models/messageeventmodel.h"
#include "neochatroom.h"
#include "testutils.h"
using namespace Quotient;
class MessageEventModelTest : public QObject
{
Q_OBJECT
private:
Connection *connection = nullptr;
MessageEventModel *model = nullptr;
private Q_SLOTS:
void initTestCase();
void init();
void switchEmptyRoom();
void switchSyncedRoom();
void simpleTimeline();
void syncNewEvents();
void pendingEvent();
void disconnect();
void idToRow();
void cleanup();
};
void MessageEventModelTest::initTestCase()
{
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
}
void MessageEventModelTest::init()
{
QCOMPARE(model, nullptr);
model = new MessageEventModel;
}
// Make sure that basic empty rooms can be switched without crashing.
void MessageEventModelTest::switchEmptyRoom()
{
auto firstRoom = new TestUtils::TestRoom(connection, QStringLiteral("#firstRoom:kde.org"));
auto secondRoom = new TestUtils::TestRoom(connection, QStringLiteral("#secondRoom:kde.org"));
QSignalSpy spy(model, SIGNAL(roomChanged()));
QCOMPARE(model->room(), nullptr);
model->setRoom(firstRoom);
QCOMPARE(spy.count(), 1);
QCOMPARE(model->room()->id(), QStringLiteral("#firstRoom:kde.org"));
model->setRoom(secondRoom);
QCOMPARE(spy.count(), 2);
QCOMPARE(model->room()->id(), QStringLiteral("#secondRoom:kde.org"));
model->setRoom(nullptr);
QCOMPARE(spy.count(), 3);
QCOMPARE(model->room(), nullptr);
}
// Make sure that rooms with some events can be switched without crashing
void MessageEventModelTest::switchSyncedRoom()
{
auto firstRoom = new TestUtils::TestRoom(connection, QStringLiteral("#firstRoom:kde.org"), QLatin1String("test-messageventmodel-sync.json"));
auto secondRoom = new TestUtils::TestRoom(connection, QStringLiteral("#secondRoom:kde.org"), QLatin1String("test-messageventmodel-sync.json"));
QSignalSpy spy(model, SIGNAL(roomChanged()));
QCOMPARE(model->room(), nullptr);
model->setRoom(firstRoom);
QCOMPARE(spy.count(), 1);
QCOMPARE(model->room()->id(), QStringLiteral("#firstRoom:kde.org"));
model->setRoom(secondRoom);
QCOMPARE(spy.count(), 2);
QCOMPARE(model->room()->id(), QStringLiteral("#secondRoom:kde.org"));
model->setRoom(nullptr);
QCOMPARE(spy.count(), 3);
QCOMPARE(model->room(), nullptr);
}
void MessageEventModelTest::simpleTimeline()
{
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-messageventmodel-sync.json"));
model->setRoom(room);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->data(model->index(0), MessageEventModel::DelegateTypeRole), DelegateType::State);
QCOMPARE(model->data(model->index(0)), QStringLiteral("changed their display name to Example Changed"));
QCOMPARE(model->data(model->index(1)), QStringLiteral("<b>This is an example<br>text message</b>"));
QCOMPARE(model->data(model->index(1), MessageEventModel::DelegateTypeRole), DelegateType::Message);
QCOMPARE(model->data(model->index(1), MessageEventModel::PlainText), QStringLiteral("This is an example\ntext message"));
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)");
QCOMPARE(model->data(model->index(-1)), QVariant());
QTest::ignoreMessage(QtWarningMsg, "Index QModelIndex(-1,-1,0x0,QObject(0x0)) is not valid (expected valid)");
QCOMPARE(model->data(model->index(model->rowCount())), QVariant());
}
// Sync some events into the MessageEventModel's current room and don't crash.
void MessageEventModelTest::syncNewEvents()
{
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"));
QSignalSpy spy(room, SIGNAL(aboutToAddNewMessages(Quotient::RoomEventsRange)));
model->setRoom(room);
QCOMPARE(model->rowCount(), 0);
room->syncNewEvents(QLatin1String("test-messageventmodel-sync.json"));
QCOMPARE(model->rowCount(), 2);
QCOMPARE(spy.count(), 1);
}
// Check the adding of pending events to the room doesn't cause any issues in the model.
void MessageEventModelTest::pendingEvent()
{
QSignalSpy spyInsert(model, SIGNAL(rowsInserted(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> &)));
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"));
model->setRoom(room);
QCOMPARE(model->rowCount(), 0);
auto txnId = room->postPlainText("New plain message"_ls);
QCOMPARE(model->rowCount(), 1);
QCOMPARE(spyInsert.count(), 1);
room->discardMessage(txnId);
QCOMPARE(model->rowCount(), 0);
QCOMPARE(spyRemove.count(), 1);
txnId = room->postPlainText("New plain message"_ls);
QCOMPARE(model->rowCount(), 1);
QCOMPARE(spyInsert.count(), 2);
// We need to manually set the transaction ID of the new message as it will be
// different every time.
QFile testSyncFile;
testSyncFile.setFileName(QLatin1String(DATA_DIR) + u'/' + QLatin1String("test-pending-sync.json"));
testSyncFile.open(QIODevice::ReadOnly);
auto testSyncJson = QJsonDocument::fromJson(testSyncFile.readAll());
auto root = testSyncJson.object();
auto timeline = root["timeline"_ls].toObject();
auto events = timeline["events"_ls].toArray();
auto firstEvent = events[0].toObject();
firstEvent.insert(QLatin1String("unsigned"), QJsonObject{{QLatin1String("transaction_id"), txnId}});
events[0] = firstEvent;
timeline.insert("events"_ls, events);
root.insert("timeline"_ls, timeline);
testSyncJson.setObject(root);
SyncRoomData roomData(QStringLiteral("@bob:kde.org"), JoinState::Join, testSyncJson.object());
room->update(std::move(roomData));
QCOMPARE(model->rowCount(), 1);
// The model will throw multiple data changed signals we need the one that refreshes
// the IsPendingRole.
QCOMPARE(spyChanged.count() > 0, true);
auto isPendingChanged = false;
for (auto signal : spyChanged) {
auto roles = signal.at(2).toList();
if (roles.contains(MessageEventModel::IsPendingRole)) {
isPendingChanged = true;
}
}
QCOMPARE(isPendingChanged, true);
}
// Make sure that the signals are disconnecting correctly when a room is switched.
void MessageEventModelTest::disconnect()
{
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"));
model->setRoom(room);
QSignalSpy spy(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
model->setRoom(nullptr);
room->syncNewEvents(QLatin1String("test-messageventmodel-sync.json"));
QCOMPARE(spy.count(), 0);
}
void MessageEventModelTest::idToRow()
{
auto room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-min-sync.json"));
model->setRoom(room);
QCOMPARE(model->eventIdToRow(QStringLiteral("$153456789:example.org")), 0);
}
void MessageEventModelTest::cleanup()
{
delete model;
model = nullptr;
QCOMPARE(model, nullptr);
}
QTEST_MAIN(MessageEventModelTest)
#include "messageeventmodeltest.moc"

View File

@@ -5,138 +5,30 @@
#include <QSignalSpy>
#include <QTest>
#include "neochatroom.h"
#include <Quotient/connection.h>
#include <Quotient/quotient_common.h>
#include <Quotient/syncdata.h>
#include <connection.h>
#include <quotient_common.h>
#include <syncdata.h>
#include "testutils.h"
using namespace Quotient;
class TestRoom : public NeoChatRoom
{
public:
using NeoChatRoom::NeoChatRoom;
void update(SyncRoomData &&data, bool fromCache = false)
{
Room::updateData(std::move(data), fromCache);
}
};
class NeoChatRoomTest : public QObject {
Q_OBJECT
private:
Connection *connection = nullptr;
TestRoom *room = nullptr;
TestUtils::TestRoom *room = nullptr;
private Q_SLOTS:
void initTestCase();
void subtitleTextTest();
void eventTest();
};
void NeoChatRoomTest::initTestCase()
{
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
room = new TestRoom(connection, QStringLiteral("#myroom:kde.org"), JoinState::Join);
auto json = QJsonDocument::fromJson(R"EVENT({
"account_data": {
"events": [
{
"content": {
"tags": {
"u.work": {
"order": 0.9
}
}
},
"type": "m.tag"
},
{
"content": {
"custom_config_key": "custom_config_value"
},
"type": "org.example.custom.room.config"
}
]
},
"ephemeral": {
"events": [
{
"content": {
"user_ids": [
"@alice:matrix.org",
"@bob:example.com"
]
},
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"type": "m.typing"
}
]
},
"state": {
"events": [
{
"content": {
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
"displayname": "Alice Margatroid",
"membership": "join",
"reason": "Looking for support"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "@alice:example.org",
"type": "m.room.member",
"unsigned": {
"age": 1234
}
}
]
},
"summary": {
"m.heroes": [
"@alice:example.com",
"@bob:example.com"
],
"m.invited_member_count": 0,
"m.joined_member_count": 2
},
"timeline": {
"events": [
{
"content": {
"body": "This is an **example** text message",
"format": "org.matrix.custom.html",
"formatted_body": "<b>This is an example text message</b>",
"msgtype": "m.text"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824654,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1235
}
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
})EVENT");
SyncRoomData roomData(QStringLiteral("@bob:kde.org"), JoinState::Join, json.object());
room->update(std::move(roomData));
}
void NeoChatRoomTest::subtitleTextTest()
{
QCOMPARE(room->timelineSize(), 1);
QCOMPARE(room->lastEventToString(), QStringLiteral("@example:example.org: This is an example text message"));
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), "test-min-sync.json"_ls);
}
void NeoChatRoomTest::eventTest()
@@ -144,5 +36,5 @@ void NeoChatRoomTest::eventTest()
QCOMPARE(room->timelineSize(), 1);
}
QTEST_MAIN(NeoChatRoomTest)
QTEST_GUILESS_MAIN(NeoChatRoomTest)
#include "neochatroomtest.moc"

View File

@@ -0,0 +1,70 @@
// 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 <QObject>
#include <QSignalSpy>
#include <QTest>
#include <Quotient/connection.h>
#include <Quotient/quotient_common.h>
#include <Quotient/syncdata.h>
#include "events/pollevent.h"
#include "pollhandler.h"
#include "testutils.h"
using namespace Quotient;
class PollHandlerTest : public QObject
{
Q_OBJECT
private:
Connection *connection = nullptr;
TestUtils::TestRoom *room = nullptr;
private Q_SLOTS:
void initTestCase();
void nullObject();
void poll();
};
void PollHandlerTest::initTestCase()
{
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), "test-pollhandlerstart-sync.json"_ls);
}
// Basically don't crash.
void PollHandlerTest::nullObject()
{
auto pollHandler = PollHandler();
QCOMPARE(pollHandler.hasEnded(), false);
QCOMPARE(pollHandler.answerCount(), 0);
QCOMPARE(pollHandler.question(), QString());
QCOMPARE(pollHandler.options(), QJsonArray());
QCOMPARE(pollHandler.answers(), QJsonObject());
QCOMPARE(pollHandler.counts(), QJsonObject());
QCOMPARE(pollHandler.kind(), QString());
}
void PollHandlerTest::poll()
{
auto startEvent = eventCast<const PollStartEvent>(room->messageEvents().at(0).get());
auto pollHandler = PollHandler(room, startEvent);
auto options = QJsonArray{QJsonObject{{"id"_ls, "option1"_ls}, {"org.matrix.msc1767.text"_ls, "option1"_ls}},
QJsonObject{{"id"_ls, "option2"_ls}, {"org.matrix.msc1767.text"_ls, "option2"_ls}}};
QCOMPARE(pollHandler.hasEnded(), false);
QCOMPARE(pollHandler.answerCount(), 0);
QCOMPARE(pollHandler.question(), QStringLiteral("test"));
QCOMPARE(pollHandler.options(), options);
QCOMPARE(pollHandler.answers(), QJsonObject());
QCOMPARE(pollHandler.counts(), QJsonObject());
QCOMPARE(pollHandler.kind(), QStringLiteral("org.matrix.msc3381.poll.disclosed"));
}
QTEST_GUILESS_MAIN(PollHandlerTest)
#include "pollhandlertest.moc"

View File

@@ -0,0 +1,83 @@
// 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 <QObject>
#include <QSignalSpy>
#include <QTest>
#include "models/reactionmodel.h"
#include <Quotient/events/roommessageevent.h>
#include "testutils.h"
using namespace Quotient;
class ReactionModelTest : public QObject
{
Q_OBJECT
private:
Connection *connection = nullptr;
TestUtils::TestRoom *room = nullptr;
private Q_SLOTS:
void initTestCase();
void nullModel();
void basicReaction();
void newReaction();
};
void ReactionModelTest::initTestCase()
{
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-reactionmodel-sync.json"));
}
void ReactionModelTest::nullModel()
{
auto model = ReactionModel(nullptr, nullptr);
QCOMPARE(model.rowCount(), 0);
QCOMPARE(model.data(model.index(0), ReactionModel::TextContentRole), QVariant());
}
void ReactionModelTest::basicReaction()
{
auto event = eventCast<const RoomMessageEvent>(room->messageEvents().at(0).get());
auto model = ReactionModel(event, room);
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::ReactionRole), QStringLiteral("👍"));
QCOMPARE(model.data(model.index(0), ReactionModel::ToolTipRole),
QStringLiteral("@alice:matrix.org reacted with <span style=\"font-family: 'emoji';\">👍</span>"));
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()
{
auto event = eventCast<const RoomMessageEvent>(room->messageEvents().at(0).get());
auto model = new ReactionModel(event, room);
QCOMPARE(model->rowCount(), 1);
QCOMPARE(model->data(model->index(0), ReactionModel::ToolTipRole),
QStringLiteral("@alice:matrix.org reacted with <span style=\"font-family: 'emoji';\">👍</span>"));
QSignalSpy spy(model, SIGNAL(modelReset()));
room->syncNewEvents(QLatin1String("test-reactionmodel-extra-sync.json"));
QCOMPARE(model->rowCount(), 2);
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(0), ReactionModel::ToolTipRole),
QStringLiteral("@alice:matrix.org and @bob:example.org reacted with <span style=\"font-family: 'emoji';\">👍</span>"));
delete model;
}
QTEST_MAIN(ReactionModelTest)
#include "reactionmodeltest.moc"

55
autotests/testutils.h Normal file
View File

@@ -0,0 +1,55 @@
// 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 <Quotient/events/event.h>
#include <Quotient/syncdata.h>
#include "neochatroom.h"
namespace Quotient
{
class Connection;
}
namespace TestUtils
{
class TestRoom : public NeoChatRoom
{
public:
TestRoom(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(QLatin1String(DATA_DIR) + u'/' + syncFileName);
testSyncFile.open(QIODevice::ReadOnly);
const auto testSyncJson = QJsonDocument::fromJson(testSyncFile.readAll());
Quotient::SyncRoomData roomData(id(), Quotient::JoinState::Join, testSyncJson.object());
update(std::move(roomData));
}
}
};
template<Quotient::EventClass EventT>
inline Quotient::event_ptr_tt<EventT> loadEventFromFile(const QString &eventFileName)
{
if (!eventFileName.isEmpty()) {
QFile testEventFile;
testEventFile.setFileName(QLatin1String(DATA_DIR) + u'/' + eventFileName);
testEventFile.open(QIODevice::ReadOnly);
auto testSyncJson = QJsonDocument::fromJson(testEventFile.readAll()).object();
return Quotient::loadEvent<EventT>(testSyncJson);
}
return nullptr;
}
}

View File

@@ -6,30 +6,25 @@
#include "texthandler.h"
#include <Quotient/quotient_common.h>
#include <Quotient/syncdata.h>
#include <qnamespace.h>
#include <quotient_common.h>
#include <syncdata.h>
#include "models/customemojimodel.h"
#include "neochatconnection.h"
#include "utils.h"
#include "testutils.h"
using namespace Quotient;
class TestRoom : public NeoChatRoom
{
public:
using NeoChatRoom::NeoChatRoom;
void update(SyncRoomData &&data, bool fromCache = false)
{
Room::updateData(std::move(data), fromCache);
}
};
class TextHandlerTest : public QObject
{
Q_OBJECT
private:
Connection *connection = nullptr;
TestRoom *room = nullptr;
TestUtils::TestRoom *room = nullptr;
private Q_SLOTS:
void initTestCase();
@@ -38,6 +33,7 @@ private Q_SLOTS:
void stripDisallowedTags();
void stripDisallowedAttributes();
void emptyCodeTags();
void formatBlockQuote();
void sendSimpleStringCase();
void sendSingleParaMarkup();
@@ -45,6 +41,9 @@ private Q_SLOTS:
void sendBadLinks();
void sendEscapeCode();
void sendCodeClass();
void sendCustomEmoji();
void sendCustomEmojiCode_data();
void sendCustomEmojiCode();
void receiveStripReply();
void receivePlainTextIn();
@@ -63,142 +62,23 @@ private Q_SLOTS:
void receiveRichEmote();
void receiveRichEdited_data();
void receiveRichEdited();
void receiveLineSeparator();
void receiveRichCodeUrl();
};
#ifdef QUOTIENT_07
void TextHandlerTest::initTestCase()
{
connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
room = new TestRoom(connection, QStringLiteral("#myroom:kde.org"), JoinState::Join);
connection->setAccountData("im.ponies.user_emotes"_ls,
QJsonObject{{"images"_ls,
QJsonObject{{"test"_ls,
QJsonObject{{"body"_ls, "Test custom emoji"_ls},
{"url"_ls, "mxc://example.org/test"_ls},
{"usage"_ls, QJsonArray{"emoticon"_ls}}}}}}});
CustomEmojiModel::instance().setConnection(static_cast<NeoChatConnection *>(connection));
const auto json = QJsonDocument::fromJson(R"EVENT({
"account_data": {
"events": [
{
"content": {
"tags": {
"u.work": {
"order": 0.9
}
}
},
"type": "m.tag"
},
{
"content": {
"custom_config_key": "custom_config_value"
},
"type": "org.example.custom.room.config"
}
]
},
"ephemeral": {
"events": [
{
"content": {
"user_ids": [
"@alice:matrix.org",
"@bob:example.com"
]
},
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"type": "m.typing"
}
]
},
"state": {
"events": [
{
"content": {
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
"displayname": "Alice Margatroid",
"membership": "join",
"reason": "Looking for support"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "@alice:example.org",
"type": "m.room.member",
"unsigned": {
"age": 1234
}
}
]
},
"summary": {
"m.heroes": [
"@alice:example.com",
"@bob:example.com"
],
"m.invited_member_count": 0,
"m.joined_member_count": 2
},
"timeline": {
"events": [
{
"content": {
"body": "This is an **example** text message",
"format": "org.matrix.custom.html",
"formatted_body": "<b>This is an example text message</b>",
"msgtype": "m.text"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824654,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1232
}
},
{
"content": {
"body": "/me This is an emote.",
"format": "org.matrix.custom.html",
"formatted_body": "This is an emote.",
"msgtype": "m.emote"
},
"event_id": "$153273582443PhrSn:example.org",
"origin_server_ts": 1532735824654,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1231
}
},
{
"content": {
"body": "tested",
"msgtype": "m.text"
},
"event_id": "$zrCiBxBnqqTn0Z5FY78qSZAszno_w8nJJXzfBULG-3E",
"origin_server_ts": 1680948575928,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1747776,
"m.relations": {
"m.replace": {
"event_id": "$UX0PlpyI7vYO32iHMuuYEP7ECMh4sX3XLGiB2SwM4mQ",
"origin_server_ts": 1680948580992,
"sender": "@example:example.org"
}
}
}
}
],
"limited": true,
"prev_batch": "t34-23535_0_0"
}
})EVENT");
SyncRoomData roomData(QStringLiteral("@bob:kde.org"), JoinState::Join, json.object());
room->update(std::move(roomData));
room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-texthandler-sync.json"));
}
#endif
void TextHandlerTest::allowedAttributes()
{
@@ -259,6 +139,16 @@ void TextHandlerTest::emptyCodeTags()
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()
{
const QString testInputString = QStringLiteral("This data should just be put in a paragraph.");
@@ -336,6 +226,39 @@ void TextHandlerTest::sendCodeClass()
QCOMPARE(testTextHandler.handleSendText(), testOutputString);
}
void TextHandlerTest::sendCustomEmoji()
{
const QString testInputString = QStringLiteral(":test:");
const QString testOutputString = QStringLiteral(
"<p><img data-mx-emoticon=\"\" src=\"mxc://example.org/test\" alt=\":test:\" title=\":test:\" height=\"32\" vertical-align=\"middle\" /></p>");
TextHandler testTextHandler;
testTextHandler.setData(testInputString);
QCOMPARE(testTextHandler.handleSendText(), testOutputString);
}
void TextHandlerTest::sendCustomEmojiCode_data()
{
QTest::addColumn<QString>("testInputString");
QTest::addColumn<QString>("testOutputString");
QTest::newRow("inline") << QStringLiteral("`:test:`") << QStringLiteral("<p><code>:test:</code></p>");
QTest::newRow("block") << QStringLiteral("```\n:test:\n```") << QStringLiteral("<pre><code>:test:\n</code></pre>");
}
// Custom emojis in code blocks should be left alone.
void TextHandlerTest::sendCustomEmojiCode()
{
QFETCH(QString, testInputString);
QFETCH(QString, testOutputString);
TextHandler testTextHandler;
testTextHandler.setData(testInputString);
QCOMPARE(testTextHandler.handleSendText(), testOutputString);
}
void TextHandlerTest::receiveStripReply()
{
const QString testInputString = QStringLiteral(
@@ -357,6 +280,7 @@ void TextHandlerTest::receiveRichInPlainOut_data()
QTest::newRow("ampersand") << QStringLiteral("a &amp; b") << QStringLiteral("a & b");
QTest::newRow("quote") << QStringLiteral("&quot;a and b&quot;") << QStringLiteral("\"a and b\"");
QTest::newRow("new line") << QStringLiteral("new<br>line") << QStringLiteral("new\nline");
}
void TextHandlerTest::receiveRichInPlainOut()
@@ -473,7 +397,6 @@ void TextHandlerTest::receiveRichtextIn()
QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
}
#ifdef QUOTIENT_07
void TextHandlerTest::receiveRichMxcUrl()
{
const QString testInputString = QStringLiteral(
@@ -491,7 +414,6 @@ void TextHandlerTest::receiveRichMxcUrl()
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, room->messageEvents().at(0).get()), testOutputString);
}
#endif
/**
* For when your rich input string has a plain text url left in.
@@ -553,10 +475,10 @@ void TextHandlerTest::receiveRichPlainUrl()
void TextHandlerTest::receiveRichEmote()
{
auto event = room->messageEvents().at(1).get();
auto author = static_cast<NeoChatUser *>(room->user(event->senderId()));
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:") + author->color().name()
+ QStringLiteral("\">@example:example.org</a> 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);
@@ -572,8 +494,9 @@ void TextHandlerTest::receiveRichEdited_data()
QTest::newRow("basic") << QStringLiteral("Edited") << QStringLiteral("Edited <span style=\"color:#000000\">(edited)</span>");
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("blockquote") << QStringLiteral("<blockquote>Edited</blockquote>")
<< QStringLiteral("<blockquote>Edited</blockquote><p> <span style=\"color:#000000\">(edited)</span></p>");
QTest::newRow("blockquote")
<< QStringLiteral("<blockquote>Edited</blockquote>")
<< QStringLiteral("<blockquote><table><tr><td>\u201CEdited\u201D</td></tr></table></blockquote><p> <span style=\"color:#000000\">(edited)</span></p>");
}
void TextHandlerTest::receiveRichEdited()
@@ -587,5 +510,21 @@ void TextHandlerTest::receiveRichEdited()
QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, room->messageEvents().at(2).get()), testOutputString);
}
void TextHandlerTest::receiveLineSeparator()
{
auto text = QStringLiteral("foo\u2028bar");
TextHandler textHandler;
textHandler.setData(text);
QCOMPARE(textHandler.handleRecievePlainText(Qt::PlainText, true), QStringLiteral("foo bar"));
}
void TextHandlerTest::receiveRichCodeUrl()
{
auto input = QStringLiteral("<code>https://kde.org</code>");
TextHandler testTextHandler;
testTextHandler.setData(input);
QCOMPARE(testTextHandler.handleRecieveRichText(), input);
}
QTEST_MAIN(TextHandlerTest)
#include "texthandlertest.moc"

View File

@@ -0,0 +1,102 @@
// 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 <QQmlApplicationEngine>
#include <QTest>
#include <QWindow>
#include <KConfig>
#include <KSharedConfig>
#include <KWindowConfig>
#include "windowcontroller.h"
class WindowControllerTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void nullWindow();
void geometry();
void showAndRaise();
void toggle();
void cleanup();
};
// Basically don't crash when no window is set.
void WindowControllerTest::nullWindow()
{
auto &instance = WindowController::instance();
QCOMPARE(instance.window(), nullptr);
instance.restoreGeometry();
instance.saveGeometry();
instance.showAndRaiseWindow({});
instance.toggleWindow();
}
void WindowControllerTest::geometry()
{
auto &instance = WindowController::instance();
QWindow window;
window.setGeometry(0, 0, 200, 200);
instance.setWindow(&window);
QCOMPARE(instance.window(), &window);
instance.saveGeometry();
const auto stateConfig = KSharedConfig::openStateConfig();
KConfigGroup windowGroup = stateConfig->group(QStringLiteral("Window"));
QCOMPARE(KWindowConfig::hasSavedWindowSize(windowGroup), true);
window.setGeometry(0, 0, 400, 400);
QCOMPARE(window.geometry(), QRect(0, 0, 400, 400));
instance.restoreGeometry();
QCOMPARE(window.geometry(), QRect(0, 0, 200, 200));
}
void WindowControllerTest::showAndRaise()
{
auto &instance = WindowController::instance();
QWindow window;
instance.setWindow(&window);
QCOMPARE(window.isVisible(), false);
instance.showAndRaiseWindow({});
QCOMPARE(window.isVisible(), true);
}
void WindowControllerTest::cleanup()
{
auto &instance = WindowController::instance();
instance.setWindow(nullptr);
QCOMPARE(instance.window(), nullptr);
}
void WindowControllerTest::toggle()
{
auto &instance = WindowController::instance();
QWindow window;
instance.setWindow(&window);
QCOMPARE(window.isVisible(), false);
instance.toggleWindow();
QCOMPARE(window.isVisible(), true);
instance.toggleWindow();
QCOMPARE(window.isVisible(), false);
// A window is classed as visible by qt when minimized but to the user this is not visible.
// So in this case we expect to show it even though visibility is technically true.
window.setVisibility(QWindow::Minimized);
QCOMPARE(window.windowState(), Qt::WindowMinimized);
QCOMPARE(window.isVisible(), true);
instance.toggleWindow();
QCOMPARE(window.windowState(), Qt::WindowNoState);
QCOMPARE(window.isVisible(), true);
instance.toggleWindow();
QCOMPARE(window.windowState(), Qt::WindowNoState);
QCOMPARE(window.isVisible(), false);
}
QTEST_MAIN(WindowControllerTest)
#include "windowcontrollertest.moc"

View File

@@ -2,4 +2,4 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
kdoctools_create_manpage(man-neochat.1.docbook 1 INSTALL_DESTINATION ${MAN_INSTALL_DIR})
kdoctools_create_manpage(man-neochat.1.docbook 1 INSTALL_DESTINATION ${KDE_INSTALL_MANDIR})

BIN
icons/300-apps-neochat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -11,6 +11,7 @@
</provides>
<name>NeoChat</name>
<name xml:lang="ar">نيوتشات</name>
<name xml:lang="ast">NeoChat</name>
<name xml:lang="az">NeoChat</name>
<name xml:lang="ca">NeoChat</name>
<name xml:lang="ca-valencia">NeoChat</name>
@@ -18,10 +19,12 @@
<name xml:lang="de">NeoChat</name>
<name xml:lang="el">NeoChat</name>
<name xml:lang="en-GB">NeoChat</name>
<name xml:lang="eo">NeoChat</name>
<name xml:lang="es">NeoChat</name>
<name xml:lang="eu">NeoChat</name>
<name xml:lang="fi">NeoChat</name>
<name xml:lang="fr">NeoChat</name>
<name xml:lang="gl">NeoChat</name>
<name xml:lang="hu">NeoChat</name>
<name xml:lang="ia">Neochat</name>
<name xml:lang="id">NeoChat</name>
@@ -44,137 +47,194 @@
<name xml:lang="uk">NeoChat</name>
<name xml:lang="x-test">xxNeoChatxx</name>
<name xml:lang="zh-CN">NeoChat</name>
<summary>A client for matrix, the decentralized communication protocol</summary>
<summary xml:lang="ar">عميل لماتركس، ميفاق الاتصال اللامركزي</summary>
<summary xml:lang="az">Matrix üçün müştəri, mərkəzləşməmiş kommunikasiya protokolu</summary>
<summary xml:lang="ca">Un client per al Matrix, el protocol de comunicacions descentralitzat</summary>
<summary xml:lang="ca-valencia">Un client per a Matrix, el protocol de comunicacions descentralitzat</summary>
<summary xml:lang="cs">Klient pro decentralizovaný komunikační protokol matrix</summary>
<summary xml:lang="de">Ein Programm für Matrix, das dezentrale Kommunikationsprotokoll</summary>
<summary xml:lang="el">Ένας πελάτης για το Matrix, το αποκεντρωμένο πρωτόκολλο επικοινωνίας</summary>
<summary xml:lang="en-GB">A client for matrix, the decentralised communication protocol</summary>
<summary xml:lang="es">Un cliente para Matrix, el protocolo de comunicaciones descentralizado</summary>
<summary xml:lang="eu">Matrix, deszentralizatutako komunikazio protokolorako bezero bat</summary>
<summary xml:lang="fi">Asiakas Matrixille, hajautetulle viestintäyhteyskäytännölle</summary>
<summary xml:lang="fr">Un client pour « Matrix », le protocole décentralisé de communications.</summary>
<summary xml:lang="hu">Kliens a matrixhoz, a decentralizált kommunikációs protokollhoz</summary>
<summary xml:lang="ia">Un cliente per Matrix, le protocollo de communication decentralisate</summary>
<summary xml:lang="id">Klien untuk matrix, protokol komunikasi terdesentralisasi</summary>
<summary xml:lang="ie">Un cliente de Matrix, li protocol de communication decentralisat</summary>
<summary xml:lang="it">Un client per matrix, il protocollo di comunicazione decentralizzato</summary>
<summary xml:lang="ka">კლიენტი Matrix-სთვის, დეცენტრალიზებული კომუნიკაციის პროტოკოლისთვის</summary>
<summary xml:lang="ko">Matrix, 분산 대화 프로토콜 클라이언트</summary>
<summary xml:lang="nl">Een client voor matrix, het gedecentraliseerde communicatieprotocol</summary>
<summary xml:lang="nn">Ein klient for Matrix, den desentraliserte lynmeldings­protokollen</summary>
<summary xml:lang="pa">ਮੈਟਰਿਕਸ, ਸਰਬ-ਸਾਂਝੇ ਸੰਚਾਰ ਪਰੋਟੋਕਾਲ, ਲਈ ਕਲਾਈਂਟ ਹੈ</summary>
<summary xml:lang="pl">Program do obsługi matriksa, rozproszonego protokołu porozumiewania się</summary>
<summary xml:lang="pt">Um cliente para o Matrix, o protocolo de comunicação descentralizado</summary>
<summary xml:lang="pt-BR">Um cliente do Matrix, o protocolo de comunicação descentralizado</summary>
<summary xml:lang="ru">Клиент для Matrix — децентрализованного коммуникационного протокола</summary>
<summary xml:lang="sk">Klient pre matrix, decentralizovaný komunikačný protokol</summary>
<summary xml:lang="sl">Odjemalec za matrix, decentralizirani komunikacijski protokol</summary>
<summary xml:lang="sv">En klient för Matrix, det decentraliserade kommunikationsprotokollet</summary>
<summary xml:lang="tr">Merkezi olmayan iletişim protokolü Matrix için bir istemci</summary>
<summary xml:lang="uk">Клієнт matrix, децентралізованого протоколу обміну даними</summary>
<summary xml:lang="x-test">xxA client for matrix, the decentralized communication protocolxx</summary>
<summary xml:lang="zh-CN">分布式通讯协议 Matrix 的客户端</summary>
<name xml:lang="zh-TW">NeoChat</name>
<summary>Chat with your friends on matrix</summary>
<summary xml:lang="ar">دردش مع أصدقائك على ماتركس</summary>
<summary xml:lang="ca">Xategeu amb els vostres amics a Matrix</summary>
<summary xml:lang="ca-valencia">Xategeu amb els vostres amics a Matrix</summary>
<summary xml:lang="cs">Mluvte se svými přáteli na Matrixu</summary>
<summary xml:lang="eo">Babilu kun viaj amikoj sur matrix</summary>
<summary xml:lang="es">Charle con sus amigos en matrix</summary>
<summary xml:lang="eu">Berriketan jardun zure lagunekin «Matrix»en</summary>
<summary xml:lang="fi">Keskustelu ystäviesi kanssa Matrixissa</summary>
<summary xml:lang="fr">Discuter avec vos ami(e)s sur le réseau Matrix</summary>
<summary xml:lang="gl">Charle coas súas amizades en Matrix.</summary>
<summary xml:lang="ia">Starta Conversation conntu amicos sur matrix</summary>
<summary xml:lang="it">Conversa con i tuoi contatti su matrix</summary>
<summary xml:lang="ka">ესაუბრეთ მეგობრებს Matrix-ზე</summary>
<summary xml:lang="ko">Matrix를 사용하여 친구들과 대화하기</summary>
<summary xml:lang="nl">Met uw vrienden chatten op matrix</summary>
<summary xml:lang="nn">Prat med vennar på Matrix</summary>
<summary xml:lang="pl">Rozmawiaj ze swoimi znajomymi w Matriksie</summary>
<summary xml:lang="sl">Klepet z vašimi prijatelji na matrixu</summary>
<summary xml:lang="sv">Chatta med dina vänner på Matrix</summary>
<summary xml:lang="ta">மேட்ரிக்ஸு மூலம் உங்கள் நண்பர்களிடம் பேசலாம்</summary>
<summary xml:lang="tr">Matrix'te arkadaşlarınızla sohbet edin</summary>
<summary xml:lang="uk">Спілкуйтеся з вашими друзями у matrix</summary>
<summary xml:lang="x-test">xxChat with your friends on matrixxx</summary>
<summary xml:lang="zh-CN">在 Matrix 上与朋友聊天</summary>
<summary xml:lang="zh-TW">在 Matrix 上與您的朋友聊天</summary>
<description>
<p>NeoChat is a Matrix client. It allows you to send text messages, videos and audio files to your family, colleagues and friends using the Matrix protocol.</p>
<p xml:lang="ar">نيوتشات هو عميل ماتركس Matrix. يتيح لك إرسال رسائل نصية ومقاطع فيديو وملفات صوتية إلى عائلتك وزملائك وأصدقائك باستخدام بروتوكول ماتركس</p>
<p xml:lang="az">NeoChat Mtrix müştərisidir. O, Matrix protokolundan istifadə edərək, ailənizə, dostlarınıza, iş yoldaşlarınıza mətn, səsli və görüntülü ismarıclar göndərməyə imkan verir.</p>
<p xml:lang="ca">El NeoChat és un client de Matrix. Permet enviar missatges de text, fitxers de vídeo i d'àudio a la família, col·legues i amics usant el protocol Matrix.</p>
<p xml:lang="ca-valencia">NeoChat és un client de Matrix. Permet enviar missatges de text, fitxers de vídeo i d'àudio a la família, col·legues i amics utilitzant el protocol Matrix.</p>
<p xml:lang="de">NeoChat ist ein Matrix-Client. Er ermöglicht Ihnen das Senden von Textnachrichten, Videos und Audiodateien an Ihre Familie, Kollegen und Freunde unter Verwendung des Matrix-Protokolls.</p>
<p xml:lang="el">Το NeoChat είναι μια εφαρμογή του Matrix. Σας επιτρέπει να στέλνετε μηνύματα κειμένου, βίντεο και ήχο στην οικογένειά σας, σε συναδέλφους και φίλους με το πρωτόκολλο Matrix.</p>
<p xml:lang="en-GB">NeoChat is a Matrix client. It allows you to send text messages, videos and audio files to your family, colleagues and friends using the Matrix protocol.</p>
<p xml:lang="es">NeoChat es un cliente para Matrix. Le permite enviar mensajes de texto, vídeos y archivos de sonido a su familia, compañeros de trabajo y amigos usando el protocolo Matrix.</p>
<p xml:lang="eu">NeoChat Matrix bezero bat da. Familiari, lankideei eta lagunei testu-mezuak, bideoak eta audio-fitxategiak bidaltzeko aukera ematen du, Matrix protokoloa erabiliz.</p>
<p xml:lang="fi">NeoChat on Matrix-asiakas. Sillä voi lähettää perheelle, tuttaville ja kavereille tekstiviestejä sekä video- ja äänitiedostoja Matrix-yhteyskäytännöllä.</p>
<p xml:lang="fr">NeoChat est un client Matrix. Il vous permet d'envoyer des messages de texte, des vidéos et des fichiers audio à votre famille, vos collègues et vos amis en utilisant le protocole Matrix.</p>
<p xml:lang="hu">A NeoChat egy Matrix kliens. Szöveges üzeneteket, videókat ésaudio fájlokat küldhet családjának, kollégáinak és barátainak a Matrix protokoll használatával.</p>
<p xml:lang="ia">NeoChat es un cliente de Matrix. Illo te permitte inviar messager de texto, files de video e audio a tu familia, collegas e amicos usante le protocollo de Matrix.</p>
<p xml:lang="id">NeoChat adalah sebuah klien Matrix. Memungkinkan Anda untuk mengirim pesan teks, file video dan audio ke keluarga, kolega dan teman Anda menggunakan protokol Matrix.</p>
<p xml:lang="ie">NeoChat es un cliente de Matrix. On posse usar it por inviar missages textual, video- e audiofiles a su familie, colegos e amics med li protocol Matrix.</p>
<p xml:lang="it">NeoChat è un client Matrix. Ti consente di inviare messaggi di testo, file video e audio a familiari, colleghi e amici utilizzando il protocollo Matrix.</p>
<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
to provide a convergent experience across multiple platforms.</p>
<p xml:lang="ar">نيوتشات هو عميل ماتركس Matrix، (ميفاق الاتصال اللامركزي للمراسلة الفورية). يتيح لك نيوتشات إرسال رسائل نصية ومقاطع فيديو وملفات صوتية إلى عائلتك وزملائك وأصدقائك. يستخدم أطر عمل كيدي وأبرزها Kirigami لتوفير تجربة متقاربة عبر منصات متعددة.</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 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="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="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="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="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="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="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="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="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="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="ka">NeoChat არის Matrix კლიენტი. ის საშუალებას გაძლევთ გაგზავნოთ ტექსტური შეტყობინებები, ვიდეოები და აუდიო ფაილები თქვენს ოჯახს, კოლეგებსა და მეგობრებს მატრიქსის პროტოკოლის გამოყენებით.</p>
<p xml:lang="ko">NeoChat은 Matrix 클라이언트입니다. Matrix 프로토콜을 사용하여 가족, 동료, 친구에게 텍스트 메시지, 동영상, 오디오 파일을 전송할 수 있습니다.</p>
<p xml:lang="nl">NeoChat is een Matrix-client. Het biedt u het verzenden van tekstberichten, video's en geluidsbestanden naar uw familie, collega's en vrienden met het Matrix-protocol.</p>
<p xml:lang="pl">NeoChat jest programem do Matrisa. Umożliwia wysyłanie wiadomości tekstowych, filmów oraz dźwięku do twojej rodziny, znajomych oraz przyjaciół poprzez protokół Matriksa.</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.</p>
<p xml:lang="pt-BR">O NeoChat é um cliente Matrix. Ele permite a você enviar mensagens de texto, arquivos de vídeo e áudio para seus familiares, colegas e amigos usando o protocolo Matrix.</p>
<p xml:lang="ru">NeoChat — это клиент, поддерживающий работу с протоколом Matrix. Он позволяет отправлять текстовые сообщения, видео и аудиофайлы.</p>
<p xml:lang="sk">NeoChat je Matrix klient. Umožňuje vám posielať textové správy, videá a zvukové súbory rodine, kolegom a priateľom pomocou protokolu Matrix.</p>
<p xml:lang="sl">NeoChat je odjemalec Matrixa. Dovoljuje vam pošiljanje besedilnih sporočil, videoposnetkov in zvočnih datotek vaši družini, kolegom in prijateljem z uporabo protokola Matrix.</p>
<p xml:lang="sv">NeoChat är en Matrix-klient. Den låter dig skicka textmeddelanden, videor och ljudfiler till din familj, kollegor och vänner med användning av Matrix-protokollet.</p>
<p xml:lang="tr">NeoChat, bir Matrix istemcisidir. Matrix protokolünü kullanarak ailenize, iş arkadaşlarınıza, arkadaşlarınıza ve başkalarına metin iletileri, video ve ses dosyaların göndermenize olanak verir.</p>
<p xml:lang="uk">NeoChat — клієнт мережі обміну повідомленнями Matrix. За допомогою цієї програми ви зможете надсилати текстові повідомлення, відео та звукові файли вашій родині, колегам та друзям за допомогою протоколу Matrix.</p>
<p xml:lang="x-test">xxNeoChat is a Matrix client. It allows you to send text messages, videos and audio files to your family, colleagues and friends using the Matrix protocol.xx</p>
<p xml:lang="zh-CN">NeoChat 是一个 Matrix 客户端。 它允许您使用 Matrix 协议向您的家人、同事和朋友发送文本消息、视频和音频文件。</p>
<p>Matrix is a decentralized communication protocol, putting the user back in control. Currently NeoChat implements large part of the protocol with the exception of encrypted chats and video chat.</p>
<p xml:lang="ar">ماتريكس هو بروتوكول اتصال لامركزي ، يعيد المستخدم إلى السيطرة. يطبق نيوتشات حاليًا جزءًا كبيرًا من الميفاق باستثناء الدردشات المشفرة ودردشة الفيديو.</p>
<p xml:lang="az">Matrix, istifadəçini nəzarətdə saxlayan, mərkəzləşməmişi rabitə protokoludur. NeoChat, söhbətin və video əlaqəsinin şifrələnməsindən başqa bir çox protokolları həyata keçirə bilir.</p>
<p xml:lang="ca">Matrix és un protocol de comunicacions descentralitzat, que retorna el control a l'usuari. Actualment el NeoChat implementa una gran part del protocol amb l'excepció dels xats encriptats i els xats de vídeo.</p>
<p xml:lang="ca-valencia">Matrix és un protocol de comunicacions descentralitzat, que retorna el control a l'usuari. Actualment NeoChat implementa una gran part del protocol amb l'excepció dels xats encriptats i els xats de vídeo.</p>
<p xml:lang="de">Matrix ist ein dezentralisiertes Kommunikationsprotokoll, das dem Benutzer wieder die Kontrolle zurückgibt. Derzeit implementiert NeoChat einen großen Teil des Protokolls mit der Ausnahme von verschlüsselten Chats und Video-Chat.</p>
<p xml:lang="el">Το Matrix είναι ένα αποκεντρωμένο πρωτόκολλο επικοινωνίας, δίνοντας πίσω στον χρήστη τον έλεγχο. Προς το παρόν το NeoChat υλοποιεί ένα μεγάλο μέρος του πρωτοκόλλου με εξαίρεση τις κρυπτογραφημένες συνομιλίες και τη συνομιλία με βίντεο.</p>
<p xml:lang="en-GB">Matrix is a decentralised communication protocol, putting the user back in control. Currently NeoChat implements large part of the protocol with the exception of encrypted chats and video chat.</p>
<p xml:lang="es">Matrix es un protocolo de comunicaciones descentralizado, que devuelve el control al usuario. En la actualidad, NeoChat implementa gran parte del protocolo con la excepción de chats cifrados y chats de vídeo.</p>
<p xml:lang="eu">Matrix komunikazio-protokolo deszentralizatu bat da, erabiltzaileari kontrola itzultzen diona. Gaur egun, NeoChat-ek protokoloaren zati handi bat inplementatzen du, berriketa zifratuak eta bideo berriketak izan ezik.</p>
<p xml:lang="fi">Matrix on hajautettu viestintäyhteyskäytäntö, joka antaa hallinnan takaisin käyttäjille. NeoChat tarjoaa nykyisellään valtaosan yhteyskäytännöstä salattuja keskustelu- ja videokeskusteluja lukuun ottamatta.</p>
<p xml:lang="fr">Matrix est un protocole de communication décentralisé, donnant le contrôle à l'utilisateur. Actuellement, NeoChat met en œuvre une grande partie du protocole, à l'exception des discussions chiffrées et du chat vidéo.</p>
<p xml:lang="hu">A Matrix egy decentralizált kommunikációs protokoll, amely a felhasználók kezébe adja az irányítást.</p>
<p xml:lang="ia">Matrix es un protocollo de communication decentrate, ponente le usator in le controlo. Currentemente NeoChat implementa un grande parte del protocollo con le exception de conversationes cryptate e conversationes video.</p>
<p xml:lang="id">Matrix adalah protokol komunikasi terdesentralisasi, menempatkan pengguna kembali dalam kendali. Saat ini NeoChat mengimplementasikan sebagian besar protokol dengan pengecualian obrolan terenkripsi dan obrolan video.</p>
<p xml:lang="ie">Matrix es un decentralisat protocol de communication quel retroda li control a un usator. Actualmen, NeoChat implementa un grand parte del protocol except ciffrat conversationes e videotelefonada.</p>
<p xml:lang="it">Matrix è un protocollo di comunicazione decentralizzato, che restituisce all'utente il controllo. Attualmente NeoChat implementa gran parte del protocollo ad eccezione delle chat cifrate e delle chat video.</p>
<p xml:lang="ka">Matrix -ი დეცენტრალიზებული კომუნიკაციის პროტოკოლია, რომელიც მომხმარებელს კონტროლის უფლებას უბრუნებს. ამჟამად NeoChat-ს პროტოკოლის ძირითადი ნაწილის მხარდაჭერა გააჩნია, დაშიფვრისა და ვიდეოჩატის გამოკლებით.</p>
<p xml:lang="ko">Matrix는 사용자에게 제어권을 돌려 주는 분산 통신 프로토콜입니다. NeoChat은 암호화된 대화 및 영상 통화를 제외한 프로토콜의 대부분 기능을 구현합니다.</p>
<p xml:lang="nl">Matrix is een gedecentraliseerd communicatieprotocol, dat de gebruiker de controle teruggeeft. Op dit moment implementeert NeoChat grote delen van het protocol met de uitzondering van versleutelde chats en video-chat.</p>
<p xml:lang="pl">Matrix jest protokołem rozproszonego porozumiewania się oddający użytkownikowi jego władzę. Obecnie NeoChat obsługuje dużą część protokołu poza szyfrowanymi rozmowami tekstowymi i z obrazem.</p>
<p xml:lang="pt">O Matrix é um protocolo de comunicações descentralizado, colocando de novo o utilizador no poder. De momento, o NeoChat implementa uma boa parte do protocolo, com a excepção das conversas encriptadas e as conversas de vídeo.</p>
<p xml:lang="pt-BR">O Matrix é um protocolo de comunicação descentralizado, colocando o usuário de volta no controle. Atualmente o NeoChat implementa grande parte do protocolo com a exceção de bate-papos criptografados e bate-papo por vídeo.</p>
<p xml:lang="ru">Matrix — это децентрализованный коммуникационный протокол, возвращающий пользователю контроль над своими данными. В настоящее время в приложении NeoChat реализована поддержка большей части протокола, за исключением зашифрованных чатов и видеочата.</p>
<p xml:lang="sk">Matrix je decentralizovaný komunikačný protokol, ktorý používateľovi vracia kontrolu. V súčasnosti NeoChat implementuje veľkú časť protokolu s výnimkou šifrovaných chatov a videohovorov.</p>
<p xml:lang="sl">Matrix je decentraliziran komunikacijski protokol, kjer ima uporabnik uporabnik kontrolo rabe. Trenutno ima NeoChat izveden velik del protokola z izjemo šifriranih klepetov in video klepetov.</p>
<p xml:lang="sv">Matrix är ett decentraliserat kommunikationsprotokoll, som ger tillbaka kontrollen till användaren. För närvarande implementerar NeoChat en stor del av protokollet, med undantag för krypterad chatt och videochatt.</p>
<p xml:lang="tr">Matrix; tam denetimi kullanıcıya bırakan, merkezi olmayan bir iletişim protokolüdür. Şu anda NeoChat, uçtan uca şifrelenmiş metin ve video sohbetleri dışında protokolün büyük bir bölümünü bünyesinde bulundurur.</p>
<p xml:lang="uk">Matrix — протокол децентралізованого спілкування, який передає контроль над даними користувачеві. У поточній версії NeoChat реалізовано більшу частину протоколу, окрім зашифрованого спілкування та відеоспілкування.</p>
<p xml:lang="x-test">xxMatrix is a decentralized communication protocol, putting the user back in control. Currently NeoChat implements large part of the protocol with the exception of encrypted chats and video chat.xx</p>
<p xml:lang="zh-CN">Matrix 是一个分布式通讯协议,使用户重新得到控制权。 目前,NeoChat 实现了协议的大部分,除了加密聊天和视频聊天。</p>
<p>NeoChat works both on mobile and desktop while providing a consistent user experience.</p>
<p xml:lang="ar">يعمل نيوتشات على كل من الأجهزة المحمولة وسطح المكتب مع توفير تجربة مستخدم متسقة.</p>
<p xml:lang="az">Vahid istifadəçi interfeysi ilə təmin olunan NeoChat, həm mobil telefonda həm də kompyuterlərdə işləyir.</p>
<p xml:lang="ca">El NeoChat funciona en els mòbils i a l'escriptori, proporcionant una experiència d'usuari coherent.</p>
<p xml:lang="ca-valencia">NeoChat funciona en els mòbils i en l'escriptori, proporcionant una experiència d'usuari coherent.</p>
<p xml:lang="de">NeoChat funktioniert sowohl auf Mobilgeräten als auch auf dem PC und bietet ein einheitliches Benutzererlebnis.</p>
<p xml:lang="el">Το NeoChat λειτουργεί και στα κινητά και στους υπολογιστές γραφείου παρέχοντας μια αδιάλειπτη εμπειρία χρήσης.</p>
<p xml:lang="en-GB">NeoChat works both on mobile and desktop while providing a consistent user experience.</p>
<p xml:lang="es">NeoChat funciona en móviles y en el escritorio a la vez que proporciona una experiencia de usuario consistente.</p>
<p xml:lang="eu">NeoChat mugikorretan eta mahaigainean dabil, erabiltzaile esperientzia koherentea eskainiz.</p>
<p xml:lang="fi">NeoChat toimii sekä mobiili- että työpöytäalustoilla tarjoten yhdenmukaisen käyttökokemuksen.</p>
<p xml:lang="fr">NeoChat fonctionne aussi bien sur les mobiles que sur les ordinateurs de bureau, tout en offrant une expérience utilisateur cohérente.</p>
<p xml:lang="hu">A NeoChat mobilon és asztali számítógépen is működik, egységes felhasználói élményt nyújtva.</p>
<p xml:lang="ia">NeoChat functiona sia sur mobile que ur scriptorio durante que forni un experientia de usator consistente.</p>
<p xml:lang="id">NeoChat berfungsi baik di ponsel dan desktop sambil memberikan pengalaman pengguna yang konsisten.</p>
<p xml:lang="ie">NeoChat supporta amb computatores e aparates mobil, ancor providente un consistent experientie de usator.</p>
<p xml:lang="it">NeoChat funziona sia su dispositivi mobili che desktop, fornendo un'esperienza utente coerente.</p>
<p xml:lang="ka">NeoChat მუშაობს როგორც მობილურ, ისე ჩვეულებრივ კომპიუტერებზე იმ დროს, როცა მომხმარებლის ინტერფეისი არ იცვლება.</p>
<p xml:lang="ko">NeoChat은 모바일과 데스크톱 모두에서 일관된 사용자 경험을 제공합니다.</p>
<p xml:lang="nl">NeoChat werkt zowel op de mobiel en het bureaublad met het leveren van een consistente gebruikerservaring.</p>
<p xml:lang="pl">NeoChat działa zarówno na urządzeniach przenośnych jak i biurkowych, zapewniając spójne wrażenia użytkownika</p>
<p xml:lang="pt">O NeoChat funciona tanto em dispositivos móveis como no computador, fornecendo uma experiência de utilizador consistente.</p>
<p xml:lang="pt-BR">O NeoChat funciona tanto no celular como no computador enquanto fornece uma experiência consistente ao usuário.</p>
<p xml:lang="ru">NeoChat работает как на мобильных устройствах, так и на настольных компьютерах, обеспечивая единый пользовательский интерфейс.</p>
<p xml:lang="sk">NeoChat funguje na mobilných aj stolových počítačoch a poskytuje konzistentný používateľský zážitok.</p>
<p xml:lang="sl">NeoChat deluje tako na mobilnih kot na namiznih platformah z zagotavljanjem konsistentne uporabniške izkušnje.</p>
<p xml:lang="sv">NeoChat fungerar både på mobil och skrivbord och tillhandahåller en konsekvent användarupplevelse.</p>
<p xml:lang="tr">NeoChat, hem masaüstü hem de taşınabilir ortamlarda çalışarak tutarlı bir kullanıcı deneyimi sunar.</p>
<p xml:lang="uk">NeoChat працює на мобільних пристроях та звичайних комп'ютерах, маючи однорідний інтерфейс на усіх підтримуваних пристроях.</p>
<p xml:lang="x-test">xxNeoChat works both on mobile and desktop while providing a consistent user experience.xx</p>
<p xml:lang="zh-CN">NeoChat 在移动设备和桌面上均可用,并提供一致的用户体验。</p>
<p xml:lang="ko">NeoChat은 분산형 인스턴트 메시징 통신 프로토콜인 Matrix 클라이언트입니다. 가족, 동료, 친구에게 텍스트 메시지, 동영상, 오디오 파일을 전송할 수 있습니다. KDE 프레임워크와 Kirigami를 사용하여 다양한 플랫폼에서 일관적인 사용자 경험을 제공합니다.</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="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="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="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="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="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="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="uk">NeoChat — клієнт Matrix, децентралізованого протоколу спілкування для миттєвого обміну повідомленнями. За його допомогою ви можете надсилати текстові повідомлення, відео та звукові файли вашій родин, колегами та друзям. У програмі використано бібліотеки KDE, зокрема Kirigami, для надання однорідного середовища на декількох програмних та апаратних платформах.</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="zh-TW">NeoChat 是去中心化即時通訊協定 Matrix 的一個用戶端。它讓您可以傳送文字訊息、影片、音訊檔案給您的家人、同事或朋友。NeoChat 使用 KDE frameworks尤其是 Kirigami來提供跨平台的響應式體驗。</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="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="en-GB">NeoChat aims to be a fully featured application for the Matrix specification. As such everything in the current stable specification with the notable exceptions of VoIP, threads and some aspects of End-to-End Encryption are supported. There are a few other smaller omissions due to the fact that the Matrix spec is constantly evolving but the aim remains to provide eventual support for the entire spec.</p>
<p xml:lang="eo">NeoChat celas esti plene kapabla aplikaĵo por la Matrix-specifo. Kiel tia, ĉio en la nuna stabila specifo kun la rimarkindaj esceptoj de VoIP, fadenoj kaj kelkaj aspektoj de Fin-al-Fina Ĉifrado estas subtenataj. Estas kelkaj aliaj pli malgrandaj preterlasoj pro la fakto, ke la Matrix-speco konstante evoluas, sed la celo restas provizi finfine subtenon por la tuta specifaĵo.</p>
<p xml:lang="es">NeoChat pretende ser una aplicación con todas las funciones para la especificación de Matrix. Como tal, admite todo en la especificación estable actual, con las notables excepciones de VoIP, subprocesos y algunas funciones de cifrado de extremo a extremo. Existen algunas omisiones menos importantes debido al hecho de que la especificación de Matrix está en constante evolución, pero el objetivo sigue siendo brindar compatibilidad final con toda la especificación.</p>
<p xml:lang="eu">«NeoChat»ek «Matrix» zehaztapenaren ezaugarri guztiak eskaintzen dituen aplikazio bat izan nahi du. Beraz, egungo zehaztapen egonkorrean dagoen guztiaren euskarria du, VoIP, hariak eta muturren artean zifratzeko salbuespen nabarmenekin. Badira beste ez-betetze txikiago batzuk, «Matrix»en zehaztapena etengabe eboluzioan dagoelako, baina azken helburua zehaztapen osoaren euskarria ematea izaten jarraitzen du.</p>
<p xml:lang="fi">NeoChat pyrkii olemaan Matrix-määritelmän täysominaisuuksinen sovellus, joten se tukee kaikkea nykyisessä vakaassa määritelmässä muutamaa huomattavaa poikkeusta lukuun ottamatta (VoIP, säikeet ja jotkin piirteet päästä päähän -salauksessa). Joitakin pienempiäkin puutteita on Matrix-määritelmän jatkuvan kehityksen vuoksi, mutta lopputavoitteena on tarjota määritelmän täysi tuki.</p>
<p xml:lang="fr">L'objectif de NeoChat est d'être une application complète pour le protocole Matrix. En tant que tel, tout dans la spécification stable actuelle avec les exceptions notables de VoIP, les processus et certains aspects du chiffrement de bout en bout sont pris en charge. Il y a quelques autres petites omissions en raison du fait que la spécification du protocole Matrix est en constante évolution. Cependant, l'objectif reste de fournir un soutien éventuel pour l'ensemble de la spécification.</p>
<p xml:lang="gl">NeoChat pretende ser unha aplicación completa para a especificación de Matrix. Coas excepcións de VoIP, conversas fiadas e algúns aspectos da cifraxe de extremo a extremo, a versión estábel segue as especificacións. Existen algunhas outras pequenas omisións debido ao feito de que Matrix está en continua evolución pero a intención é implementar a especificación completa.</p>
<p xml:lang="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="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="ko">NeoChat은 Matrix 표준을 따르는 프로그램을 목표로 합니다. 현재 안정 버전의 표준에서 제공하는 기능의 대부분을 지원하며, VoIP, 스레드, 일부 종단간 암호화와 같은 기능은 아직 지원하지 않습니다. Matrix 표준은 계속하여 진화 중이기 때문에 일부 기능이 빠져 있을 수도 있지만 장기적으로는 전체 표준을 지원하는 것이 목표입니다.</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="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="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="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="uk">Метою створення NeoChat є повноцінна реалізація програми для специфікації Matrix. Як наслідок, реалізовано усе у поточній стабільній специфікації, окрім голосового інтернет-зв'язку, потоків та деяких аспектів міжвузлового шифрування. Є також декілька інших незначних прогалин через те, що специфікація Matrix постійно змінюється, але метою лишається повна підтримка специфікації.</p>
<p xml:lang="x-test">xxNeoChat 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.xx</p>
<p xml:lang="zh-TW">NeoChat 以完整支援 Matrix 標準為目標,因此目前穩定版標準除了 VoIP、對話串與端對端加密的某些部分以外的所有部分都有支援。其他部分還有一些較小的不支援的部分這是因為 Matrix 標準隨時都在改進,但目標仍然時最終提供整個標準的完整支援。</p>
<p>Due to the nature of the Matrix specification development NeoChat also supports numerous unstable features. Currently these are:</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-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="en-GB">Due to the nature of the Matrix specification development NeoChat also supports numerous unstable features. Currently these are:</p>
<p xml:lang="eo">Pro la naturo de la Matrix-specifevoluo NeoChat ankaŭ subtenas multajn malstabilajn funkciojn. Nuntempe ĉi tiuj estas:</p>
<p xml:lang="es">Debido a la naturaleza del desarrollo de la especificación de Matrix, NeoChat también permite numerosas funciones no estables, como:</p>
<p xml:lang="eu">«Matrix» zehaztapenaren garapenaren izaeragatik, «Neo¢hat»ek ezaugarri ezegonkor ugari ere onartzen ditu. Gaur egun hauek:</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="gl">Debido á natureza do desenvolvemento da especificación de Matrix, NeoChat tamén inclúe varias funcionalidades non estábeis:</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="ka">Matrix-ის სპეციფიკაციის განვითარების ბუნების გამო NeoChat-ს ასევე აქვს უამრავი არასტაბილური ფუნქციაც. ახლა ისინია:</p>
<p xml:lang="ko">Matrix 표준 개발의 특징으로 인하여 NeoChat은 일부 실험적인 기능을 지원합니다. 현재 지원하는 기능은 다음과 같습니다.</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="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="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="ta">மேட்ரிக்ஸு நெறிமுறை வரையறுக்கப்படும் வித‍த்தின் காரணமாக, பல நிலையற்ற அம்சங்களையும் நியோச்சாட் ஆதரிக்கிறது. தற்போது ஆதரிக்கப்படுபவை:</p>
<p xml:lang="tr">NeoChat, Matrix belirtimi geliştirmesinin doğası gereği çok sayıda kararsız özelliği de destekler. Şu anda bunlar:</p>
<p xml:lang="uk">Через природу розробки специфікації Matrix, у NeoChat також передбачено підтримку численних нестабільних можливостей. У поточній версії цими можливостями є:</p>
<p xml:lang="x-test">xxDue to the nature of the Matrix specification development NeoChat also supports numerous unstable features. Currently these are:xx</p>
<p xml:lang="zh-TW">由於 Matrix 標準的開發流程的緣故NeoChat 也支援數個非穩定版的功能。目前這些功能是:</p>
<ul>
<li>Polls - MSC3381</li>
<li xml:lang="ar">التصويت - MSC3381</li>
<li xml:lang="ca">Enquestes - MSC3381</li>
<li xml:lang="ca-valencia">Enquestes - MSC3381</li>
<li xml:lang="en-GB">Polls - MSC3381</li>
<li xml:lang="eo">Enketoj - MSC3381</li>
<li xml:lang="es">Encuestas - MSC3381</li>
<li xml:lang="eu">Polls - MSC3381</li>
<li xml:lang="fi">Kyselyt MSC3381</li>
<li xml:lang="fr">Sondages - MSC3381</li>
<li xml:lang="gl">Enquisas — MSC3381</li>
<li xml:lang="ia">Inquestas - MSC3381</li>
<li xml:lang="it">Sondaggi - MSC3381</li>
<li xml:lang="ka">Polls - MSC3381</li>
<li xml:lang="ko">투표 - MSC3381</li>
<li xml:lang="nl">Polls - MSC3381</li>
<li xml:lang="nn">Avstemmingar  MSC3381</li>
<li xml:lang="pl">Ankiety - MSC3381</li>
<li xml:lang="pt">Inquéritos - MSC3381</li>
<li xml:lang="sl">Polls - MSC3381</li>
<li xml:lang="sv">Polls - MSC3381</li>
<li xml:lang="ta">வாக்கெடுப்புகள் - MSC3381</li>
<li xml:lang="tr">Anketler - MSC3381</li>
<li xml:lang="uk">Опитування - MSC3381</li>
<li xml:lang="x-test">xxPolls - MSC3381xx</li>
<li xml:lang="zh-TW">投票 - MSC3381</li>
<li>Sticker Packs - MSC2545</li>
<li xml:lang="ar">حزم الملصقات - MSC2545</li>
<li xml:lang="ca">Paquets d'adhesius - MSC2545</li>
<li xml:lang="ca-valencia">Paquets d'adhesius - MSC2545</li>
<li xml:lang="en-GB">Sticker Packs - MSC2545</li>
<li xml:lang="eo">Glumark-Pakoj - MSC2545</li>
<li xml:lang="es">Paquetes de pegatinas - MSC2545</li>
<li xml:lang="eu">Eranskailu paketeak - MSC2545</li>
<li xml:lang="fi">Tarrapakkaukset MSC2545</li>
<li xml:lang="fr">Paquets d'auto-collants - MSC2545</li>
<li xml:lang="gl">Paquetes de adhesivos — MSC2545</li>
<li xml:lang="ia">Etiquetta gummate (sticker) -MSC2545</li>
<li xml:lang="it">Pacchetti di adesivi - MSC2545</li>
<li xml:lang="ka">სტიკერების პაკეტები - MSC2545</li>
<li xml:lang="ko">스티커 팩 - MSC2545</li>
<li xml:lang="nl">Sticker Packs - MSC2545</li>
<li xml:lang="nn">Klistremerke-pakkar  MSC2545</li>
<li xml:lang="pl">Paczki naklejek - MSC2545</li>
<li xml:lang="pt">Pacotes de Autocolantes - MSC2545</li>
<li xml:lang="sl">Sticker Packs - MSC2545</li>
<li xml:lang="sv">Sticker Packs - MSC2545</li>
<li xml:lang="ta">ஒட்டி தொகுப்புகள் - MSC2545</li>
<li xml:lang="tr">Yapışkan Paketleri - MSC2545</li>
<li xml:lang="uk">Пакунки наліпок - MSC2545</li>
<li xml:lang="x-test">xxSticker Packs - MSC2545xx</li>
<li xml:lang="zh-TW">貼圖包 - MSC2545</li>
<li>Location Events - MSC3488</li>
<li xml:lang="ar">موقع الأحداث - MSC3488</li>
<li xml:lang="ca">Esdeveniments d'ubicació - MSC3488</li>
<li xml:lang="ca-valencia">Esdeveniments d'ubicació - MSC3488</li>
<li xml:lang="en-GB">Location Events - MSC3488</li>
<li xml:lang="eo">Lokaj Eventoj - MSC3488</li>
<li xml:lang="es">Eventos de ubicación - MSC3488</li>
<li xml:lang="eu">Kokaleku-gertaerak - MSC3488</li>
<li xml:lang="fi">Sijaintitapahtumat 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="ia">Eventos de Location - MSC3488</li>
<li xml:lang="it">Località eventi - MSC3488</li>
<li xml:lang="ka">მდებარეობის მოვლენები - MSC3488</li>
<li xml:lang="ko">위치 이벤트 - MSC3488</li>
<li xml:lang="nl">Locatie gebeurtenissen - MSC3488</li>
<li xml:lang="nn">Posisjonshendingar  MSC3488</li>
<li xml:lang="pl">Wydarzenia w miejscach - MSC3488</li>
<li xml:lang="pt">Eventos com Localizações - MSC3488</li>
<li xml:lang="sl">Location Events - MSC3488</li>
<li xml:lang="sv">Location Events - MSC3488</li>
<li xml:lang="ta">இட நிகழ்வுகள் - MSC3488</li>
<li xml:lang="tr">Konum Etkinlikleri - MSC3488</li>
<li xml:lang="uk">Місцеві зустрічі - MSC3488</li>
<li xml:lang="x-test">xxLocation Events - MSC3488xx</li>
<li xml:lang="zh-TW">位置事件 - MSC3488</li>
</ul>
</description>
<url type="homepage">https://apps.kde.org/neochat/</url>
<url type="bugtracker">https://bugs.kde.org/buglist.cgi?component=General&amp;product=NeoChat</url>
<url type="homepage">https://apps.kde.org/neochat</url>
<url type="bugtracker">https://bugs.kde.org/enter_bug.cgi?product=NeoChat</url>
<categories>
<category>Network</category>
</categories>
@@ -187,10 +247,12 @@
<developer_name xml:lang="de">Die KDE-Gemeinschaft</developer_name>
<developer_name xml:lang="el">Η Κοινότητα του KDE</developer_name>
<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>
@@ -208,15 +270,22 @@
<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>
<project_license>GPL-3.0</project_license>
<custom>
<value key="KDE::matrix">#neochat:kde.org</value>
<value key="KDE::windows_store">https://www.microsoft.com/store/apps/9PNXWVNRC29H</value>
<value key="KDE::mastodon">https://kde.social/@neochat</value>
<value key="KDE::windows_store::StoreLogo9x16">https://invent.kde.org/network/neochat/-/raw/master/icons/windows/storelogo-720x1080.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::PromotionalArt16x9">https://invent.kde.org/network/neochat/-/raw/master/icons/windows/promoimage-1920x1080.png</value>
</custom>
<launchable type="desktop-id">org.kde.neochat.desktop</launchable>
<screenshots>
@@ -226,11 +295,95 @@
<screenshot type="default">
<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 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="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="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="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="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 environment="windows">
<image>https://cdn.kde.org/screenshots/neochat/NeoChat-Windows-Login.png</image>
<caption>Login screen</caption>
<caption xml:lang="ar">شاشة الدخول</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="cs">Přihlašovací obrazovka</caption>
<caption xml:lang="eo">Ensaluta ekrano</caption>
<caption xml:lang="es">Pantalla de inicio de sesión</caption>
<caption xml:lang="eu">Saio-hasteko pantaila</caption>
<caption xml:lang="fi">Kirjautumisnäkymä</caption>
<caption xml:lang="fr">Écran de connexion</caption>
<caption xml:lang="gl">Pantalla de identificación.</caption>
<caption xml:lang="ia">Schermo de accesso</caption>
<caption xml:lang="it">Schermata di accesso</caption>
<caption xml:lang="ka">შესვლის ეკრანი</caption>
<caption xml:lang="ko">로그인 화면</caption>
<caption xml:lang="nl">Aanmeldscherm</caption>
<caption xml:lang="nn">Innloggingsbilete</caption>
<caption xml:lang="pl">Ekran logowania</caption>
<caption xml:lang="pt">Ecrã de autenticação</caption>
<caption xml:lang="sl">Prijavni zaslon</caption>
<caption xml:lang="sv">Inloggningsfönster</caption>
<caption xml:lang="ta">நுழைவுத் திரை</caption>
<caption xml:lang="tr">Oturum açma ekranı</caption>
<caption xml:lang="uk">Вікно входу</caption>
<caption xml:lang="x-test">xxLogin screenxx</caption>
<caption xml:lang="zh-TW">登入畫面</caption>
</screenshot>
</screenshots>
<content_rating type="oars-1.1">
<content_attribute id="social-chat">intense</content_attribute>
</content_rating>
<releases>
<release version="23.08.4" date="2023-12-07"/>
<release version="23.08.3" date="2023-11-09"/>
<release version="23.08.2" date="2023-10-12"/>
<release version="23.08.0" date="2023-08-24">
<url>https://kde.org/announcements/gear/23.08.0/#neochathttpsappskdeorgneochat</url>
<description>
<p>Apart from a visual overhaul, NeoChat can now display location events and also a map with the location of all the users currently broadcasting their location using Itineray's Matrix integration. Great for locating where your friends are.</p>
</description>
</release>
<release version="23.04.3" date="2023-07-06"/>
<release version="23.04.2" date="2023-06-08"/>
<release version="23.04.1" date="2023-05-11"/>
<release version="23.04.0" date="2023-04-20">
<url>https://kde.org/announcements/gear/23.04.0/#neochathttpsappskdeorgneochat</url>
<description>
<p>NeoChat improves its design with tweaks that provide a more compact layout and a simpler menu which works better for the collapsed room list.</p>
<p>We have also improved the video controls, added a new command /knock &lt;room-id&gt; to send a knock event to a room, and you can now edit a prior message inline, within the chat pane.</p>
<p>Other usability improvements include an overhaul of the keyboard navigation and shortcuts like Ctrl+PgUp/PgDn that allow you to skip from room to room.</p>
</description>
<artifacts>
<artifact type="binary" platform="x86_64-windows-msvc">
<location>https://download.kde.org/stable/release-service/23.04.0/windows/neochat-23.04.0-512-windows-cl-msvc2019-x86_64.exe</location>
<checksum type="sha256">85e17fdd9b128bfdd171a93b11f7a95febeff0a00df9261df11f6ff67637686d</checksum>
<size type="download">58032464</size>
</artifact>
</artifacts>
</release>
<release version="23.01" date="2023-01-30">
<url>https://plasma-mobile.org/2023/01/30/january-blog-post/</url>
<description>

View File

@@ -4,6 +4,7 @@
Version=1.5
Name=NeoChat
Name[ar]=نيوتشات
Name[ast]=NeoChat
Name[az]=NeoChat
Name[ca]=NeoChat
Name[ca@valencia]=NeoChat
@@ -11,10 +12,12 @@ Name[cs]=NeoChat
Name[de]=NeoChat
Name[el]=NeoChat
Name[en_GB]=NeoChat
Name[eo]=NeoChat
Name[es]=NeoChat
Name[eu]=NeoChat
Name[fi]=NeoChat
Name[fr]=NeoChat
Name[gl]=NeoChat
Name[hu]=NeoChat
Name[ia]=Neochat
Name[id]=NeoChat
@@ -39,6 +42,7 @@ Name[tr]=NeoChat
Name[uk]=NeoChat
Name[x-test]=xxNeoChatxx
Name[zh_CN]=NeoChat
Name[zh_TW]=NeoChat
GenericName=Matrix Client
GenericName[ar]=عميل ماتركس
GenericName[az]=Matrix Müştərisi
@@ -48,10 +52,12 @@ GenericName[cs]=Klient protokolu Matrix
GenericName[de]=Matrix-Programm
GenericName[el]=Εφαρμογή του Matrix
GenericName[en_GB]=Matrix Client
GenericName[eo]=Matrix-Kliento
GenericName[es]=Cliente para Matrix
GenericName[eu]=Matrix bezeroa
GenericName[fi]=Matrix-asiakas
GenericName[fr]=Client « Matrix »
GenericName[gl]=Cliente de Matrix
GenericName[hu]=Matrix kliens
GenericName[ia]=Cliente de Matrice
GenericName[id]=Klien Matrix
@@ -76,6 +82,7 @@ GenericName[tr]=Matrix İstemcisi
GenericName[uk]=Клієнт Matrix
GenericName[x-test]=xxMatrix Clientxx
GenericName[zh_CN]=Matrix 客户端
GenericName[zh_TW]=Matrix 用戶端
Comment=Client for the Matrix protocol
Comment[ar]=عميل لميفاق ماتركس
Comment[az]=Matrix protokolu üçün müştəri
@@ -84,10 +91,12 @@ Comment[ca@valencia]=Client per al protocol Matrix
Comment[de]=Programm für das Matrix-Protokoll
Comment[el]=Πελάτης για το πρωτόκολλο Matrix
Comment[en_GB]=Client for the Matrix protocol
Comment[eo]=Kliento por la Matrix-protokolo
Comment[es]=Cliente para el protocolo Matrix
Comment[eu]=Matrix protokolorako bezeroa
Comment[fi]=Asiakas Matrix-yhteyskäytännölle
Comment[fr]=Client pour le protocole « Matrix »
Comment[gl]=Cliente para o protocolo Matrix.
Comment[hu]=Kliens a Matrix protokollhoz
Comment[ia]=Cliente per le protocollo de Matrix
Comment[id]=Klien untuk protokol Matrix
@@ -97,7 +106,7 @@ Comment[ka]=კლიენტი Matrix-ის პროტოკოლის
Comment[ko]=Matrix 프로토콜용 클라이언트
Comment[lt]=Matrix protokolo kliento programa
Comment[nl]=Client voor het Matrix-protocol
Comment[nn]=Lynmeldings­klient for Matrix-protokollen
Comment[nn]=Klient for Matrix-protokollen
Comment[pa]=ਮੈਟਰਿਕਸ ਪਰੋਟੋਕਾਲ ਲਈ ਕਲਾਈਂਟ ਹੈ
Comment[pl]=Program obsługi protokołu Matriksa
Comment[pt]=Cliente para o protocolo Matrix
@@ -112,6 +121,7 @@ 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;
Exec=neochat %u
Terminal=false

View File

@@ -1 +1,8 @@
<svg width="22" height="22" fill="none" version="1.1" id="svg13" xmlns="http://www.w3.org/2000/svg"><style type="text/css" id="current-color-scheme">.ColorScheme-Text{color:#232629}</style><path class="ColorScheme-Text" style="fill:currentColor;fill-opacity:1;stroke:none" fill-rule="evenodd" clip-rule="evenodd" d="M2 4h18v11H6.681L3 18.067V15H2zm1 10h1v1.933L6.319 14H19V5H3z" id="path3"/><path class="ColorScheme-Text" style="fill:currentColor;fill-opacity:1;stroke:none" id="rect5" d="M4 7h9v1H4z"/><path class="ColorScheme-Text" style="fill:currentColor;fill-opacity:1;stroke:none" id="rect7" d="M4 9h7v1H4z"/><path class="ColorScheme-Text" style="fill:currentColor;fill-opacity:1;stroke:none" id="rect9" d="M4 11h5v1H4z"/><path class="ColorScheme-Text" style="fill:currentColor;fill-opacity:1;stroke:none" fill-rule="evenodd" clip-rule="evenodd" d="m16 15.293-1.147-1.146-.707.707 2.853 2.853V14.5h-1z" id="path11"/></svg>
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<style type="text/css" id="current-color-scheme">.ColorScheme-Text{color:#232629}</style>
<path class="ColorScheme-Text" fill-rule="evenodd" clip-rule="evenodd" d="M3 3H19V14H8.68787L4 18.1019V14H3V3ZM4 13H5V15.8981L8.31213 13H18V4H4V13Z" fill="currentColor"/>
<path class="ColorScheme-Text" fill-rule="evenodd" clip-rule="evenodd" d="M17 15.2929L14.8536 13.1465L14.1465 13.8536L18 17.7071V13.5H17V15.2929Z" fill="currentColor"/>
<path class="ColorScheme-Text" d="M5 6H15V7H5V6Z" fill="currentColor"/>
<path class="ColorScheme-Text" d="M5 8H13V9H5V8Z" fill="currentColor"/>
<path class="ColorScheme-Text" d="M5 10H11V11H5V10Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 928 B

After

Width:  |  Height:  |  Size: 752 B

File diff suppressed because it is too large Load Diff

4558
po/ast/neochat.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -97,7 +97,7 @@ SPDX-License-Identifier: CC-BY-SA-4.0
>Vegeu també</title>
<simplelist>
<member
>Una llista de les preguntes més freqüents quan a Matrix <ulink url="https://matrix.org/faq/"
>Una llista de les preguntes més freqüents quant a Matrix <ulink url="https://matrix.org/faq/"
>https://matrix.org/faq/</ulink
> </member>
<member

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4625
po/eo/neochat.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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 % Swedish "INCLUDE">
]>
<!--
SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
SPDX-License-Identifier: CC-BY-SA-4.0
-->
<refentry lang="&language;">
<refentryinfo>
<title
>NeoChat användarmanual</title>
<author
><firstname
>Carl</firstname
><surname
>Schwan</surname
> <contrib
>NeoChat manualsida.</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
>Klient för att interagera med meddelandeprotokollet 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
>Beskrivning</title>
<para
><command
>neochat</command
> är ett chattprogram för protokollet matrix som fungerar både på skrivbord och mobil. </para>
</refsect1>
<refsect1 id="options"
><title
>Väljare</title>
<variablelist>
<varlistentry>
<term
><option
>URI</option
></term>
<listitem>
<para
>Matrix webbadress för en användare eller ett rum, t.ex. matrix:u/användare:exempel.org. Det gör att NeoChat försöker öppna det angivna rummet eller konversationen. </para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 id="bug">
<title
>Rapportera fel</title>
<para
>Rapportera fel och funktionsönskemål på <ulink url="https://bugs.kde.org/enter_bug.cgi?product=NeoChat&amp;component=General"
>https://bugs.kde.org/enter_bug.cgi?product=NeoChat&amp;component=General</ulink
></para>
</refsect1>
<refsect1>
<title
>Se också</title>
<simplelist>
<member
>En lista över vanliga frågor om 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
>Copyright</title>
<para
>Copyright &copy; 2020-2022 Tobias Fella </para>
<para
>Copyright &copy; 2020-2022 Carl Schwan </para>
<para
>Licens: GNU General Public Version 3 eller senare &lt;<ulink url="https://wwwgnuorg/licenses/gpl-html"
>http://www.gnu.org/licenses/gpl-3.0.html</ulink
>&gt;</para>
</refsect1>
</refentry>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,96 +5,392 @@
add_library(neochat STATIC
controller.cpp
controller.h
actionshandler.cpp
actionshandler.h
models/emojimodel.cpp
models/emojimodel.h
emojitones.cpp
emojitones.h
models/customemojimodel.cpp
models/customemojimodel.h
clipboard.cpp
clipboard.h
matriximageprovider.cpp
matriximageprovider.h
models/messageeventmodel.cpp
models/messageeventmodel.h
models/messagefiltermodel.cpp
models/messagefiltermodel.h
models/roomlistmodel.cpp
models/roomlistmodel.h
models/sortfilterspacelistmodel.cpp
models/sortfilterspacelistmodel.h
models/accountemoticonmodel.cpp
models/accountemoticonmodel.h
spacehierarchycache.cpp
spacehierarchycache.h
roommanager.cpp
roommanager.h
neochatroom.cpp
neochatuser.cpp
neochatroom.h
models/userlistmodel.cpp
models/userlistmodel.h
models/userfiltermodel.cpp
models/userfiltermodel.h
models/publicroomlistmodel.cpp
models/publicroomlistmodel.h
models/spacechildrenmodel.cpp
models/spacechildrenmodel.h
models/spacechildsortfiltermodel.cpp
models/spacechildsortfiltermodel.h
models/spacetreeitem.cpp
models/spacetreeitem.h
models/userdirectorylistmodel.cpp
models/keywordnotificationrulemodel.cpp
models/userdirectorylistmodel.h
models/pushrulemodel.cpp
models/pushrulemodel.h
models/emoticonfiltermodel.cpp
models/emoticonfiltermodel.h
notificationsmanager.cpp
notificationsmanager.h
models/sortfilterroomlistmodel.cpp
models/sortfilterroomlistmodel.h
chatdocumenthandler.cpp
chatdocumenthandler.h
models/devicesmodel.cpp
filetypesingleton.cpp
models/devicesmodel.h
models/devicesproxymodel.cpp
filetype.cpp
filetype.h
login.cpp
stickerevent.cpp
login.h
models/webshortcutmodel.cpp
models/webshortcutmodel.h
blurhash.cpp
blurhash.h
blurhashimageprovider.cpp
joinrulesevent.cpp
models/collapsestateproxymodel.cpp
blurhashimageprovider.h
models/mediamessagefiltermodel.cpp
models/mediamessagefiltermodel.h
urlhelper.cpp
urlhelper.h
windowcontroller.cpp
windowcontroller.h
linkpreviewer.cpp
linkpreviewer.h
models/completionmodel.cpp
models/completionmodel.h
models/completionproxymodel.cpp
models/completionproxymodel.h
models/actionsmodel.cpp
models/actionsmodel.h
models/serverlistmodel.cpp
models/serverlistmodel.h
models/statemodel.cpp
models/statemodel.h
models/statefiltermodel.cpp
models/statefiltermodel.h
filetransferpseudojob.cpp
filetransferpseudojob.h
models/searchmodel.cpp
models/searchmodel.h
texthandler.cpp
texthandler.h
logger.cpp
logger.h
models/stickermodel.cpp
models/stickermodel.h
models/imagepacksmodel.cpp
models/imagepacksmodel.h
events/imagepackevent.cpp
events/imagepackevent.h
events/joinrulesevent.cpp
events/joinrulesevent.h
models/reactionmodel.cpp
models/reactionmodel.h
delegatesizehelper.cpp
delegatesizehelper.h
models/livelocationsmodel.cpp
models/livelocationsmodel.h
models/locationsmodel.cpp
models/locationsmodel.h
locationhelper.cpp
locationhelper.h
events/pollevent.cpp
pollhandler.cpp
utils.h
registration.cpp
neochatconnection.cpp
neochatconnection.h
jobs/neochatdeactivateaccountjob.cpp
jobs/neochatdeactivateaccountjob.h
jobs/neochatdeletedevicejob.cpp
jobs/neochatdeletedevicejob.h
jobs/neochatchangepasswordjob.cpp
jobs/neochatchangepasswordjob.h
mediasizehelper.cpp
mediasizehelper.h
eventhandler.cpp
enums/delegatetype.h
roomlastmessageprovider.cpp
roomlastmessageprovider.h
chatbarcache.cpp
chatbarcache.h
colorschemer.cpp
colorschemer.h
models/notificationsmodel.cpp
models/notificationsmodel.h
models/timelinemodel.cpp
models/timelinemodel.h
enums/pushrule.h
)
qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN
QML_FILES
qml/main.qml
qml/AccountMenu.qml
qml/ExploreComponent.qml
qml/ExploreComponentMobile.qml
qml/ContextMenu.qml
qml/CollapsedRoomDelegate.qml
qml/RoomDelegate.qml
qml/RoomListPage.qml
qml/SpaceListContextMenu.qml
qml/UserInfo.qml
qml/UserInfoDesktop.qml
qml/RoomPage.qml
qml/RoomWindow.qml
qml/JoinRoomPage.qml
qml/ManualRoomDialog.qml
qml/ExplorerDelegate.qml
qml/InviteUserPage.qml
qml/StartChatPage.qml
qml/ImageEditorPage.qml
qml/WelcomePage.qml
qml/General.qml
qml/RoomSecurity.qml
qml/PushNotification.qml
qml/Categories.qml
qml/Permissions.qml
qml/NeochatMaximizeComponent.qml
qml/FancyEffectsContainer.qml
qml/TypingPane.qml
qml/QuickSwitcher.qml
qml/HoverActions.qml
qml/ChatBar.qml
qml/AttachmentPane.qml
qml/ReplyPane.qml
qml/CompletionMenu.qml
qml/PieProgressBar.qml
qml/QuickFormatBar.qml
qml/RoomData.qml
qml/ServerData.qml
qml/EmojiPicker.qml
qml/TimelineDelegate.qml
qml/ReplyComponent.qml
qml/StateDelegate.qml
qml/RichLabel.qml
qml/MessageDelegate.qml
qml/Bubble.qml
qml/SectionDelegate.qml
qml/VideoDelegate.qml
qml/ReactionDelegate.qml
qml/LinkPreviewDelegate.qml
qml/AudioDelegate.qml
qml/FileDelegate.qml
qml/ImageDelegate.qml
qml/EncryptedDelegate.qml
qml/EventDelegate.qml
qml/TextDelegate.qml
qml/ReadMarkerDelegate.qml
qml/PollDelegate.qml
qml/MimeComponent.qml
qml/StateComponent.qml
qml/MessageEditComponent.qml
qml/AvatarFlow.qml
qml/LoginStep.qml
qml/Login.qml
qml/Homeserver.qml
qml/Username.qml
qml/RegisterPassword.qml
qml/Captcha.qml
qml/Terms.qml
qml/Email.qml
qml/Password.qml
qml/LoginRegister.qml
qml/Loading.qml
qml/LoginMethod.qml
qml/Sso.qml
qml/UserDetailDialog.qml
qml/CreateRoomDialog.qml
qml/EmojiDialog.qml
qml/OpenFileDialog.qml
qml/KeyVerificationDialog.qml
qml/ConfirmLogoutDialog.qml
qml/PowerLevelDialog.qml
qml/Message.qml
qml/EmojiItem.qml
qml/EmojiRow.qml
qml/EmojiSas.qml
qml/ConfirmDeactivateAccountDialog.qml
qml/VerificationCanceled.qml
qml/GlobalMenu.qml
qml/EditMenu.qml
qml/MessageDelegateContextMenu.qml
qml/FileDelegateContextMenu.qml
qml/MessageSourceSheet.qml
qml/ReportSheet.qml
qml/SettingsPage.qml
qml/ThemeRadioButton.qml
qml/ColorScheme.qml
qml/GeneralSettingsPage.qml
qml/EmoticonsPage.qml
qml/EmoticonEditorPage.qml
qml/EmoticonFormCard.qml
qml/GlobalNotificationsPage.qml
qml/NotificationRuleItem.qml
qml/AppearanceSettingsPage.qml
qml/AccountsPage.qml
qml/AccountEditorPage.qml
qml/DevicesPage.qml
qml/DeviceDelegate.qml
qml/DevicesCard.qml
qml/About.qml
qml/AboutKDE.qml
qml/SonnetConfigPage.qml
qml/NetworkProxyPage.qml
qml/DevtoolsPage.qml
qml/ConfirmEncryptionDialog.qml
qml/RemoveSheet.qml
qml/BanSheet.qml
qml/EmojiTonesPicker.qml
qml/EmojiDelegate.qml
qml/EmojiGrid.qml
qml/SearchPage.qml
qml/LocationDelegate.qml
qml/LocationChooser.qml
qml/TimelineView.qml
qml/InvitationView.qml
qml/AvatarTabButton.qml
qml/SpaceDrawer.qml
qml/OsmLocationPlugin.qml
qml/LiveLocationDelegate.qml
qml/FullScreenMap.qml
qml/LocationsPage.qml
qml/LocationMapItem.qml
qml/RoomDrawer.qml
qml/RoomDrawerPage.qml
qml/DirectChatDrawerHeader.qml
qml/GroupChatDrawerHeader.qml
qml/RoomInformation.qml
qml/RoomMedia.qml
qml/ChooseRoomDialog.qml
qml/ShareAction.qml
qml/SpaceHomePage.qml
qml/SpaceHierarchyDelegate.qml
qml/RemoveChildDialog.qml
qml/SelectParentDialog.qml
qml/Security.qml
qml/QrCodeMaximizeComponent.qml
qml/SelectSpacesDialog.qml
qml/AttachDialog.qml
qml/NotificationsView.qml
qml/LoadingDelegate.qml
qml/TimelineEndDelegate.qml
RESOURCES
qml/confetti.png
qml/glowdot.png
)
if(WIN32)
set_target_properties(neochat PROPERTIES OUTPUT_NAME "neochatlib")
endif()
ecm_qt_declare_logging_category(neochat
HEADER "messageeventmodel_logging.h"
IDENTIFIER "MessageEvent"
CATEGORY_NAME "org.kde.neochat.messageeventmodel"
DESCRIPTION "Neochat: messageeventmodel"
DEFAULT_SEVERITY Info
EXPORT NEOCHAT
)
ecm_qt_declare_logging_category(neochat
HEADER "eventhandler_logging.h"
IDENTIFIER "EventHandling"
CATEGORY_NAME "org.kde.neochat.eventhandler"
DEFAULT_SEVERITY Info
)
ecm_qt_declare_logging_category(neochat
HEADER "chatdocumenthandler_logging.h"
IDENTIFIER "ChatDocumentHandling"
CATEGORY_NAME "org.kde.neochat.chatdocumenthandler"
DEFAULT_SEVERITY Info
)
add_executable(neochat-app
main.cpp
res.qrc
)
if(TARGET Qt::WebView)
target_link_libraries(neochat-app PUBLIC Qt::WebView)
target_compile_definitions(neochat-app PUBLIC -DHAVE_WEBVIEW)
endif()
target_include_directories(neochat-app PRIVATE ${CMAKE_BINARY_DIR})
target_link_libraries(neochat-app PRIVATE
neochat
)
if(Quotient_VERSION_MINOR GREATER 6)
target_compile_definitions(neochat PUBLIC QUOTIENT_07)
target_sources(neochat PRIVATE pollevent.cpp pollhandler.cpp)
else()
target_compile_definitions(neochat PUBLIC QUOTIENT_VERSION=\"${Quotient_VERSION}\")
target_sources(neochat PRIVATE neochataccountregistry.cpp)
endif()
ecm_add_app_icon(NEOCHAT_ICON ICONS ${CMAKE_SOURCE_DIR}/128-logo.png)
target_sources(neochat-app PRIVATE ${NEOCHAT_ICON})
if(NOT ANDROID)
target_sources(neochat PRIVATE colorschemer.cpp)
if (NOT WIN32 AND NOT APPLE)
target_sources(neochat PRIVATE trayicon_sni.cpp)
target_sources(neochat PRIVATE trayicon_sni.cpp trayicon_sni.h)
target_link_libraries(neochat PRIVATE KF6::StatusNotifierItem)
else()
target_sources(neochat PRIVATE trayicon.cpp)
target_sources(neochat PRIVATE trayicon.cpp trayicon.h)
endif()
target_link_libraries(neochat PUBLIC KF${QT_MAJOR_VERSION}::ConfigWidgets KF${QT_MAJOR_VERSION}::WindowSystem)
target_compile_definitions(neochat PUBLIC -DHAVE_COLORSCHEME)
target_link_libraries(neochat PUBLIC KF6::WindowSystem ICU::uc)
target_compile_definitions(neochat PUBLIC -DHAVE_WINDOWSYSTEM)
target_compile_definitions(neochat PUBLIC -DHAVE_ICU)
endif()
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
target_sources(neochat-app PRIVATE res_desktop.qrc)
target_compile_definitions(neochat PUBLIC -DHAVE_RUNNER)
target_compile_definitions(neochat PUBLIC -DHAVE_X11)
target_sources(neochat PRIVATE runner.cpp)
else()
target_sources(neochat-app PRIVATE res_android.qrc)
endif()
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR})
target_link_libraries(neochat PUBLIC Qt::Core Qt::Quick Qt::Qml Qt::Gui Qt::Multimedia Qt::Network Qt::QuickControls2 KF${QT_MAJOR_VERSION}::I18n KF${QT_MAJOR_VERSION}::Kirigami2 KF${QT_MAJOR_VERSION}::Notifications KF${QT_MAJOR_VERSION}::ConfigCore KF${QT_MAJOR_VERSION}::ConfigGui KF${QT_MAJOR_VERSION}::CoreAddons KF${QT_MAJOR_VERSION}::SonnetCore KF${QT_MAJOR_VERSION}::ItemModels Quotient cmark::cmark ${QTKEYCHAIN_LIBRARIES} QCoro::Core)
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/models ${CMAKE_CURRENT_SOURCE_DIR}/enums)
target_link_libraries(neochat PUBLIC
Qt::Core
Qt::Quick
Qt::Qml
Qt::Gui
Qt::Multimedia
Qt::Network
Qt::QuickControls2
KF6::I18n
KF6::Kirigami
KF6::Notifications
KF6::ConfigCore
KF6::ConfigGui
KF6::CoreAddons
KF6::SonnetCore
KF6::ColorScheme
KF6::ItemModels
QuotientQt6
cmark::cmark
QCoro::Core
QCoro::Network
)
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)
if(NEOCHAT_FLATPAK)
@@ -179,9 +475,25 @@ if(ANDROID)
"preferences-desktop-notification"
"computer-symbolic"
"gps"
"system-users-symbolic"
"map-flat"
"documentinfo"
"view-list-details"
"go-previous"
"mail-forward-symbolic"
"dialog-warning-symbolic"
"object-rotate-left"
"object-rotate-right"
"add-subtitle"
"security-low"
"security-low-symbolic"
"kde"
"list-remove-symbolic"
"edit-delete"
)
ecm_add_android_apk(neochat-app ANDROID_DIR ${CMAKE_SOURCE_DIR}/android)
else()
target_link_libraries(neochat PUBLIC Qt::Widgets KF${QT_MAJOR_VERSION}::KIOWidgets)
target_link_libraries(neochat PUBLIC Qt::Widgets KF6::KIOWidgets)
install(FILES neochat.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR})
endif()
@@ -189,18 +501,27 @@ if(NOT ANDROID)
set_target_properties(neochat-app PROPERTIES OUTPUT_NAME "neochat")
endif()
if(TARGET KF${QT_MAJOR_VERSION}::DBusAddons)
target_link_libraries(neochat PUBLIC KF${QT_MAJOR_VERSION}::DBusAddons)
if(TARGET KF6::DBusAddons)
target_link_libraries(neochat PUBLIC KF6::DBusAddons)
target_compile_definitions(neochat PUBLIC -DHAVE_KDBUSADDONS)
endif()
if (TARGET KF${QT_MAJOR_VERSION}::KIOWidgets)
if (TARGET KF6::KIOWidgets)
target_compile_definitions(neochat PUBLIC -DHAVE_KIO)
endif()
if (TARGET KUnifiedPush)
target_compile_definitions(neochat PUBLIC -DHAVE_KUNIFIEDPUSH)
target_link_libraries(neochat PUBLIC KUnifiedPush)
if (NOT ANDROID)
configure_file(org.kde.neochat.service.in ${CMAKE_CURRENT_BINARY_DIR}/org.kde.neochat.service)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.neochat.service DESTINATION ${KDE_INSTALL_DBUSSERVICEDIR})
endif()
endif()
install(TARGETS neochat-app ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
install(FILES plasma-runner-neochat.desktop DESTINATION ${KDE_INSTALL_DATAROOTDIR}/krunner/dbusplugins)
endif()

View File

@@ -3,23 +3,16 @@
#include "actionshandler.h"
#include "controller.h"
#include <csapi/joining.h>
#include <events/roommemberevent.h>
#include <Quotient/csapi/joining.h>
#include <Quotient/events/roommemberevent.h>
#include <cmark.h>
#include <KLocalizedString>
#include <QStringBuilder>
#include "controller.h"
#include "models/actionsmodel.h"
#include "models/customemojimodel.h"
#include "neochatconfig.h"
#include "neochatroom.h"
#include "neochatuser.h"
#include "roommanager.h"
#include "texthandler.h"
using namespace Quotient;
@@ -44,45 +37,30 @@ void ActionsHandler::setRoom(NeoChatRoom *room)
Q_EMIT roomChanged();
}
void ActionsHandler::handleNewMessage()
void ActionsHandler::handleMessageEvent(ChatBarCache *chatBarCache)
{
checkEffects(m_room->chatBoxText());
if (!m_room->chatBoxAttachmentPath().isEmpty()) {
QUrl url(m_room->chatBoxAttachmentPath());
auto path = url.isLocalFile() ? url.toLocalFile() : url.toString();
m_room->uploadFile(path, m_room->chatBoxText().isEmpty() ? path.mid(path.lastIndexOf('/') + 1) : m_room->chatBoxText());
m_room->setChatBoxAttachmentPath({});
m_room->setChatBoxText({});
if (!m_room || !chatBarCache) {
qWarning() << "ActionsHandler::handleMessageEvent - called with m_room and/or chatBarCache set to nullptr.";
return;
}
QString handledText = m_room->chatBoxText();
handledText = handleMentions(handledText);
handleMessage(m_room->chatBoxText(), handledText);
}
void ActionsHandler::handleEdit()
{
checkEffects(m_room->editText());
QString handledText = m_room->editText();
handledText = handleMentions(handledText, true);
handleMessage(m_room->editText(), handledText, true);
}
QString ActionsHandler::handleMentions(QString handledText, const bool &isEdit)
{
if (!m_room) {
return QString();
checkEffects(chatBarCache->text());
if (!chatBarCache->attachmentPath().isEmpty()) {
QUrl url(chatBarCache->attachmentPath());
auto path = url.isLocalFile() ? url.toLocalFile() : url.toString();
m_room->uploadFile(QUrl(path), chatBarCache->text().isEmpty() ? path.mid(path.lastIndexOf(u'/') + 1) : chatBarCache->text());
chatBarCache->setAttachmentPath({});
chatBarCache->setText({});
return;
}
QVector<Mention> *mentions;
if (isEdit) {
mentions = m_room->editMentions();
} else {
mentions = m_room->mentions();
}
QString handledText = chatBarCache->text();
handledText = handleMentions(handledText, chatBarCache->mentions());
handleMessage(m_room->mainCache()->text(), handledText, chatBarCache);
}
QString ActionsHandler::handleMentions(QString handledText, QList<Mention> *mentions)
{
std::sort(mentions->begin(), mentions->end(), [](const auto &a, const auto &b) -> bool {
return a.cursor.anchor() > b.cursor.anchor();
});
@@ -93,17 +71,17 @@ QString ActionsHandler::handleMentions(QString handledText, const bool &isEdit)
}
handledText = handledText.replace(mention.cursor.anchor(),
mention.cursor.position() - mention.cursor.anchor(),
QStringLiteral("[%1](https://matrix.to/#/%2)").arg(mention.text, mention.id));
QStringLiteral("[%1](https://matrix.to/#/%2)").arg(mention.text.toHtmlEscaped(), mention.id));
}
mentions->clear();
return handledText;
}
void ActionsHandler::handleMessage(const QString &text, QString handledText, const bool &isEdit)
void ActionsHandler::handleMessage(const QString &text, QString handledText, ChatBarCache *chatBarCache)
{
if (NeoChatConfig::allowQuickEdit()) {
QRegularExpression sed("^s/([^/]*)/([^/]*)(/g)?$");
QRegularExpression sed(QStringLiteral("^s/([^/]*)/([^/]*)(/g)?$"));
auto match = sed.match(text);
if (match.hasMatch()) {
const QString regex = match.captured(1);
@@ -119,13 +97,13 @@ void ActionsHandler::handleMessage(const QString &text, QString handledText, con
} else {
originalString = event->plainBody();
}
if (flags == "/g") {
m_room->postHtmlMessage(handledText, originalString.replace(regex, replacement), event->msgtype(), "", event->id());
if (flags == "/g"_ls) {
m_room->postHtmlMessage(handledText, originalString.replace(regex, replacement), event->msgtype(), {}, event->id());
} else {
m_room->postHtmlMessage(handledText,
originalString.replace(originalString.indexOf(regex), regex.size(), replacement),
event->msgtype(),
"",
{},
event->id());
}
return;
@@ -139,8 +117,8 @@ void ActionsHandler::handleMessage(const QString &text, QString handledText, con
if (handledText.startsWith(QLatin1Char('/'))) {
for (const auto &action : ActionsModel::instance().allActions()) {
if (handledText.indexOf(action.prefix) == 1
&& (handledText.indexOf(" ") == action.prefix.length() + 1 || handledText.length() == action.prefix.length() + 1)) {
handledText = action.handle(handledText.mid(action.prefix.length() + 1).trimmed(), m_room);
&& (handledText.indexOf(" "_ls) == action.prefix.length() + 1 || handledText.length() == action.prefix.length() + 1)) {
handledText = action.handle(handledText.mid(action.prefix.length() + 1).trimmed(), m_room, chatBarCache);
if (action.messageType.has_value()) {
messageType = *action.messageType;
}
@@ -153,38 +131,39 @@ void ActionsHandler::handleMessage(const QString &text, QString handledText, con
}
}
handledText = CustomEmojiModel::instance().preprocessText(handledText);
TextHandler textHandler;
textHandler.setData(handledText);
handledText = textHandler.handleSendText();
if (handledText.count("<p>") == 1 && handledText.count("</p>") == 1) {
handledText.remove("<p>");
handledText.remove("</p>");
if (handledText.count("<p>"_ls) == 1 && handledText.count("</p>"_ls) == 1) {
handledText.remove("<p>"_ls);
handledText.remove("</p>"_ls);
}
if (handledText.length() == 0) {
return;
}
m_room->postMessage(text, handledText, messageType, m_room->chatBoxReplyId(), isEdit ? m_room->chatBoxEditId() : "");
m_room->postMessage(text, handledText, messageType, chatBarCache->replyId(), chatBarCache->editId(), chatBarCache->threadId());
}
void ActionsHandler::checkEffects(const QString &text)
{
std::optional<QString> effect = std::nullopt;
if (text.contains("\u2744")) {
if (text.contains(QStringLiteral("\u2744"))) {
effect = QLatin1String("snowflake");
} else if (text.contains("\u1F386")) {
} else if (text.contains(QStringLiteral("\u1F386"))) {
effect = QLatin1String("fireworks");
} else if (text.contains("\u2F387")) {
} else if (text.contains(QStringLiteral("\u2F387"))) {
effect = QLatin1String("fireworks");
} else if (text.contains("\u1F389")) {
} else if (text.contains(QStringLiteral("\u1F389"))) {
effect = QLatin1String("confetti");
} else if (text.contains("\u1F38A")) {
} else if (text.contains(QStringLiteral("\u1F38A"))) {
effect = QLatin1String("confetti");
}
if (effect.has_value()) {
Q_EMIT showEffect(*effect);
}
}
#include "moc_actionshandler.cpp"

Some files were not shown because too many files have changed in this diff Show More