Compare commits

...

317 Commits

Author SHA1 Message Date
Heiko Becker
b009b9aac0 GIT_SILENT Update Appstream for new release 2026-02-28 13:21:50 +01:00
Heiko Becker
a133180925 GIT_SILENT Upgrade release service version to 25.12.3. 2026-02-28 13:21:43 +01:00
l10n daemon script
78d2b12fa7 GIT_SILENT Sync po/docbooks with svn 2026-02-27 03:33:06 +00:00
l10n daemon script
8e80e643f4 GIT_SILENT made messages (after extraction) 2026-02-27 02:46:53 +00:00
l10n daemon script
09e81a51b6 GIT_SILENT Sync po/docbooks with svn 2026-02-25 03:28:04 +00:00
l10n daemon script
4c64ff5925 GIT_SILENT made messages (after extraction) 2026-02-25 02:44:11 +00:00
l10n daemon script
00a497f0d2 GIT_SILENT made messages (after extraction) 2026-02-24 02:40:39 +00:00
l10n daemon script
6f91a45c8e GIT_SILENT Sync po/docbooks with svn 2026-02-23 03:22:18 +00:00
l10n daemon script
6cfdf9dab9 GIT_SILENT made messages (after extraction) 2026-02-23 02:39:24 +00:00
l10n daemon script
3fefdf57ac GIT_SILENT made messages (after extraction) 2026-02-22 02:42:29 +00:00
l10n daemon script
94df22832e GIT_SILENT Sync po/docbooks with svn 2026-02-21 03:30:11 +00:00
l10n daemon script
86cecf49c1 GIT_SILENT made messages (after extraction) 2026-02-21 02:45:06 +00:00
Tobias Fella
71e6acef76 Use released libquotient in release branch 2026-02-20 15:33:34 +01:00
l10n daemon script
9966e02eaf GIT_SILENT Sync po/docbooks with svn 2026-02-20 04:12:37 +00:00
l10n daemon script
cd776b8bd7 GIT_SILENT made messages (after extraction) 2026-02-20 03:17:57 +00:00
l10n daemon script
55f1de221c GIT_SILENT made messages (after extraction) 2026-02-19 02:46:37 +00:00
l10n daemon script
090ef3ac7a GIT_SILENT Sync po/docbooks with svn 2026-02-18 03:49:48 +00:00
l10n daemon script
27c49714de GIT_SILENT Sync po/docbooks with svn 2026-02-17 03:24:07 +00:00
l10n daemon script
18fdba2f7a GIT_SILENT made messages (after extraction) 2026-02-17 02:39:59 +00:00
Joshua Goins
a1615118d0 Allow focusing and navigating the space drawer with a keyboard
CCBUG: 511591
(cherry picked from commit f1b5ad7392)
2026-02-16 11:13:41 -05:00
Joshua Goins
9d816158f5 When favoriting/reprioritizng a room, make sure to re-sort the list
This fixes some odd issues like newly favorited rooms being sent to the
bottom of the room list, and so on.

(cherry picked from commit 78beb9ffff)
2026-02-16 11:13:41 -05:00
Joshua Goins
d8619356d3 Stop tree view from attempting to expand sections too early
This fixes a consistent bug for me, where the expandRecursively call
(somehow) predates the room list being populated. Which resulted in some
or all sections being collapsed on start-up.

(cherry picked from commit 431dbf6457)
2026-02-16 11:13:41 -05:00
Joshua Goins
6b6ccdaff0 Fix the emoticon editor page
It wasn't possible to edit the shortcode or description anymore, because
signals weren't hooked up. I also added a separator to help separate
some of these controls visually.

(cherry picked from commit 4e616d53b2)
2026-02-16 11:13:41 -05:00
Joshua Goins
18a29bc46b Fix weird scrolling behavior in room list
You may have noticed that the room list acts a bit... odd. You usually
can't scroll all the way down with a scrollwheel, it just
stops. It's possible to continue a little bit more with the scrollbar.
And sometimes the scrollbar doesn't know how big it's actually supposed
to be, commonly occuring when switching from a large room list to a
smaller one.

I narrowed it down the same usual problem with views in QtQuick:
variable sized delegates! Using GammaRay I figured out that for the
delegates currently in use they're slightly different: 46 pixels for
regular room delegates, 42 pixels for section headers and the "Find your
Friends" button was also different.

*Technically* TableView (and by extension TreeView) is supposed to allow
variable-sized delegates, and we should be able to advertise that with
rowHeightProvider. I tried a bunch of different solutions and none of
them worked reliably, so I took the usual sledgehammer approach of
making all of the delegates the same size.

This fixes all of the obvious bugs with the room list I could see, with
the one visual downside of making the section headers slightly taller.
But since I spent some time improving the tap targets, this is only a
visual change and not a functional one.

I also made sure to test it in compact mode, and everything shrinks as
expected.

(cherry picked from commit d47a4eb0de)
2026-02-16 11:09:17 -05:00
Joshua Goins
76180ace07 Re-settle the timeline view when replying to messages
Or changing the height of the chatbar in other ways, which I'm sure is
going to become more common with our new rich text system.

(cherry picked from commit e4c9230c09)
2026-02-16 11:09:17 -05:00
Joshua Goins
c439fa7e45 Fix undefined reference in Bubble
This tends to spam the logs while loading/unloading timelines.

(cherry picked from commit 318432d561)
2026-02-16 11:09:17 -05:00
Joshua Goins
9cadce88bb Hide rooms with custom defined types in quick switcher
This matches the behavior in other room lists. I also tried to normalize
the constructor with SortFilterRoomTreeModel.

(cherry picked from commit 847db41fb3)
2026-02-16 11:09:17 -05:00
Joshua Goins
d8984dc812 Reduce the tap target of RoomTreeSection
For some reason I don't understand, the ItemDelegate used for these
sections are ginormous. There is quite a bit of padding which confuses
users as its unexpectedly used for the tap area.

I changed it so we only listen for taps inside of the contentItem
itself, which is a more suitable area.

(cherry picked from commit 115d4e7466)
2026-02-16 11:09:17 -05:00
Joshua Goins
3f096da49b Fix the emoticon editor looking visually broken
We need to set a minimum width/height here since the Image isn't
technically loaded, when creating a new one.

(cherry picked from commit 9f4146e5b1)
2026-02-16 11:09:17 -05:00
l10n daemon script
bb51b1d677 GIT_SILENT Sync po/docbooks with svn 2026-02-16 03:23:42 +00:00
l10n daemon script
e45ccc00c3 GIT_SILENT made messages (after extraction) 2026-02-16 02:40:06 +00:00
l10n daemon script
c6f041d0bb GIT_SILENT Sync po/docbooks with svn 2026-02-15 03:44:06 +00:00
l10n daemon script
566f9de72a GIT_SILENT Sync po/docbooks with svn 2026-02-14 03:45:57 +00:00
Joshua Goins
6abc398033 Focus code and location chooser maximize components too
I did this for images a while back, but not for these. Otherwise you
can't press escape or perform other key navigation functions easily.

BUG: 515462
FIXED-IN: 25.12.2
(cherry picked from commit 793f81e733)
2026-02-09 21:47:11 -05:00
James Graham
bef4f370b6 Fix use after free in message delegate. We can't delete the incubator in the completed callback because it then returns to the incubator we just deleted.
(cherry picked from commit 8edb248647)
2026-02-09 21:45:42 -05:00
Joshua Goins
b18c12f149 Don't scroll the timeline when reacting to messages
BUG: 515306
FIXED-IN: 25.12.2
(cherry picked from commit 5de394b4b7)
2026-02-06 12:22:39 -05:00
Joshua Goins
e267f9f667 Fix closeToYEnd check
The comparison operator was reversed, and this was seen with mark as
read being broken and buttons showing up at the wrong times.

(cherry picked from commit 9ace01f74a)
2026-02-06 12:22:39 -05:00
l10n daemon script
32d264a3aa GIT_SILENT Sync po/docbooks with svn 2026-02-06 03:47:24 +00:00
l10n daemon script
77f9e43c82 GIT_SILENT Sync po/docbooks with svn 2026-02-04 03:48:38 +00:00
l10n daemon script
bc0d1aff35 GIT_SILENT Sync po/docbooks with svn 2026-01-31 03:19:28 +00:00
l10n daemon script
bc594ec8a2 GIT_SILENT Sync po/docbooks with svn 2026-01-30 03:48:53 +00:00
l10n daemon script
2a7f0b406c GIT_SILENT Sync po/docbooks with svn 2026-01-29 03:51:50 +00:00
l10n daemon script
c9f685a733 GIT_SILENT Sync po/docbooks with svn 2026-01-28 03:25:54 +00:00
Joshua Goins
5be43575fc Remove single tap to maximize code component
This is just more ergonomic (in my opinion) as you usually want to
select some text from a code block, instead of maximizing it. There's
already an easy-to-access button for maximizing if you want to.

BUG: 499048
FIXED-IN: 25.12.2
(cherry picked from commit 332a822996)
2026-01-27 18:08:09 +01:00
Joshua Goins
558519f355 Fix transparency blur not applying to the timeline anymore
We still had the default opaque background for RoomPage. I added a
comment too so it isn't removed accidentally in the future.

BUG: 513363
FIXED-IN: 25.12.2
(cherry picked from commit f145bbe8db)
2026-01-27 18:08:09 +01:00
l10n daemon script
f83e2e2677 GIT_SILENT Sync po/docbooks with svn 2026-01-27 03:20:43 +00:00
Albert Astals Cid
4c4f406c41 GIT_SILENT Update Appstream for new release 2026-01-27 02:13:34 +01:00
Albert Astals Cid
2f8a873202 GIT_SILENT Upgrade release service version to 25.12.2. 2026-01-27 01:14:18 +01:00
l10n daemon script
78b3cfe916 GIT_SILENT made messages (after extraction) 2026-01-25 02:36:47 +00:00
l10n daemon script
0bc529da2d GIT_SILENT Sync po/docbooks with svn 2026-01-24 03:21:02 +00:00
l10n daemon script
6ad6121dfa GIT_SILENT Sync po/docbooks with svn 2026-01-23 03:24:22 +00:00
l10n daemon script
7b5b7a67ae GIT_SILENT Sync po/docbooks with svn 2026-01-20 03:47:09 +00:00
l10n daemon script
59c8b82bc2 GIT_SILENT Sync po/docbooks with svn 2026-01-19 03:23:08 +00:00
l10n daemon script
c6aec89b61 GIT_SILENT Sync po/docbooks with svn 2026-01-18 03:41:28 +00:00
Joshua Goins
2ef3fd9d6c Add hack to fix crash when sending long text reactions
This is some bug in Flow (that is really hard to debug, I can't get it
to exit at all) but we can work around it for a minor visual impact. It
seems to me allow the reaction list to become slightly larger, but
that's about it.

BUG: 504344
FIXED-IN: 25.12.2
(cherry picked from commit 93e932c09c)
2026-01-17 15:08:11 -05:00
Joshua Goins
e64b6033f3 Cleanup few remaining atYEnd usages in TimelineView
These were either mistakes or rebase errors, but we should be using
closeToYEnd here.

(cherry picked from commit 3b8930c2bc)
2026-01-17 15:08:11 -05:00
Joshua Goins
82989e7ef2 Add hack to fix room sidebar not sticking to the top
This is similar to the TimelineView hacks, but this time its the header
item that's changing height as our room topics and such wrap.

(cherry picked from commit 6eb2b2e739)
2026-01-17 15:08:11 -05:00
Joshua Goins
ddf272ab2b Fix left padding for "Rooms" label in the room list
This now emulates the default Kirigami heading behavior now, with the
correct amount of padding.

(cherry picked from commit be89362fdd)
2026-01-17 15:08:11 -05:00
Joshua Goins
4d4b44e011 Fix Quick Switcher not being activatable by Enter/Return key
(cherry picked from commit e53c84d30c)
2026-01-17 15:08:11 -05:00
Joshua Goins
a17d7e18fd Don't show the Share action for non-file messages
This only shares files, if you try it on anything else it crashes
NeoChat.

(cherry picked from commit a90c26f566)
2026-01-17 15:08:10 -05:00
Joshua Goins
1e78f119f1 Add hack around the timeline never settling just right
This is due to some kind of bug in ListView that never resettles
properly for bottom-to-top views. This can arise when the pinned message
is loaded (because that squishes the view) or the window is resized
(because that also resizes the view.)

We can work around it by assuming the following:
1. The RoomPage knows the window is resizing because it gets its height
changed before TimelineView.
2. The first height change can be a marker to position the view at the
beginning.

This fixes the issue for me, I did the following in order to test this:
* Switch between many rooms, especially ones with a pinned message. Now
all of them start at the bottom as they should.
* Resize the window, ensure that if you scrolled it stays around that
position - otherwise it sticks at the bottom.

(cherry picked from commit 39de4d10e4)
2026-01-17 10:22:10 -05:00
Joshua Goins
b6a4b67c22 Improve reliability of restoring the last space and room (again)
I found that 50% of the time, NeoChat won't restore the last space but
instead get stuck at Home. Even worse, it will overwrite Home's last
opened room with the one from the space - resulting in really buggy
behavior.

The reason why this happens is partly due to the space hierarchy cache
(I think) but that's not the real problem in my opinion. During
setCurrentSpace, we needlessly update the last space & room config
despite us being the ones already reading it.

In addition to that I also refactored this code a bit to be more
consolidated and readable.

(cherry picked from commit 4c37dcf518)
2026-01-17 10:22:10 -05:00
Joshua Goins
e965e1680f Add hack around atYEnd
This fixes the annoying "I just scrolled down to the bottom, how come
NeoChat doesn't think I did?"

From what I can tell this is also ListView bug (or something caused by
our style/Kirigami) that creates cases like contentY being -643.2 (for a
ListView of height 643) thus that's not "at Y's end". For our case
though, we don't care and can safely round it.

(cherry picked from commit 3c77711417)
2026-01-17 10:22:10 -05:00
Nate Graham
7d4cc7a5cf Tell room page header message to fill the width
Otherwise it scrunches up as small as possible and breaks the layout.

(cherry picked from commit c50380b448)
2026-01-17 10:21:47 -05:00
l10n daemon script
112b4b54e5 GIT_SILENT Sync po/docbooks with svn 2026-01-17 03:20:03 +00:00
l10n daemon script
782f096f21 GIT_SILENT Sync po/docbooks with svn 2026-01-16 03:46:52 +00:00
l10n daemon script
57e0f04086 GIT_SILENT Sync po/docbooks with svn 2026-01-15 03:45:05 +00:00
l10n daemon script
a639011db6 GIT_SILENT Sync po/docbooks with svn 2026-01-14 03:19:41 +00:00
Joshua Goins
26e7f3780c Small notification improvements
Changed a check to use isDirectChat (which is a clearer indication of
what we want.) I also made sure not to show the account name if you only
have one, since that's just useless noise.

(cherry picked from commit fc6f345036)
2026-01-13 17:55:41 -05:00
Lorenz Wildberg
8c96d05799 fix bug: room settings don't open
(cherry picked from commit 2ec1fa92fa)
2026-01-13 17:55:04 -05:00
Veres Károly
bc6e22bc6d Null check decoded messages in loadPinnedMessage
`decryptMessage` returns null if it fails to decode the passed message. This value
then got fed into `EventHandler::richBody` which logged a warning and cleared `m_pinnedMessage`.
If we instead retain the value as an `EncryptedEvent`, the UI will pin the encrypted event
placeholder instead of hiding the existence of pins.

(cherry picked from commit 71c84be4b4)
2026-01-13 17:55:04 -05:00
Veres Károly
4371c3f7e5 Null check pinned messages after decryption when filling PinnedMessageModel.
`room()->decryptMessage()` returns null if the message fails to decode. Since elements of `m_pinnedEvents`
get directly dereferenced in getEventForIndex, storing null values leads to a segfault.
In this case we should retain the EncryptedEvent to let the UI report the error.

(cherry picked from commit b684fb451d)
2026-01-13 17:55:04 -05:00
Kai Uwe Broulik
b88ee65a4c RoomPage: Fix selected text and hovered link in context menu
They were not forwarded to the menu.
Also, "isThread" argument is no longer there in the signal.

(cherry picked from commit 7a2211f8e0)
2026-01-13 17:54:55 -05:00
Azhar Momin
033e865a27 Fix some runtime qml warnings
(cherry picked from commit 4155e9116a)
2026-01-13 17:54:33 -05:00
Azhar Momin
75ba46e292 Fix pushDialogLayer failing in DelegateContextMenu
(cherry picked from commit a989ef42b2)
2026-01-13 17:54:33 -05:00
Joshua Goins
d492ed038a Decrypt when downloading single events from the server
This fixes issues like not being able to view pinned messages in
encrypted rooms.

(cherry picked from commit 89e42dbc53)
2026-01-13 17:54:33 -05:00
Joshua Goins
b29108a2f7 Fix reply colors being broken if you're faster than the server
This is that bug that causes reply colors to be white, and this error to
print in the log:

qrc:/qt/qml/org/kde/neochat/messagecontent/ReplyComponent.qml:41: TypeError: Cannot read property 'color' of null

The reason why this happens is inside of EventMessageContentModel, it
needs to be able to find the relevant event in the room to fetch the
room member (and then their color.) Dependent on many variables to
align, this can happen easily if you are faster than your server giving
you said events.

But this is an easy fix, we obviously get the event afterwards and just
need to re-evaluate the the author property. I also made sure it falls
back to some color instead of white, which will also quiet the error.

(cherry picked from commit b45967508c)
2026-01-13 17:54:33 -05:00
Joshua Goins
2790d430ae Make clicking room list section headers more reliable
ListSectionHeader itself is an ItemDelegate, which eats up input events.
We can work around this by also listening to onClicked there too.

(cherry picked from commit 3a416990ca)
2026-01-13 17:54:33 -05:00
l10n daemon script
23f61fff36 GIT_SILENT Sync po/docbooks with svn 2026-01-13 11:40:36 +00:00
l10n daemon script
254d105e35 GIT_SILENT Sync po/docbooks with svn 2026-01-12 03:47:38 +00:00
l10n daemon script
6dde57a786 GIT_SILENT Sync po/docbooks with svn 2026-01-10 03:43:02 +00:00
l10n daemon script
d803fcb874 GIT_SILENT Sync po/docbooks with svn 2026-01-09 03:19:23 +00:00
l10n daemon script
90e70a9295 GIT_SILENT Sync po/docbooks with svn 2026-01-08 03:21:39 +00:00
l10n daemon script
2090e4dc0e GIT_SILENT Sync po/docbooks with svn 2026-01-06 03:41:42 +00:00
l10n daemon script
5ced491d54 GIT_SILENT Sync po/docbooks with svn 2026-01-05 03:42:28 +00:00
Azhar Momin
e156d4da90 Fix notification count refresh for low-priority and mentions-only rooms
(cherry picked from commit 5f7967363f)
2026-01-04 17:13:27 -05:00
Joshua Goins
b3aa2abd89 Fix icons on Windows
KirigamiApp currently calls KIconTheme::initTheme too late for Windows,
as a workaround we can go back to calling it ourselves.

(cherry picked from commit a02a04d966)
2026-01-04 17:13:27 -05:00
Veres Károly
7627d6d0e2 Extract the space selection logic from setCurrentRoom and use it for setting lastRoomConfig too.
If a setCurrentRoom call changed the active space at the end of its execution, the new room's ID ended up still being written to the old space's lastRoomConfig.

By extracting this space selection logic into a helper function, we can now calculate this value earlier and use it as the space id when writing lastRoomConfig.

(cherry picked from commit 68b00b9fc5)
2026-01-04 17:13:27 -05:00
Nate Graham
77da7e6c7d Improve hamburger menu button
- Open the menu right beneath the button
- Use pressed state for the button while the menu is open
- Close the menu when clicking the button again
- Hide the tooltip while the menu is open

(cherry picked from commit bd0588ca99)
2026-01-04 17:13:27 -05:00
l10n daemon script
1e3ce9d6cd GIT_SILENT Sync po/docbooks with svn 2026-01-04 03:38:17 +00:00
Heiko Becker
321561fd89 GIT_SILENT Update Appstream for new release 2026-01-03 12:14:39 +01:00
Heiko Becker
856bc7b713 GIT_SILENT Upgrade release service version to 25.12.1. 2026-01-03 11:15:22 +01:00
l10n daemon script
10e9b8d8f8 GIT_SILENT Sync po/docbooks with svn 2026-01-02 03:39:44 +00:00
l10n daemon script
9f1803c551 GIT_SILENT Sync po/docbooks with svn 2025-12-31 03:38:13 +00:00
l10n daemon script
9260c92026 GIT_SILENT Sync po/docbooks with svn 2025-12-30 03:42:39 +00:00
l10n daemon script
9c7030a5db GIT_SILENT Sync po/docbooks with svn 2025-12-29 03:13:12 +00:00
l10n daemon script
909e20889e GIT_SILENT Sync po/docbooks with svn 2025-12-27 03:11:47 +00:00
l10n daemon script
74f4c291a0 GIT_SILENT Sync po/docbooks with svn 2025-12-24 03:36:13 +00:00
Carl Schwan
242a248bf3 Send beautiful red ❤️'s when quick reacting
I wondered for a while (and could tell) when people were using NeoChat
because they would react with cold, monochrome hearts. Let's add more
color to our world!


(cherry picked from commit 531df7a3b2)

Co-authored-by: Joshua Goins <josh@redstrate.com>
2025-12-21 19:59:56 +01:00
Carl Schwan
dfb0bb75f4 Fix missing escape sequence in /shrug command
Before the fix, the upper arm _ characters in the command's output would be parsed as Markdown italic formatting around the (ツ).


(cherry picked from commit 706f1f7836)

Co-authored-by: Veres Károly <mail+kde@karcsesz.hu>
2025-12-21 18:07:46 +01:00
l10n daemon script
3cefd4b1ef GIT_SILENT Sync po/docbooks with svn 2025-12-14 03:13:17 +00:00
l10n daemon script
3f3ce6b421 GIT_SILENT Sync po/docbooks with svn 2025-12-13 03:17:45 +00:00
l10n daemon script
73d910421a GIT_SILENT Sync po/docbooks with svn 2025-12-10 03:32:09 +00:00
l10n daemon script
1da44f3ae3 GIT_SILENT Sync po/docbooks with svn 2025-12-09 03:15:27 +00:00
l10n daemon script
08836010c6 GIT_SILENT Sync po/docbooks with svn 2025-12-07 03:22:57 +00:00
l10n daemon script
13042d9ba6 GIT_SILENT Sync po/docbooks with svn 2025-12-04 03:20:39 +00:00
Heiko Becker
0e4b52ee62 GIT_SILENT Update Appstream for new release 2025-12-04 00:19:55 +01:00
Heiko Becker
4c32280343 GIT_SILENT Upgrade release service version to 25.12.0. 2025-12-03 23:04:35 +01:00
l10n daemon script
a2e540d6ef GIT_SILENT Sync po/docbooks with svn 2025-12-03 03:26:04 +00:00
Carl Schwan
573c8925d2 Fix krunner integration with Flatpak
(cherry picked from commit 1da24191f0)

Co-authored-by: renner 03 <renner0@posteo.de>
2025-12-02 23:00:25 +01:00
l10n daemon script
6c0bd850b0 GIT_SILENT Sync po/docbooks with svn 2025-12-01 03:28:35 +00:00
l10n daemon script
1da9719314 GIT_SILENT Sync po/docbooks with svn 2025-11-25 03:15:21 +00:00
Heiko Becker
3cd5f3a1c6 Drop unused dependencies
Both KF6Crash and KF6IconThemes aren't used anymore after porting to
KirigamiApp in eab45e761a.

(cherry picked from commit 0cb3fd32f4)
2025-11-24 21:56:55 +01:00
Albert Astals Cid
b4108f2eef GIT_SILENT Upgrade release service version to 25.11.90. 2025-11-24 00:57:39 +01:00
l10n daemon script
bb7de18341 GIT_SILENT Sync po/docbooks with svn 2025-11-23 03:19:33 +00:00
l10n daemon script
7b8328fce6 GIT_SILENT Sync po/docbooks with svn 2025-11-21 03:20:12 +00:00
l10n daemon script
aeee6570c0 GIT_SILENT Sync po/docbooks with svn 2025-11-20 03:14:24 +00:00
l10n daemon script
780b9a6f9b GIT_SILENT Sync po/docbooks with svn 2025-11-17 15:49:57 +00:00
l10n daemon script
0ba06882d1 GIT_SILENT Sync po/docbooks with svn 2025-11-17 03:16:16 +00:00
l10n daemon script
ce131a53e5 GIT_SILENT Sync po/docbooks with svn 2025-11-16 03:16:40 +00:00
l10n daemon script
e9421e28dd 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"
2025-11-16 03:13:00 +00:00
l10n daemon script
1c64a6b5f0 GIT_SILENT Sync po/docbooks with svn 2025-11-15 03:19:51 +00:00
l10n daemon script
9b5200c344 GIT_SILENT Sync po/docbooks with svn 2025-11-14 03:21:54 +00:00
l10n daemon script
5baf4ab823 GIT_SILENT Sync po/docbooks with svn 2025-11-13 03:20:11 +00:00
l10n daemon script
58a72a08f2 GIT_SILENT Sync po/docbooks with svn 2025-11-11 03:37:16 +00:00
l10n daemon script
c9b97d4d0d GIT_SILENT Sync po/docbooks with svn 2025-11-10 03:26:49 +00:00
Carl Schwan
2a7d61c73b Improve invited room counting
I didn't realize when redoing the tooltip for DMs that directChatInvites
was a boolean, not an integer type. Now it's changed to an integer type,
which fixes the DM invite count.

NeoChat apparently didn't count normal room invites until now either, so
now Home is highlighted in that case. Now it should be harder to miss
these kinds of invites.


(cherry picked from commit 887865c0aa)

Co-authored-by: Joshua Goins <josh@redstrate.com>
2025-11-09 22:23:09 +01:00
l10n daemon script
f55bd28e10 GIT_SILENT Sync po/docbooks with svn 2025-11-09 03:45:49 +00:00
Albert Astals Cid
2a67861099 GIT_SILENT Upgrade release service version to 25.11.80. 2025-11-06 17:40:37 +01:00
l10n daemon script
273d962707 GIT_SILENT Sync po/docbooks with svn 2025-11-06 01:40:42 +00:00
Paul Brown
5e8b44fea6 Adding Akseli as supporter 2025-11-05 21:56:17 +00:00
l10n daemon script
be9e2ec7d0 GIT_SILENT Sync po/docbooks with svn 2025-11-05 01:48:44 +00:00
l10n daemon script
ee042cc1a2 GIT_SILENT Sync po/docbooks with svn 2025-11-04 01:47:11 +00:00
Kristen McWilliam
25c0bc131a feat: add font size scaling setting
Adds an option in Appearance Settings to adjust font size scaling,
improving accessibility and user customization.
2025-11-03 10:18:23 -05:00
Paul Brown
7def8c066c Added anonymous donot to list of supporters 2025-11-03 12:50:59 +00:00
l10n daemon script
1ddaf37e52 GIT_SILENT Sync po/docbooks with svn 2025-11-02 01:39:31 +00:00
Heiko Becker
40694f502a Fix version in appstream file
GIT_SILENT
2025-11-01 20:01:46 +01:00
l10n daemon script
d9f4a0a032 GIT_SILENT Sync po/docbooks with svn 2025-11-01 01:44:57 +00:00
l10n daemon script
5e392f3101 GIT_SILENT Sync po/docbooks with svn 2025-10-31 01:39:58 +00:00
Heiko Becker
ce1ac6128e GIT_SILENT Update Appstream for new release
(cherry picked from commit c6fa5a10dd)
2025-10-31 01:23:25 +01:00
l10n daemon script
a9d08a6ee2 GIT_SILENT Sync po/docbooks with svn 2025-10-30 01:41:27 +00:00
Joshua Goins
24d4829ba9 Clarify what is "recent activity" in our room list ordering settings
As seen in the bug report, this setting is a bit confusing. First, it
refers to "message activity" but in reality it does take into account
all events. This is fine in my opinion, so I clarified that point.

Another thing is that it wasn't clear that timeline visibility settings
currently affect the sorting, so I added a tip about that.

Finally I wasn't happy with these two options being called "Activity"
so the old "Activity" setting is now called "Importance". The "Last
Message Activity" setting is now called "Newest Events".

BUG: 508480
FIXED-IN: 25.12.0
2025-10-29 18:18:53 -04:00
l10n daemon script
a121c39b6e GIT_SILENT Sync po/docbooks with svn 2025-10-29 01:41:34 +00:00
Joshua Goins
f009420c20 Improve the design of the room notifications settings
Now it has icons that match what we have in the room menu, and the
duplicate header text is removed.
2025-10-28 12:27:23 -04:00
Joshua Goins
069e0d8f16 Add informational Keyboard Shortcuts settings page
While we don't have customizable keyboard shortcuts (yet!) we have been
asked before for some way to view all of NeoChat's keyboard shortcuts.
2025-10-28 10:29:55 -04:00
Joshua Goins
1f1db11197 Fix plugin on LocationsPage
This lives in the base NeoChat QML module, not the libneochat one.
2025-10-28 09:17:18 -04:00
Joshua Goins
be92e56c3a Show less scary icon for neutral reasons when cancelling verification
For example, accepting a verification on another device shows a giant
red security icon which isn't really suitable. I chucked the
dialog-information icon in for some of the neutral-sounding messages so
this dialog can be a little less intimidating.

BUG: 510421
FIXED-IN: 24.08.3
2025-10-28 09:16:17 -04:00
l10n daemon script
d1fc426513 GIT_SILENT Sync po/docbooks with svn 2025-10-28 01:41:19 +00:00
Joshua Goins
c778ba8b24 Fix jump to previous/next unread room shortcuts
These were dependent on a renamed property and ended up breaking, oops.
2025-10-27 18:09:00 -04:00
Joshua Goins
07fb3160eb Add "Inspect Room Data" button in the room sidebar
I find myself doing the same routine: I want to inspect a room's state,
so I have to go hunting for the Developer Tools button. And then I have
to do a few clicks to even get the correct room, what a waste of time!

So I added a new button to the sidebar to open the Developer Tools for
the current room.
2025-10-27 18:08:51 -04:00
Joshua Goins
7444d68280 Change room sidebar action text
As we've continued to add more and more room actions, I'm not entirely
happy with how they're worded. Some are super short and sweet like
"Verify User" while others refer to the room as if the sidebar wasn't
enough context: "Search in this room".

I redid all of the button's text so they're shorter, like "Search
Messages".
2025-10-27 18:08:42 -04:00
Joshua Goins
1d5536401d Make the CTRL+F shortcut search the current room's messages
Right now there's not an easy way to quickly bring up message search. If
you press CTRL+F (with the room information sidebar *closed*, for some
reason) that brings up the same dialog as CTRL+K which seems redundant.

I assigned that shortcut to the message search dialog instead, which is
makes much more sense in my opinion. I also made sure its disabled in
spaces or when there's not a room open.

BUG: 487270
FIXED-IN: 25.12.0
2025-10-27 18:08:29 -04:00
Joshua Goins
099e996f2f Improve standalone images in link preview and more
We would incorrectly show a "truncate" button for standalone images
which isn't applicable since there's no text. That check has been fixed,
and it doesn't seem to regress normal link previews.

Another is that if there's only an image, our layout would center the
image which looks awkward since almost everything else is left-aligned
in chat. This is also fixed, which notably matches up to Element Web's
behavior.

I added support for the hover link indicator as well. Someone could
maliciously hide it via Markdown but have a legitimate-looking link
preview, for example. You can check that by hovering over the link in
the message itself, but now the link preview is another way to confirm
that!
2025-10-27 18:08:21 -04:00
Joshua Goins
6d9974b2b1 Improve the Jitsi meeting button UX
Widgets support is incredibly useful and so is this button, but it has a
few problems. The most obvious is that it's still enabled even if you
don't actually have the permission to start Jitsi meetings, so I fixed
that. I also made sure it's hidden when viewing spaces too.

Another problem is that you can't easily tell if a meeting is currently
in progress either, nor do we have a good icon for that in Breeze. So I
changed the tooltip and colored the icon in this case.

The final problem I fixed is something not exclusive to NeoChat, but
generally all chat applications with this feature - there's no
confirmation! To stop "butt-dialing" random people or rooms, I added a
prompt before starting or joining a meeting.
2025-10-27 18:08:08 -04:00
James Graham
f65e9f7599 Fix the chatbar so that the icons show on android. Overring the contentItem was what was causing them to disappear. 2025-10-27 16:13:54 -04:00
l10n daemon script
4a39810923 GIT_SILENT Sync po/docbooks with svn 2025-10-26 01:38:47 +00:00
l10n daemon script
6720e2dfaa GIT_SILENT Sync po/docbooks with svn 2025-10-25 01:39:53 +00:00
l10n daemon script
eb1bf2ed2b GIT_SILENT Sync po/docbooks with svn 2025-10-24 01:39:25 +00:00
l10n daemon script
cc26b1b62f GIT_SILENT Sync po/docbooks with svn 2025-10-23 01:38:07 +00:00
l10n daemon script
59c2c88eb6 GIT_SILENT made messages (after extraction) 2025-10-22 00:43:30 +00:00
l10n daemon script
99e8fd16eb GIT_SILENT Sync po/docbooks with svn 2025-10-21 01:39:43 +00:00
l10n daemon script
eaa4bdb0b7 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"
2025-10-21 01:34:16 +00:00
l10n daemon script
892b61e6bb GIT_SILENT Sync po/docbooks with svn 2025-10-20 01:41:26 +00:00
Nicolas Fella
6d56b673c4 Don't call direct messages friends
Not every person I communicate with is necessarily my friend

Use a more neutral term

BUG: 480167
2025-10-19 19:42:21 +02:00
l10n daemon script
f59e5a4b3c GIT_SILENT Sync po/docbooks with svn 2025-10-19 01:42:36 +00:00
Nicolas Fella
16e3fd4476 Don't show direct messages in room list when not in a space
2b0251c593 changed the logic to also show direct messages inside a space

However this also causes direct messages to be shown when *not* inside a space, which is undesirable
2025-10-18 15:02:07 +02:00
l10n daemon script
82d0fdefd2 GIT_SILENT Sync po/docbooks with svn 2025-10-18 02:03:22 +00:00
Tobias Fella
cbde14d58b Cleanup DevicesPage 2025-10-17 12:23:58 +00:00
l10n daemon script
f3c37e4304 GIT_SILENT Sync po/docbooks with svn 2025-10-17 01:57:08 +00:00
l10n daemon script
369008cec3 GIT_SILENT Sync po/docbooks with svn 2025-10-16 01:40:30 +00:00
l10n daemon script
1a2af57901 GIT_SILENT Sync po/docbooks with svn 2025-10-15 01:39:22 +00:00
l10n daemon script
dbb41d061c 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"
2025-10-15 01:33:59 +00:00
l10n daemon script
d1d3c43c6f GIT_SILENT Sync po/docbooks with svn 2025-10-14 01:40:53 +00:00
Paul Brown
ba2b1529ea Edit org.kde.neochat.appdata.xml 2025-10-13 10:50:10 +00:00
l10n daemon script
b5150f82f0 GIT_SILENT Sync po/docbooks with svn 2025-10-13 01:40:08 +00:00
Tobias Fella
00c81de035 Fix pushing welcome page onto layer
BUG: 510285
2025-10-12 10:58:21 +00:00
Tobias Fella
52d4451932 Add state event texts for some element-specific widget events 2025-10-12 10:49:45 +00:00
l10n daemon script
3efc11b9aa GIT_SILENT Sync po/docbooks with svn 2025-10-12 01:39:29 +00:00
James Graham
5fd9f07664 Some further belt and braces to ensure that we don't crash in the timeline
Some further belt and braces to ensure that we don't crash in the timeline. This does the following:
- Checks all callback inputs
- Makes sure that any objects are cleaned up from incubators when deleting the delegate as it turns out that clear() doesn't do this. Hopefully this stops callbacks into an already deleted parent.

Hopefully helps with https://crash-reports.kde.org/organizations/kde/issues/261627/events/0b6bef500c5641e1924aa0bc2b0c11bd/
2025-10-11 18:11:57 +00:00
l10n daemon script
bec9f36bce GIT_SILENT Sync po/docbooks with svn 2025-10-11 10:19:58 +00:00
l10n daemon script
a631acc0ac GIT_SILENT Sync po/docbooks with svn 2025-10-10 01:38:30 +00:00
l10n daemon script
b729aaf6ee GIT_SILENT Sync po/docbooks with svn 2025-10-09 01:43:02 +00:00
Tobias Fella
94b7fc5cdf Fix delegate menu for state events 2025-10-08 21:50:56 +00:00
Marco Martin
ec5355d86e Push to PageRow on mobile too
This fixes some glitches during animation, which had the background
disappearing when the pop animation was running,
and now uses always the pagerow for viewing the room.

This depends from the new PageRow animation on mobile,
https://invent.kde.org/frameworks/kirigami/-/merge_requests/1925
which makes all applications coherent with an application which
looks a bit more like the one on most android apps.

Also, the swipe back gesture now will work there too
2025-10-08 15:44:46 +00:00
Arno Rehn
1a43d15c6d EventHandler: Acknowledge that non-room-events can have a body as well
Specifically, in the current architecture, these can be EncryptedEvents
which are redactions of previous events. These will have artifical bodies.
2025-10-08 14:01:48 +00:00
James Graham
7356a68f4c Hopefully this stops any crashes around QuickActions.qml and EmojiDialog.qml
Hopefully this stops any crashes around QuickActions.qml and EmojiDialog.qml. Best I can guess this is some race condition where QuickActions are deleted in the time it takes to instnatiate the EmojiDialog popup. I've also rearranged the updateQuickActions function to stop a possible race condition there.

BUG: 509484
2025-10-08 13:07:02 +00:00
Tobias Fella
1070427a0d Try fixing crash in QConcatenateTablesProxyModel 2025-10-08 11:39:39 +00:00
l10n daemon script
196ef535ca GIT_SILENT Sync po/docbooks with svn 2025-10-08 01:40:26 +00:00
Tobias Fella
88fd173829 Show a placeholder message if there are no extensions 2025-10-07 22:43:18 +02:00
Arno Rehn
8b0698c670 Support adding Jitsi and removing widgets 2025-10-07 21:58:34 +02:00
Arno Rehn
5b07a0ff45 Add jitsi button to RoomPage 2025-10-07 21:58:34 +02:00
Arno Rehn
ba1d175d67 Add "Extensions" item to the room info 2025-10-07 21:58:34 +02:00
Arno Rehn
36ce55e892 Add WidgetModel 2025-10-07 21:56:18 +02:00
Arno Rehn
ba4a83d38c Don't switch to global DMs when space contains DM 2025-10-06 14:14:04 +00:00
Arno Rehn
5c49c35b82 Space overview: Fix displayed name of direct chats
When in the space overview page, direct chats were previously only
shown with their room ID. Fix this by getting the actual NeoChatRoom
and its displayName.
2025-10-06 14:14:04 +00:00
Arno Rehn
2b0251c593 Room list: Show direct chats in spaces
Direct Chats can be added to spaces as well. No need to exclude them.
2025-10-06 14:14:04 +00:00
l10n daemon script
3b08d0f382 GIT_SILENT Sync po/docbooks with svn 2025-10-06 01:43:51 +00:00
l10n daemon script
f64e8a3192 GIT_SILENT Sync po/docbooks with svn 2025-10-04 15:09:41 +00:00
Tobias Fella
eab45e761a Use KirigamiApp 2025-10-03 11:32:15 +00:00
l10n daemon script
0f03290c57 GIT_SILENT Sync po/docbooks with svn 2025-10-03 01:42:04 +00:00
Tobias Fella
59f87bb2c2 Set deprecation level 2025-10-02 16:43:27 +02:00
Tobias Fella
9afc10160d Raise compiler settings level to 6.17 2025-10-02 16:19:01 +02:00
Tobias Fella
cfc7f50a1f MessageContentModel: Guard data() against being called when there is no room 2025-10-01 23:48:49 +02:00
Heiko Becker
a2fc00365e GIT_SILENT Update Appstream for new release
(cherry picked from commit debbe8e478)
2025-10-01 00:40:10 +02:00
Joshua Goins
466cfd971d Fix room succession not actually working
I broke this in 409b6da160 making it not
possible to join a succeeding room. I decided to keep the old behavior
of not prompting you to join, because:

1. You are intentionally choosing to tap the button.
2. Room successions aren't random, a privileged user in the room is
creating it and there's already some implicit existing trust

(Also the current join confirmation dialog isn't useful enough yet to
make an actual informed decision anyway.)
2025-09-30 16:05:36 -04:00
Joshua Goins
8e83febb24 Remove some dead code from MessageModel::createEventObjects
This senderId variable doesn't seem to be used in the current iteration
of this function, lets remove it.
2025-09-30 12:07:49 -04:00
l10n daemon script
12072b0a73 GIT_SILENT Sync po/docbooks with svn 2025-09-30 01:47:20 +00:00
l10n daemon script
83b1daac07 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"
2025-09-30 01:36:30 +00:00
Arno Rehn
981ea053a6 Pinned messages: Decrypt events before handling them 2025-09-29 18:59:53 +02:00
Arno Rehn
e41fd7d986 PollHandler: Decrypt EncryptedEvents
Related events for a poll will be EncryptedEvents in an encrypted
room. Decrypt them before handling.
2025-09-29 18:59:53 +02:00
Arno Rehn
a88a82ca08 PollHandler: Correctly handle paginated events 2025-09-29 18:59:20 +02:00
Arno Rehn
23dc88df60 PollComponent: Apply word wrapping on long messages
Long messages were not wrapped and would overflow.
Correctly apply word wrapping and align all elements on the top of a
row.
2025-09-29 18:58:57 +02:00
l10n daemon script
520b1daeec GIT_SILENT Sync po/docbooks with svn 2025-09-29 01:41:25 +00:00
l10n daemon script
cbe7ace32d GIT_SILENT Sync po/docbooks with svn 2025-09-28 01:46:45 +00:00
l10n daemon script
2b4471ea91 GIT_SILENT Sync po/docbooks with svn 2025-09-27 01:40:14 +00:00
Joshua Goins
88e1e1dd2a Add the ability to scroll up in the message search window
This wasn't a thing yet, so the search experience compared to something
like Element Web was much worse. Now you can scroll back as far as any
other client can!

I had to do a bit of refactoring to stop resetting the model all the
time, and append instead. Otherwise, it was quite straightforward to
implement.
2025-09-26 17:49:22 -04:00
Joshua Goins
94ea1305b2 Fix some miscellaneous weirdness around push notifications
For some reason, I *stopped* the timer if we get a push message - which
makes *no* sense. It meant that NeoChat kept running in the background
for basically no reason.

We can also make the NotificationsManager::postPushNotification function
static and avoid creating some singletons.
2025-09-26 15:14:05 -04:00
Joshua Goins
960377838d Replace KDBusService usage with QDBusConnection when D-Bus activated
This is lighter and more reliable when it comes to being activated by
KUnifiedPush. We also don't need all of the features of KDBusService
here.
2025-09-26 15:14:05 -04:00
Joshua Goins
a48e8662d6 Remove useless translated string from dbus-activated CLI option
It never gets shown, so let's not waste our translators time.
2025-09-26 15:12:56 -04:00
l10n daemon script
9c90a38efc GIT_SILENT Sync po/docbooks with svn 2025-09-26 01:39:23 +00:00
l10n daemon script
8696a24127 GIT_SILENT Sync po/docbooks with svn 2025-09-25 01:40:55 +00:00
l10n daemon script
f2d1b4c1e1 GIT_SILENT Sync po/docbooks with svn 2025-09-24 01:40:47 +00:00
Laurent Montel
4cdc2b5e58 GIT_SILENT: Don't duplicate headers between .h/.cpp 2025-09-22 04:43:02 +00:00
l10n daemon script
e26f02d9e2 GIT_SILENT Sync po/docbooks with svn 2025-09-22 01:38:51 +00:00
l10n daemon script
5d83fe9a1d GIT_SILENT Sync po/docbooks with svn 2025-09-21 01:41:04 +00:00
l10n daemon script
6a506f237a GIT_SILENT Sync po/docbooks with svn 2025-09-20 01:41:10 +00:00
l10n daemon script
3a5a0153d8 GIT_SILENT Sync po/docbooks with svn 2025-09-18 01:40:38 +00:00
l10n daemon script
27519b8788 GIT_SILENT Sync po/docbooks with svn 2025-09-17 01:39:11 +00:00
l10n daemon script
dd45fe16a5 GIT_SILENT Sync po/docbooks with svn 2025-09-16 01:41:59 +00:00
Vlad Zahorodnii
161815acff Fix inserting UserListModel items without beginInsertRows()
If an item is added, the corresponding code should be wrapped with
beginInsertRows() and endInsertRows(), otherwise proxy or filter models
can end up with corrupted internal state.

m_members.insert() in refreshMember() should be unnecessary because
if pos is not the same as m_members.size(), then it means there's already
a member.id() item in the member list.
2025-09-15 18:04:29 +00:00
Tobias Fella
438edf2155 Fix qml warnings in ImageEditorPage 2025-09-15 16:13:49 +02:00
Tobias Fella
6607a4b72c Fix qml warnings in ChatBar 2025-09-15 16:11:20 +02:00
Tobias Fella
8f0c4ab133 Fix warning in FullScreenMap 2025-09-15 16:06:58 +02:00
Tobias Fella
78e5cd51cd remove unused imports 2025-09-15 16:05:22 +02:00
Tobias Fella
f5da44655e Fix qml warnings in SpaceDrawer 2025-09-15 16:03:38 +02:00
Tobias Fella
a91863c60d Fix qml warnings in AccountSwitchDialog 2025-09-15 14:39:40 +02:00
Tobias Fella
29e3a09aba Fix qml warning 2025-09-15 14:29:55 +02:00
Tobias Fella
a59952f189 Fix qml warnings in AccountData 2025-09-15 14:24:42 +02:00
Tobias Fella
b169da25ab Fix qml warnings in RoomSortParameterDialog 2025-09-15 14:21:47 +02:00
Tobias Fella
833e357d70 Fix qml warnings in login module 2025-09-15 14:15:38 +02:00
Tobias Fella
f9bf2b8f7a Fix warnings in NeoChatMaximizeComponent 2025-09-15 14:06:17 +02:00
Tobias Fella
7b27579f2d Fix qml warnings in ExploreRoomsPage 2025-09-15 13:54:43 +02:00
Tobias Fella
edb9d9f54e Remove unused import 2025-09-15 13:51:23 +02:00
Tobias Fella
abf9a486d0 Fix qml warnings in RoomData 2025-09-15 13:49:08 +02:00
Tobias Fella
b0bc19c055 Fix qml warnings in RoomInformation 2025-09-15 13:41:32 +02:00
Tobias Fella
71776ef275 Fix qml warnings in TypingPane 2025-09-15 13:30:55 +02:00
Tobias Fella
8dc7d1d39d Fix most qml warnings in StateKeys 2025-09-15 13:25:41 +02:00
Tobias Fella
adb9e59503 Fix qml warnings 2025-09-15 13:21:17 +02:00
Tobias Fella
518044e34a Fix qml warning 2025-09-15 13:17:32 +02:00
Tobias Fella
d6d747bb99 Fix qml warnings in EmoticonFormCard 2025-09-15 13:15:59 +02:00
l10n daemon script
f390702a7a GIT_SILENT Sync po/docbooks with svn 2025-09-15 01:39:42 +00:00
Tobias Fella
e056360ddd Various fixes for ExportKeysDialog 2025-09-14 18:31:26 +02:00
l10n daemon script
85163791ce GIT_SILENT Sync po/docbooks with svn 2025-09-14 01:39:17 +00:00
l10n daemon script
b5a853bc96 GIT_SILENT Sync po/docbooks with svn 2025-09-13 01:46:27 +00:00
Tobias Fella
e4cd6ce5a6 Add "copy user id" menu to delegate in user search page
BUG: 499792
2025-09-12 11:37:07 +00:00
l10n daemon script
84fa68e3ae GIT_SILENT Sync po/docbooks with svn 2025-09-12 01:38:40 +00:00
Joshua Goins
649dc7a815 Add placeholder message when there's no public rooms at all
I guess we never tested this against a truly empty server yet, as the
"no search" message was empty. This would normally never show up since
the top public rooms are usually listed instead.
2025-09-11 14:09:52 -04:00
Joshua Goins
b87e43660c Use better-fitting icons for "Explore rooms" and "Find your friends"
Only a problem on the room list, which used list-add which is odd as it
doesn't match up with how these are displayed elsewhere.
2025-09-11 11:52:24 -04:00
Joshua Goins
511138e3bb Revert back to normal, non-master KNotifications
It requires KF6.18, and while we could also force that it's probably
easier to wait for the full release.
2025-09-11 17:47:29 +02:00
Volker Krause
5a3c23d000 Fix KNotifications Craft path 2025-09-11 17:22:04 +02:00
Joshua Goins
1036384023 Add recently pinned message to the top of the window
This makes pinned messages actually quite useful, as rooms can stick
persistent and important information for users to see. (For example, the
KWin has crash triage meeting information pinned in their room.)

For simplicity and space reasons, only one line of the generic message
body is shown.
2025-09-11 08:57:22 -04:00
Tobias Fella
e3f618489b Remove flatpak patches 2025-09-11 12:00:44 +00:00
Joshua Goins
cfedd4fdb5 Stop erroring out when setting avatar if you never set it
The code didn't actually check the avatar URLs were different until now.
2025-09-11 07:43:04 -04:00
Joshua Goins
812e5beee6 Allow pressing enter/return on "Add Account" in account switcher dialog
Because "Add Account" is a "fake item" by being the footer, it should be
the null fallback when accessing currentItem.
2025-09-11 07:41:56 -04:00
Joshua Goins
17b632eb78 Add a small margin between the border of media and "Hide Media" button
I thought we had this already, I don't know where it went, but now it's
back.
2025-09-11 13:36:51 +02:00
Joshua Goins
877d5f34f7 Hide "Scan a QR Code" with no camera connected
Also when you disconnect/turn off the camera while the QR scanner is
open, show a better error message instead of freezing the last frame.
2025-09-11 05:15:39 -04:00
Tobias Fella
c93ce52ba1 Remove various outdated ifdefs 2025-09-11 10:47:23 +02:00
l10n daemon script
2504ca3f5c GIT_SILENT Sync po/docbooks with svn 2025-09-11 01:38:19 +00:00
l10n daemon script
5be05032be GIT_SILENT Sync po/docbooks with svn 2025-09-10 01:39:56 +00:00
Joshua Goins
81e5061831 Fix-up QR code scanning actions
I cleaned up how resolving QR codes work, I made sure to test both user
and room links and everything works great.

A more awkward bug I fixed is
a workaround around a quirk in Kirigami.Dialog, but actually regresses
QR codes. Because the QR code scanner is currently an extra window (at
least on desktop) the UserDetailDialog will reparent itself to the
soon-to-be-destroyed scanner window.
2025-09-09 13:35:12 -04:00
Joshua Goins
3b419e18a3 Build KNotifications master in Craft for now
This is needed to make Android notifications work again, as it narrowly
missed 6.18. We can remove it upon the next release.
2025-09-09 10:44:25 -04:00
Joshua Goins
1a1190d7bd Fix URL previews on modern Matrix servers never loading
This was a regression in 5d5295d06d where
the job never connected to the onSuccess function.
2025-09-09 08:51:54 -04:00
Joshua Goins
5b4d3df6ee Make rooms in the room list bold when there's unread messages
This used to be a feature but kinda broke/changed when we switched to
focusing on context-aware or notable events. Basically instead of only
notable events making a room bold in the room list, it's any unread
messages now.
2025-09-09 11:43:25 +02:00
Tobias Fella
f53d47fa28 Require libQuotient 0.9.3 2025-09-09 07:47:39 +00:00
l10n daemon script
67d5711cc4 GIT_SILENT Sync po/docbooks with svn 2025-09-09 02:18:13 +00:00
l10n daemon script
9f51b1e7ab 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"
2025-09-09 02:04:03 +00:00
l10n daemon script
5ac296ee71 GIT_SILENT made messages (after extraction) 2025-09-09 00:54:31 +00:00
Joshua Goins
1b8adcc91a Don't import Purpose on Android
This prevents the app from launching on Android (and probably Windows
too) because our module declares a dependency on a non-existent Purpose.
2025-09-08 16:10:12 +02:00
Joshua Goins
1e78209cd7 Fix missing appWindow property for GlobalMenuStub
This was one of the issues with the current Android version.
2025-09-08 15:47:04 +02:00
Tobias Fella
0fd924be7b Fix showing permissions settings for v12 rooms 2025-09-08 08:14:17 +00:00
l10n daemon script
d67cb89505 GIT_SILENT Sync po/docbooks with svn 2025-09-08 02:13:16 +00:00
l10n daemon script
0d0f88e251 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"
2025-09-08 01:51:40 +00:00
Joshua Goins
4cbd4a034c Remove incorrect context for "Always allow device verification" 2025-09-07 12:57:08 -04:00
Joshua Goins
e7ed07e386 Show the "Verify This Device" warning when turning on reverification
This is the only way to reverify your device again, so it's useful to
show this in that case.
2025-09-07 12:57:08 -04:00
Joshua Goins
390654fa4a Fix deprecation warning about QHoverEvent::pos
We should be using position().
2025-09-07 12:26:27 -04:00
Joshua Goins
e8830b56d8 Add "Done" button when verification session is finished
It isn't immediately obvious when to close the window, other clients
(e.g. Element Web) has a "Got It" button in addition to the regular
dialog close button.
2025-09-07 12:25:16 -04:00
Tobias Fella
bbf2587908 Don't use raw json for getting reply event id 2025-09-07 16:43:35 +02:00
Joshua Goins
409b6da160 Bring up the room confirmation dialog in more situations
This super helpful and nice dialog went mostly unused, especially if you
only joined links to rooms through matrix.to or within NeoChat itself.

The reason why this never showed up for said links is because we were
greedily overwriting the "action". I don't think the code made solid
sense anyway, so I redone it a bit so there's a clearer
"join_confirmed" our UI uses. I added a test case to showcase this
working.
2025-09-07 08:43:51 -04:00
l10n daemon script
9d8c9853ce GIT_SILENT Sync po/docbooks with svn 2025-09-07 01:40:17 +00:00
Joshua Goins
b3781e0db4 Turn NeoChatConnection::isVerifiedSession into a notifiable property
This should allow the devices page to hide the "Verify this Device"
warning, once you actually complete verification. I also made sure to
update the other consumer - the menu item under the user menu.

Additionally, I also fixed the password field not being automatically
focused when trying to remove a device.
2025-09-06 07:51:38 -04:00
l10n daemon script
fbcb2379fb GIT_SILENT Sync po/docbooks with svn 2025-09-06 01:40:56 +00:00
Tobias Fella
e8ad4a5dee Fixes for logging out the active connection
- Don't crash
- Fall back to WelcomePage
2025-09-05 10:11:43 +00:00
l10n daemon script
6c57c41993 GIT_SILENT Sync po/docbooks with svn 2025-09-05 01:41:21 +00:00
Joshua Goins
ce0014f846 Don't accidentally hide relevant error banners
We use error banners for intermittent errors (failing to join a room),
along with more long-standing/important errors (like going offline.) And
due to the nature of how we manage banner visibility - for example, the
online check could accidentally hide joining rooms errors which is
pretty bad.

To fix this, each error banner is assigned an id. All errors can still
overwrite each other as they could before, but they can only hide
banners of their own kind.
2025-09-04 20:48:56 -04:00
l10n daemon script
e5df412258 GIT_SILENT Sync po/docbooks with svn 2025-09-04 01:41:16 +00:00
Heiko Becker
0c482aa463 GIT_SILENT Update Appstream for new release
(cherry picked from commit 681a3c4036)
2025-09-04 01:31:22 +02:00
Joshua Goins
2df3a21fb5 Show the room name when failing to join it
The previous error message generically said you failed to join a room,
but it doesn't say *which* one!
2025-09-03 10:19:26 -04:00
l10n daemon script
9dd438e8a2 GIT_SILENT Sync po/docbooks with svn 2025-09-03 01:45:00 +00:00
Tobias Fella
cea5006e15 Revert "Use libQuotient qml module"
This reverts commit b80a2f94f4.
2025-09-03 00:00:16 +02:00
Tobias Fella
8ff3b31497 Fix some qml warnings in RoomDelegate 2025-09-02 23:00:15 +02:00
Tobias Fella
c7a9f9f07e Fix qml warnings in NotificationsView 2025-09-02 22:57:39 +02:00
Tobias Fella
1de10a4b87 Fix qml warnings in RoomAdvancedPage 2025-09-02 22:51:45 +02:00
Tobias Fella
d7f19efbd6 Fix qml warnings in MimeComponent 2025-09-02 22:49:27 +02:00
Tobias Fella
a3a28b2472 Fix qml warnings in PolLDelegate 2025-09-02 22:48:19 +02:00
Tobias Fella
919fc8b821 Fix qml warnings in DelegateContextMenu 2025-09-02 20:43:46 +00:00
Tobias Fella
b80a2f94f4 Use libQuotient qml module 2025-09-02 22:36:07 +02:00
Tobias Fella
6d18d1a237 Fix qml warnings 2025-09-02 15:36:21 +02:00
Tobias Fella
a2d64d2955 Fix some qml warnings 2025-09-02 15:06:58 +02:00
l10n daemon script
95617e3210 GIT_SILENT Sync po/docbooks with svn 2025-09-02 01:52:19 +00:00
Tobias Fella
1522f7086e Fix various qmllint warnings 2025-09-01 23:50:17 +02:00
Tobias Fella
14167d197f Fix some qml warnings 2025-09-01 23:33:25 +02:00
Tobias Fella
c377cf05b8 Fix qml warnings 2025-09-01 23:27:21 +02:00
Tobias Fella
4a52bc04fb Fix warning 2025-09-01 23:12:31 +02:00
Tobias Fella
53cd230d16 Remove redundant TapHandlers 2025-09-01 23:09:18 +02:00
Tobias Fella
e7b204b9fd Fix various qmllint warnings 2025-09-01 23:06:46 +02:00
Tobias Fella
4d91ae96e3 Only build required parts of opencv 2025-09-01 15:46:08 +02:00
Tobias Fella
b422d641de Add opencv to flatpak
Dependency of KQuickImageEditor
2025-09-01 14:58:27 +02:00
214 changed files with 64312 additions and 36323 deletions

View File

@@ -44,6 +44,22 @@
}
]
},
{
"name": "opencv",
"config-opts": [
"-DBUILD_TESTS=OFF",
"-DWITH_GTK=OFF",
"-DBUILD_LIST=core,imgproc"
],
"buildsystem": "cmake-ninja",
"sources": [
{
"type": "git",
"url": "https://github.com/opencv/opencv"
}
],
"builddir": true
},
{
"name": "kquickimageeditor",
"config-opts": [
@@ -131,7 +147,7 @@
{
"type": "git",
"url": "https://github.com/quotient-im/libQuotient.git",
"branch": "dev",
"branch": "0.9.6.1",
"disable-submodules": true
}
],
@@ -190,14 +206,6 @@
{
"type": "dir",
"path": "."
},
{
"type": "patch",
"path": "patches/0001-Revert-Bump-KF6-dependency-version.patch"
},
{
"type": "patch",
"path": "patches/0001-Revert-Use-new-Kirigami-builtin-column-resize-handle.patch"
}
]
}

View File

@@ -10,11 +10,11 @@ Dependencies:
'frameworks/ki18n': '@latest-kf6'
'frameworks/kconfig': '@latest-kf6'
'frameworks/syntax-highlighting': '@latest-kf6'
'frameworks/kiconthemes': '@latest-kf6'
'frameworks/kitemmodels': '@latest-kf6'
'frameworks/kquickcharts': '@latest-kf6'
'frameworks/knotifications': '@latest-kf6'
'frameworks/kcolorscheme': '@latest-kf6'
'frameworks/kiconthemes': '@latest-kf6'
'libraries/kquickimageeditor': '@latest-kf6'
'frameworks/sonnet': '@latest-kf6'
'frameworks/prison': '@latest-kf6'
@@ -29,7 +29,6 @@ Dependencies:
'frameworks/kio': '@latest-kf6'
'frameworks/kwindowsystem': '@latest-kf6'
'frameworks/kstatusnotifieritem': '@latest-kf6'
'frameworks/kcrash': '@latest-kf6'
- 'on': ['Linux', 'FreeBSD']
'require':
'frameworks/kdbusaddons': '@latest-kf6'

View File

@@ -8,14 +8,14 @@ cmake_minimum_required(VERSION 3.16)
# KDE Applications version, managed by release script.
set(RELEASE_SERVICE_VERSION_MAJOR "25")
set(RELEASE_SERVICE_VERSION_MINOR "11")
set(RELEASE_SERVICE_VERSION_MICRO "70")
set(RELEASE_SERVICE_VERSION_MINOR "12")
set(RELEASE_SERVICE_VERSION_MICRO "3")
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
set(KF_MIN_VERSION "6.17")
set(QT_MIN_VERSION "6.8")
set(QT_MIN_VERSION "6.9")
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
@@ -24,7 +24,7 @@ set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(KDE_COMPILERSETTINGS_LEVEL 6.0)
set(KDE_COMPILERSETTINGS_LEVEL 6.17)
include(FeatureSummary)
include(ECMSetupVersion)
@@ -39,6 +39,7 @@ include(ECMCheckOutboundLicense)
include(ECMQtDeclareLoggingCategory)
include(ECMAddAndroidApk)
include(ECMQmlModule)
include(ECMDeprecationSettings)
include(GenerateExportHeader)
include(ECMGenerateHeaders)
if (NOT ANDROID)
@@ -51,6 +52,8 @@ endif()
set(QUOTIENT_FORCE_NAMESPACED_INCLUDES TRUE)
ecm_set_disabled_deprecation_versions(Qt 6.9.0 KF 6.17.0)
ecm_setup_version(${PROJECT_VERSION}
VARIABLE_PREFIX NEOCHAT
VERSION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/neochat-version.h
@@ -66,7 +69,7 @@ if (QT_KNOWN_POLICY_QTP0004)
qt_policy(SET QTP0004 NEW)
endif ()
find_package(KF6 ${KF_MIN_VERSION} COMPONENTS Kirigami I18n Notifications Config CoreAddons Sonnet ItemModels IconThemes ColorScheme)
find_package(KF6 ${KF_MIN_VERSION} COMPONENTS Kirigami I18n Notifications Config CoreAddons Sonnet ItemModels ColorScheme IconThemes)
set_package_properties(KF6 PROPERTIES
TYPE REQUIRED
PURPOSE "Basic application components"
@@ -75,7 +78,7 @@ set_package_properties(KF6Kirigami PROPERTIES
TYPE REQUIRED
PURPOSE "Kirigami application UI framework"
)
find_package(KF6KirigamiAddons 1.6.0 REQUIRED)
find_package(KF6KirigamiAddons 1.10.0 REQUIRED)
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT NEOCHAT_FLATPAK AND NOT NEOCHAT_APPIMAGE)
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS Purpose)
@@ -89,7 +92,7 @@ if(ANDROID)
)
else()
find_package(Qt6 ${QT_MIN_VERSION} COMPONENTS Widgets)
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle KIO WindowSystem StatusNotifierItem Crash)
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle KIO WindowSystem StatusNotifierItem)
find_package(KF6SyntaxHighlighting ${KF_MIN_VERSION} REQUIRED)
set_package_properties(KF6QQC2DesktopStyle PROPERTIES
TYPE RUNTIME
@@ -107,7 +110,7 @@ if (NOT ANDROID AND NOT WIN32 AND NOT APPLE AND NOT HAIKU)
find_package(KF6DBusAddons ${KF_MIN_VERSION} REQUIRED)
endif()
find_package(QuotientQt6 0.9.1)
find_package(QuotientQt6 0.9.3)
set_package_properties(QuotientQt6 PROPERTIES
TYPE REQUIRED
DESCRIPTION "Qt wrapper around Matrix API"

View File

@@ -63,7 +63,7 @@ void ActionsTest::testActions_data()
QTest::addColumn<std::optional<QString>>("resultText");
QTest::addColumn<std::optional<Quotient::RoomMessageEvent::MsgType>>("type");
QTest::newRow("shrug") << u"/shrug Hello"_s << std::make_optional(u"¯\\\\_(ツ)_/¯ Hello"_s)
QTest::newRow("shrug") << u"/shrug Hello"_s << std::make_optional(u"¯\\\\\\_(ツ)\\_/¯ Hello"_s)
<< std::make_optional(Quotient::RoomMessageEvent::MsgType::Text);
QTest::newRow("lenny") << u"/lenny Hello"_s << std::make_optional(u"( ͡° ͜ʖ ͡°) Hello"_s) << std::make_optional(Quotient::RoomMessageEvent::MsgType::Text);
QTest::newRow("tableflip") << u"/tableflip Hello"_s << std::make_optional(u"(╯°□°)╯︵ ┻━┻ Hello"_s)

View File

@@ -28,6 +28,7 @@ private:
private Q_SLOTS:
void initTestCase();
void testMaximizeMedia();
void testResolveMatrixLinks();
};
void RoomManagerTest::initTestCase()
@@ -128,5 +129,13 @@ void RoomManagerTest::testMaximizeMedia()
QVERIFY(spy[1][0] == 0);
}
void RoomManagerTest::testResolveMatrixLinks()
{
// Test if resolving a non-joined room will bring up the confirmation dialog.
const QSignalSpy askToJoinSpy(&RoomManager::instance(), &RoomManager::askJoinRoom);
RoomManager::instance().resolveResource(QStringLiteral("matrix:r/testbuild:matrix.org"), QStringLiteral("join"));
QTRY_COMPARE(askToJoinSpy.size(), 1);
}
QTEST_MAIN(RoomManagerTest)
#include "roommanagertest.moc"

View File

@@ -4,15 +4,12 @@
#include "server.h"
#include <QFile>
#include <QHttpServer>
#include <QHttpServerResponder>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QSslCertificate>
#include <QSslKey>
#include <QSslServer>
#include <QUuid>
#include <Quotient/networkaccessmanager.h>

File diff suppressed because it is too large Load Diff

View File

@@ -44,7 +44,6 @@ Name[sv]=NeoChat
Name[ta]=நியோச்சாட்
Name[tr]=NeoChat
Name[uk]=NeoChat
Name[x-test]=xxNeoChatxx
Name[zh_CN]=NeoChat
Name[zh_TW]=NeoChat
GenericName=Matrix Client
@@ -88,7 +87,6 @@ GenericName[sv]=Matrix-klient
GenericName[ta]=Matrix வாங்கி
GenericName[tr]=Matrix İstemcisi
GenericName[uk]=Клієнт Matrix
GenericName[x-test]=xxMatrix Clientxx
GenericName[zh_CN]=Matrix 客户端
GenericName[zh_TW]=Matrix 用戶端
Comment=Chat on Matrix
@@ -114,6 +112,7 @@ Comment[lv]=Tērzējiet „Matrix“ tīklā
Comment[nl]=Chat op Matrix
Comment[pl]=Rozmawiaj na Matriksie
Comment[pt_BR]=Bate papo na Matrix
Comment[ro]=Discutați pe Matrix
Comment[ru]=Общение в Matrix
Comment[sa]=Matrix इत्यत्र गपशपं कुर्वन्तु
Comment[sl]=Klepet na Matrixu
@@ -121,7 +120,6 @@ Comment[sv]=Chatta på Matrix
Comment[ta]=மேட்ரிக்ஸில் உரையாட உதவும்
Comment[tr]=Matrix üzerinde sohbet edin
Comment[uk]=Спілкування у Matrix
Comment[x-test]=xxChat on Matrixxx
Comment[zh_CN]=在 Matrix 上聊天
Comment[zh_TW]=在 Matrix 上聊天
MimeType=x-scheme-handler/matrix;

View File

@@ -1,28 +0,0 @@
SPDX-FileCopyrightText: 2025 Tobias Fella <tobias.fella@kde.org>
SPDX-License-Identifier: BSD-2-Clause
From dbd1cefd0f07a6942aef450f8f3e082aa3b1cc25 Mon Sep 17 00:00:00 2001
From: Tobias Fella <tobias.fella@kde.org>
Date: Sun, 17 Aug 2025 20:04:04 +0200
Subject: [PATCH] Revert "Bump KF6 dependency version"
This reverts commit 18a6ea98232b3a734905fb18eebba9cf39bf5325.
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 10fe66daa..cd063113d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,7 +14,7 @@ set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
-set(KF_MIN_VERSION "6.17")
+set(KF_MIN_VERSION "6.12")
set(QT_MIN_VERSION "6.8")
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
--
2.50.1

View File

@@ -1,123 +0,0 @@
SPDX-FileCopyrightText: 2025 Tobias Fella <tobias.fella@kde.org>
SPDX-License-Identifier: BSD-2-Clause
From ca72345b8ee550be2172d8ac5e5dc9e4c2b508c9 Mon Sep 17 00:00:00 2001
From: Tobias Fella <tobias.fella@kde.org>
Date: Sun, 17 Aug 2025 20:00:08 +0200
Subject: [PATCH] Revert "Use new Kirigami builtin column resize handle"
This reverts commit de97275a387abcbca6fcb185bcbd1b69c30f5c66.
---
src/app/qml/Main.qml | 1 -
src/rooms/RoomListPage.qml | 70 +++++++++++++++++++++++++++++---------
2 files changed, 54 insertions(+), 17 deletions(-)
diff --git a/src/app/qml/Main.qml b/src/app/qml/Main.qml
index ea8955674..6eed271c1 100644
--- a/src/app/qml/Main.qml
+++ b/src/app/qml/Main.qml
@@ -45,7 +45,6 @@ Kirigami.ApplicationWindow {
showExisting: true
onConnectionChosen: root.load()
}
- columnView.columnResizeMode: pageStack.wideMode ? Kirigami.ColumnView.DynamicColumns : Kirigami.ColumnView.SingleColumn
globalToolBar.canContainHandles: true
globalToolBar {
style: Kirigami.ApplicationHeaderStyle.ToolBar
diff --git a/src/rooms/RoomListPage.qml b/src/rooms/RoomListPage.qml
index 2ac211fd5..f5586d789 100644
--- a/src/rooms/RoomListPage.qml
+++ b/src/rooms/RoomListPage.qml
@@ -17,22 +17,13 @@ import org.kde.neochat
Kirigami.Page {
id: root
- Kirigami.ColumnView.interactiveResizeEnabled: true
- Kirigami.ColumnView.minimumWidth: _private.collapsedSize + spaceDrawer.width + 1
- Kirigami.ColumnView.maximumWidth: _private.defaultWidth + spaceDrawer.width + 1
- Kirigami.ColumnView.onInteractiveResizingChanged: {
- if (!Kirigami.ColumnView.interactiveResizing && collapsed) {
- Kirigami.ColumnView.preferredWidth = root.Kirigami.ColumnView.minimumWidth;
- }
- }
- Kirigami.ColumnView.preferredWidth: _private.currentWidth + spaceDrawer.width + 1
- Kirigami.ColumnView.onPreferredWidthChanged: {
- if (width > _private.collapseWidth) {
- NeoChatConfig.collapsed = false;
- } else if (Kirigami.ColumnView.interactiveResizing) {
- NeoChatConfig.collapsed = true;
- }
- }
+ /**
+ * @brief The current width of the room list.
+ *
+ * @note Other objects can access the value but the private function makes sure
+ * that only the internal members can modify it.
+ */
+ readonly property int currentWidth: _private.currentWidth + spaceDrawer.width + 1
required property NeoChatConnection connection
@@ -40,6 +31,10 @@ Kirigami.Page {
signal search
+ onCurrentWidthChanged: pageStack.defaultColumnWidth = root.currentWidth
+ Component.onCompleted: pageStack.defaultColumnWidth = root.currentWidth
+
+
onCollapsedChanged: {
if (collapsed) {
RoomManager.sortFilterRoomTreeModel.filterText = "";
@@ -252,6 +247,49 @@ Kirigami.Page {
sourceComponent: Kirigami.Settings.isMobile ? exploreComponentMobile : userInfoDesktop
}
+ MouseArea {
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ parent: applicationWindow().overlay.parent
+
+ x: root.currentWidth - width / 2
+ width: Kirigami.Units.smallSpacing * 2
+ z: root.z + 1
+ enabled: RoomManager.hasOpenRoom && applicationWindow().width >= Kirigami.Units.gridUnit * 35
+ visible: enabled
+ cursorShape: Qt.SplitHCursor
+
+ property int _lastX
+
+ onPressed: mouse => {
+ _lastX = mouse.x;
+ }
+ onPositionChanged: mouse => {
+ if (_lastX == -1) {
+ return;
+ }
+ if (mouse.x > _lastX) {
+ // we moved to the right
+ if (_private.currentWidth < _private.collapseWidth && _private.currentWidth + (mouse.x - _lastX) >= _private.collapseWidth) {
+ // Here we get back directly to a more wide mode.
+ _private.currentWidth = _private.defaultWidth;
+ NeoChatConfig.collapsed = false;
+ } else if (_private.currentWidth >= _private.collapseWidth) {
+ // Increase page width
+ _private.currentWidth = Math.min(_private.defaultWidth, _private.currentWidth + (mouse.x - _lastX));
+ }
+ } else if (mouse.x < _lastX) {
+ const tmpWidth = _private.currentWidth - (_lastX - mouse.x);
+ if (tmpWidth < _private.collapseWidth) {
+ _private.currentWidth = Qt.binding(() => _private.collapsedSize);
+ NeoChatConfig.collapsed = true;
+ } else {
+ _private.currentWidth = tmpWidth;
+ }
+ }
+ }
+ }
+
Component {
id: userInfo
UserInfo {
--
2.50.1

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

7002
po/ga/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

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 % Brazilian-Portuguese "INCLUDE">
]>
<!--
SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
SPDX-License-Identifier: CC-BY-SA-4.0
-->
<refentry lang="&language;">
<refentryinfo>
<title
>Manual do Usuário do NeoChat</title>
<author
><firstname
>Carl</firstname
><surname
>Schwan</surname
> <contrib
>NeoChat man page.</contrib
> <email
>carl@carlschwan.eu</email
></author>
<date
>01/11/2022</date>
<releaseinfo
>22.09</releaseinfo>
<productname
>NeoChat</productname>
</refentryinfo>
<refmeta>
<refentrytitle>
<command
>neochat</command>
</refentrytitle>
<manvolnum
>1</manvolnum>
</refmeta>
<refnamediv>
<refname
>neochat</refname>
<refpurpose
>Cliente para interação com o protocolo de mensagens 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
>Descrição</title>
<para
>O <command
>neochat</command
> é um aplicativo de bate-papo para o protocolo Matrix. Ele funciona tanto em computadores quanto em dispositivos móveis. </para>
</refsect1>
<refsect1 id="options"
><title
>Opções</title>
<variablelist>
<varlistentry>
<term
><option
>URI</option
></term>
<listitem>
<para
>O URI da matriz para um usuário ou uma sala. Por exemplo, matrix:u/usuário:exemplo.org e matrix:r/root:exemplo.org. Isso fará com que o NeoChat tente abrir a sala ou conversa especificada. </para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1 id="bug">
<title
>Relatar bugs</title>
<para
>Você pode reportar erros e solicitar novas funcionalidades em <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
>Veja também</title>
<simplelist>
<member
>Lista de perguntas frequentes sobre o Matrix <ulink url="https://matrix.org/faq/"
>https://matrix.org/faq/</ulink
> </member>
<member
>kf5options(7)</member>
<member
>qt5options(7)</member>
</simplelist>
</refsect1>
<refsect1 id="copyright"
><title
>Direitos autorais</title>
<para
>Direitos autorais &copy; 2020-2022 Tobias Fella </para>
<para
>Direitos autorais &copy; 2020-2022 Carl Schwan </para>
<para
>Licença: GNU General Public Versão 3 ou posterior <ulink url="https://www.gnu.org/licenses/gpl-3.0.html"
>https://www.gnu.org/licenses/gpl-3.0.html</ulink
>&gt;</para>
</refsect1>
</refentry>

File diff suppressed because it is too large Load Diff

7049
po/ro/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

View File

@@ -48,6 +48,8 @@ if(ANDROID OR WIN32)
set_source_files_properties(qml/GlobalMenuStub.qml PROPERTIES
QT_QML_SOURCE_TYPENAME GlobalMenu
)
else()
set(EXTRA_IMPORTS org.kde.purpose)
endif()
ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
@@ -101,6 +103,7 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
qml/ReasonDialog.qml
qml/NewPollDialog.qml
qml/UserMenu.qml
qml/MeetingDialog.qml
DEPENDENCIES
QtCore
QtQuick
@@ -117,8 +120,8 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
org.kde.neochat.login
org.kde.neochat.chatbar
org.kde.config
org.kde.purpose
org.kde.syntaxhighlighting
${EXTRA_IMPORTS}
)
if(NOT ANDROID AND NOT WIN32)
@@ -150,6 +153,7 @@ target_include_directories(neochat-app PRIVATE ${CMAKE_BINARY_DIR})
target_link_libraries(neochat-app PRIVATE
neochat
KF6::IconThemes
)
ecm_add_app_icon(NEOCHAT_ICON ICONS ${CMAKE_SOURCE_DIR}/128-logo.png)
@@ -200,8 +204,9 @@ target_link_libraries(neochat PUBLIC
KF6::ConfigGui
KF6::CoreAddons
KF6::SonnetCore
KF6::IconThemes
KF6::ItemModels
KF6::I18nQml
KirigamiApp
QuotientQt6
Login
Rooms
@@ -209,10 +214,6 @@ target_link_libraries(neochat PUBLIC
Spaces
)
if (TARGET KF6::Crash)
target_link_libraries(neochat PUBLIC KF6::Crash)
endif()
kconfig_target_kcfg_file(neochat FILE neochatconfig.kcfg CLASS_NAME NeoChatConfig MUTATORS GENERATE_PROPERTIES DEFAULT_VALUE_GETTERS PARENT_IN_CONSTRUCTOR SINGLETON GENERATE_MOC QML_REGISTRATION)
if(NEOCHAT_FLATPAK)
@@ -323,6 +324,7 @@ if(ANDROID)
"kt-restore-defaults-symbolic"
"user-symbolic"
"mark-location-symbolic"
"amarok_playcount"
${KIRIGAMI_ADDONS_ICONS}
)
@@ -351,7 +353,8 @@ 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)
# krunner plugin must be the same as the app id for flatpak to export it
install(FILES plasma-runner-neochat.desktop DESTINATION ${KDE_INSTALL_DATAROOTDIR}/krunner/dbusplugins RENAME org.kde.neochat.desktop)
endif()
if (APPLE)

View File

@@ -17,7 +17,6 @@
#include <Quotient/qt_connection_util.h>
#include <Quotient/settings.h>
#include "accountmanager.h"
#include "enums/roomsortparameter.h"
#include "general_logging.h"
#include "mediasizehelper.h"
@@ -26,9 +25,7 @@
#include "models/roomlistmodel.h"
#include "models/roomtreemodel.h"
#include "neochatconfig.h"
#include "neochatconnection.h"
#include "neochatroom.h"
#include "notificationsmanager.h"
#include "proxycontroller.h"
#include "roommanager.h"
@@ -309,8 +306,7 @@ void Controller::listenForNotifications()
connect(timer, &QTimer::timeout, qGuiApp, &QGuiApplication::quit);
connect(connector, &KUnifiedPush::Connector::messageReceived, [timer](const QByteArray &data) {
instance().m_notificationsManager.postPushNotification(data);
timer->stop();
NotificationsManager::postPushNotification(data);
});
// Wait five seconds to see if we received any messages or this happened to be an erroneous activation.

View File

@@ -33,13 +33,10 @@
#include <KWindowSystem>
#endif
#if __has_include("KCrash")
#include <KCrash>
#endif
#include <KIconTheme>
#include <KLocalizedContext>
#include <KLocalizedQmlContext>
#include <KLocalizedString>
#include <KirigamiApp>
#include "neochat-version.h"
@@ -104,33 +101,22 @@ Q_DECL_EXPORT
#endif
int main(int argc, char *argv[])
{
KIconTheme::initTheme();
QNetworkProxyFactory::setUseSystemConfiguration(true);
// We currently need to do this ourselves,
// KirigamiApp currently called this after constructing the app which breaks icons on Windows.
KIconTheme::initTheme();
#ifdef HAVE_WEBVIEW
QtWebView::initialize();
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
#endif
#ifdef Q_OS_ANDROID
QGuiApplication app(argc, argv);
QQuickStyle::setStyle(u"org.kde.breeze"_s);
#else
QIcon::setFallbackThemeName("breeze"_L1);
QApplication app(argc, argv);
// Default to org.kde.desktop style unless the user forces another style
if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) {
QQuickStyle::setStyle(u"org.kde.desktop"_s);
}
#endif
KirigamiApp::App app(argc, argv);
KirigamiApp kirigamiApp;
#ifdef Q_OS_WINDOWS
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
}
QApplication::setStyle(u"breeze"_s);
QFont font(u"Segoe UI Emoji"_s);
font.setPointSize(10);
@@ -177,10 +163,6 @@ int main(int argc, char *argv[])
KAboutData::setApplicationData(about);
QGuiApplication::setWindowIcon(QIcon::fromTheme(u"org.kde.neochat"_s));
#if __has_include("KCrash")
KCrash::initialize();
#endif
Connection::setEncryptionDefault(true);
Connection::setDirectChatEncryptionDefault(true);
@@ -205,7 +187,7 @@ int main(int argc, char *argv[])
parser.addOption(testOption);
#ifdef HAVE_KUNIFIEDPUSH
QCommandLineOption dbusActivatedOption(u"dbus-activated"_s, i18n("Internal usage only."));
QCommandLineOption dbusActivatedOption(u"dbus-activated"_s);
dbusActivatedOption.setFlags(QCommandLineOption::Flag::HiddenFromHelp);
parser.addOption(dbusActivatedOption);
#endif
@@ -219,8 +201,14 @@ int main(int argc, char *argv[])
#ifdef HAVE_KUNIFIEDPUSH
if (parser.isSet(dbusActivatedOption)) {
// We want to be replaceable by the main client
KDBusService service(KDBusService::Replace);
#ifdef HAVE_KDBUSADDONS
// We *don't* want to use KDBusService here. I don't know why, but it makes activation super unreliable. We don't really need it anyway.
if (!QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.neochat"))) {
// Gracefully fail if NeoChat is already running
qWarning() << "NeoChat already running, not sending push notifications.";
return 0;
}
#endif
#ifdef HAVE_RUNNER
// If we are built with KRunner and KUnifiedPush support, we need to do something special.
@@ -279,7 +267,7 @@ int main(int argc, char *argv[])
});
#endif
engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
KLocalization::setupLocalizedContext(&engine);
engine.setNetworkAccessManagerFactory(new NetworkAccessManagerFactory());
if (parser.isSet("ignore-ssl-errors"_L1)) {
@@ -294,7 +282,9 @@ int main(int argc, char *argv[])
engine.addImageProvider(u"blurhash"_s, new BlurhashImageProvider);
engine.loadFromModule("org.kde.neochat", "Main");
if (!kirigamiApp.start("org.kde.neochat", "Main", &engine)) {
return -1;
}
if (!parser.positionalArguments().isEmpty() && !parser.isSet("share"_L1)) {
RoomManager::instance().setUrlArgument(parser.positionalArguments()[0]);

View File

@@ -58,7 +58,7 @@ QVariant NotificationsModel::data(const QModelIndex &index, int role) const
QHash<int, QByteArray> NotificationsModel::roleNames() const
{
return {
{TextRole, "text"},
{TextRole, "notificationText"},
{RoomIdRole, "roomId"},
{AuthorName, "authorName"},
{AuthorAvatar, "authorAvatar"},

View File

@@ -42,7 +42,6 @@ Name[sv]=NeoChat
Name[ta]=நியோச்சாட்
Name[tr]=NeoChat
Name[uk]=NeoChat
Name[x-test]=xxNeoChatxx
Name[zh_CN]=NeoChat
Name[zh_TW]=NeoChat
DesktopEntry=org.kde.neochat
@@ -87,7 +86,6 @@ Comment[sv]=En klient för matrix, det decentraliserade kommunikationsprotokolle
Comment[ta]=மையமில்லா தகவல் பரிமாற்ற நெறிமுறையான மேட்ரிக்ஸுக்கான செயலி
Comment[tr]=Merkezi olmayan iletişim protokolü Matrix için bir istemci
Comment[uk]=Клієнт matrix, децентралізованого протоколу обміну даними
Comment[x-test]=xxA client for matrix, the decentralized communication protocolxx
Comment[zh_CN]=分布式通讯协议 Matrix 的客户端
Comment[zh_TW]=去中心化通訊協定 Matrix 的用戶端
@@ -134,7 +132,6 @@ Name[sv]=Nytt meddelande
Name[ta]=புதிய செய்தி
Name[tr]=Yeni İleti
Name[uk]=Нове повідомлення
Name[x-test]=xxNew messagexx
Name[zh_CN]=新消息
Name[zh_TW]=新訊息
Comment=There is a new message
@@ -177,7 +174,6 @@ Comment[sv]=Det finns ett nytt meddelande
Comment[ta]=ஒரு புதிய செய்தி உள்ளது
Comment[tr]=Yeni bir ileti var
Comment[uk]=Надійшло нове повідомлення
Comment[x-test]=xxThere is a new messagexx
Comment[zh_CN]=有新消息
Comment[zh_TW]=有新的訊息
Action=Popup
@@ -215,6 +211,7 @@ Name[pa]=ਨਵਾਂ ਸੱਦਾ
Name[pl]=Nowe zaproszenie
Name[pt]=Novo Convite
Name[pt_BR]=Novo convite
Name[ro]=Invitație nouă
Name[ru]=Новое приглашение
Name[sa]=नवीन आमन्त्रणम्
Name[sl]=Novo povabilo
@@ -222,7 +219,6 @@ Name[sv]=Ny inbjudan
Name[ta]=புதிய அழைப்பிதழ்
Name[tr]=Yeni Davet
Name[uk]=Нове запрошення
Name[x-test]=xxNew Invitationxx
Name[zh_CN]=新邀请
Name[zh_TW]=新邀請
Comment=There is a new invitation to a room
@@ -257,14 +253,14 @@ Comment[pa]=ਰੂਮ ਲਈ ਨਵਾਂ ਸੱਦਾ ਹੈ
Comment[pl]=Dostępna jest nowe zaproszenie do pokoju
Comment[pt]=Existe um novo convite para uma sala
Comment[pt_BR]=Existe um novo convite para uma sala
Comment[ro]=E o nouă invitație la o cameră
Comment[ru]=Доступно новое приглашение в комнату
Comment[sa]=कक्षस्य नूतनं निमन्त्रणम् अस्ति
Comment[sl]=Tam je novo povabilo v sobo
Comment[sv]=Det finns en ny inbjudan till ett rum
Comment[ta]=ஓர் அரங்கிற்கான புதிய அழைப்பிதழ் உள்ளது
Comment[tr]=Bir odaya yeni bir davetiye var
Comment[tr]=Bir odaya yeni bir davet var
Comment[uk]=У кімнаті нове запрошення
Comment[x-test]=xxThere is a new invitation to a roomxx
Comment[zh_CN]=有新的聊天室邀请
Comment[zh_TW]=有新的加入聊天室邀請
Action=Popup
@@ -296,6 +292,7 @@ Name[nl]=Gedeelde
Name[nn]=Del
Name[pl]=Udostępnij
Name[pt_BR]=Compartilhar
Name[ro]=Partajare
Name[ru]=Публикация
Name[sa]=संविभागः
Name[sl]=Deli
@@ -303,7 +300,6 @@ Name[sv]=Dela
Name[ta]=பகிர்
Name[tr]=Paylaş
Name[uk]=Оприлюднення
Name[x-test]=xxSharexx
Name[zh_CN]=分享
Name[zh_TW]=分享
Comment=The result of sharing a piece of content
@@ -331,6 +327,7 @@ Comment[nl]=Het resultaat van het delen van een stukje inhoud
Comment[nn]=Resultatet av deling av innhald
Comment[pl]=Wynik udostępniania kawałka treści
Comment[pt_BR]=O resultado de compartilhar um conteúdo
Comment[ro]=Rezultatul partajării unei bucăți de conținut
Comment[ru]=Результат публикации данных
Comment[sa]=सामग्रीखण्डस्य साझाकरणस्य परिणामः
Comment[sl]=Rezultat deljenega kosa vsebine
@@ -338,7 +335,6 @@ Comment[sv]=Resultatet av att dela innehåll
Comment[ta]=எதையோ பகிர்ந்த‍தன் விளைவு
Comment[tr]=Bir parça içerik paylaşımının sonucu
Comment[uk]=Результат оприлюднення даних
Comment[x-test]=xxThe result of sharing a piece of contentxx
Comment[zh_CN]=分享一个内容得到的结果
Comment[zh_TW]=分享一份內容之後的結果
Action=Popup

View File

@@ -66,6 +66,10 @@
</entry>
</group>
<group name="Timeline">
<entry name="FontScale" type="double">
<label>Scaling factor for font sizes</label>
<default>1.0</default>
</entry>
<entry name="ShowAvatarInTimeline" type="bool">
<label>Show avatar in the timeline</label>
<default>true</default>

View File

@@ -216,12 +216,12 @@ void NotificationsManager::postNotification(NeoChatRoom *room,
}
});
notification->setTitle(room->displayName());
QString entry;
if (sender == room->displayName()) {
notification->setTitle(sender);
if (room->isDirectChat()) {
entry = text.toHtmlEscaped();
} else {
notification->setTitle(room->displayName());
entry = i18n("%1: %2", sender, text.toHtmlEscaped());
}
@@ -253,7 +253,9 @@ void NotificationsManager::postNotification(NeoChatRoom *room,
notification->setReplyAction(std::move(replyAction));
}
notification->setHint(u"x-kde-origin-name"_s, room->localMember().id());
if (Controller::instance().accounts()->rowCount() > 1) {
notification->setHint(u"x-kde-origin-name"_s, room->localMember().id());
}
notification->sendEvent();
}
@@ -347,7 +349,9 @@ void NotificationsManager::doPostInviteNotification(QPointer<NeoChatRoom> room)
m_invitations.remove(room->id());
});
notification->setHint(u"x-kde-origin-name"_s, room->localMember().id());
if (Controller::instance().accounts()->rowCount() > 1) {
notification->setHint(u"x-kde-origin-name"_s, room->localMember().id());
}
notification->sendEvent();
}
@@ -388,7 +392,7 @@ void NotificationsManager::postPushNotification(const QByteArray &message)
#ifdef HAVE_KIO
auto openAction = notification->addAction(i18n("Open NeoChat"));
connect(openAction, &KNotificationAction::activated, this, [=]() {
connect(openAction, &KNotificationAction::activated, notification, [=]() {
QString properId = roomId;
properId = properId.replace(u"#"_s, QString());
properId = properId.replace(u"!"_s, QString());
@@ -402,8 +406,6 @@ void NotificationsManager::postPushNotification(const QByteArray &message)
connect(notification, &KNotification::closed, qGuiApp, &QGuiApplication::quit);
notification->sendEvent();
m_notifications.insert(roomId, {json["ts"_L1].toVariant().toLongLong(), notification});
} else {
qWarning() << "Skipping unsupported push notification" << type;
}

View File

@@ -53,7 +53,7 @@ public:
/**
* @brief Display a native notification for the given push notification.
*/
void postPushNotification(const QByteArray &message);
static void postPushNotification(const QByteArray &message);
/**
* @brief Handle the notifications for the given connection.

View File

@@ -43,7 +43,6 @@ Name[sv]=NeoChat
Name[ta]=நியோச்சாட்
Name[tr]=NeoChat
Name[uk]=NeoChat
Name[x-test]=xxNeoChatxx
Name[zh_CN]=NeoChat
Name[zh_TW]=NeoChat
Comment=Find rooms in NeoChat
@@ -76,6 +75,7 @@ Comment[nn]=Finn rom i NeoChat
Comment[pl]=Znajdź pokoje w NeoChat
Comment[pt]=Procurar salas no NeoChat
Comment[pt_BR]=Encontrar salas no NeoChat
Comment[ro]=Găsește camere în NeoChat
Comment[ru]=Поиск комнат NeoChat
Comment[sa]=NeoChat इत्यत्र कक्ष्याः अन्वेषणं कुर्वन्तु
Comment[sl]=Najdi sobe v NeoChatu
@@ -83,7 +83,6 @@ Comment[sv]=Sök efter rum i NeoChat
Comment[ta]=நியோச்சாட்டில் அரங்குகளை கண்டுபிடிக்கும்
Comment[tr]=NeoChatte odalar bulun
Comment[uk]=Пошук кімнат у NeoChat
Comment[x-test]=xxFind rooms in NeoChatxx
Comment[zh_CN]=在 NeoChat 查找聊天室
Comment[zh_TW]=在 NeoChat 尋找聊天室
X-KDE-ServiceTypes=Plasma/Runner

View File

@@ -88,7 +88,7 @@ KirigamiComponents.ConvergentContextMenu {
Kirigami.Action {
text: i18nc("@action:inmenu", "Verify This Device")
icon.name: "security-low"
visible: !root.connection.isVerifiedSession()
visible: !root.connection.isVerifiedSession
onTriggered: {
root.connection.startSelfVerification();
const dialog = Qt.createComponent("org.kde.kirigami", "PromptDialog").createObject(QQC2.Overlay.overlay, {

View File

@@ -61,7 +61,7 @@ Kirigami.Dialog {
}
onClicked: {
pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.login', 'WelcomePage'), {}, {
((root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat.login', 'WelcomePage'), {}, {
title: i18nc("@title:window", "Login")
});
root.close();
@@ -95,8 +95,8 @@ Kirigami.Dialog {
accountView.decrementCurrentIndex();
}
}
Keys.onEnterPressed: (accountView.currentItem as Delegates.RoundedItemDelegate).clicked()
Keys.onReturnPressed: (accountView.currentItem as Delegates.RoundedItemDelegate).clicked()
Keys.onEnterPressed: ((accountView.currentItem ?? accountView.footerItem) as Delegates.RoundedItemDelegate).clicked()
Keys.onReturnPressed: ((accountView.currentItem ?? accountView.footerItem) as Delegates.RoundedItemDelegate).clicked()
onVisibleChanged: {
for (let i = 0; i < accountView.count; i++) {

View File

@@ -21,6 +21,7 @@ Delegates.RoundedItemDelegate {
signal contextMenuRequested
signal selected
activeFocusOnTab: true
padding: Kirigami.Units.largeSpacing
QQC2.ToolTip.visible: hovered

View File

@@ -48,7 +48,7 @@ Components.AbstractMaximizeComponent {
implicitWidth: Kirigami.Units.iconSizes.medium
implicitHeight: Kirigami.Units.iconSizes.medium
name: root.author.name ?? root.author.displayName
name: root.author.displayName
source: root.author.avatarUrl
color: root.author.color
}
@@ -57,7 +57,7 @@ Components.AbstractMaximizeComponent {
QQC2.Label {
id: userLabel
text: root.author.name ?? root.author.displayName
text: root.author.displayName
color: root.author.color
font.weight: Font.Bold
elide: Text.ElideRight
@@ -91,6 +91,7 @@ Components.AbstractMaximizeComponent {
color: Kirigami.Theme.textColor
font.family: "monospace"
font.pointSize: Kirigami.Theme.defaultFont.pointSize * NeoChatConfig.fontScale
Kirigami.SpellCheck.enabled: false
@@ -149,4 +150,6 @@ Components.AbstractMaximizeComponent {
color: Kirigami.Theme.backgroundColor
}
}
onOpened: forceActiveFocus()
}

View File

@@ -6,16 +6,15 @@ import QtQuick.Controls as QQC2
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.neochat
ColumnLayout {
id: root
property alias emoji: emojiLabel.text
property alias description: descriptionLabel.text
required property string emoji
required property string description
QQC2.Label {
id: emojiLabel
text: root.emoji
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.iconSizes.huge
Layout.preferredHeight: Kirigami.Units.iconSizes.huge
@@ -25,7 +24,7 @@ ColumnLayout {
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 4
}
QQC2.Label {
id: descriptionLabel
text: root.description
Layout.fillWidth: true
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter

View File

@@ -17,9 +17,6 @@ RowLayout {
Repeater {
id: repeater
delegate: EmojiItem {
emoji: modelData.emoji
description: modelData.description
}
delegate: EmojiItem {}
}
}

View File

@@ -17,7 +17,7 @@ ApplicationWindow {
property real longitude: NaN
property string asset
property var author
property QtObject liveLocationModel: null
property LiveLocationsModel liveLocationModel: null
flags: Qt.FramelessWindowHint | Qt.WA_TranslucentBackground
visibility: Qt.WindowFullScreen
@@ -59,7 +59,7 @@ ApplicationWindow {
Connections {
target: mapView.map
function onCopyrightLinkActivated() {
function onCopyrightLinkActivated(link: string) {
Qt.openUrlExternally(link);
}
}

View File

@@ -22,12 +22,12 @@ Labs.MenuBar {
Labs.MenuItem {
icon.name: "list-add-user"
text: i18nc("@action:inmenu", "Find your Friends")
text: i18nc("@action:inmenu", "Find User")
enabled: root.connection
onTriggered: root.appWindow.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'UserSearchPage'), {
connection: root.connection
}, {
title: i18nc("@title", "Find your friends")
title: i18nc("@title", "Find User")
})
}
Labs.MenuItem {

View File

@@ -3,8 +3,10 @@
import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.neochat
Item {
required property NeoChatConnection connection
required property Kirigami.ApplicationWindow appWindow
}

View File

@@ -66,7 +66,7 @@ Kirigami.Dialog {
text: i18nc("@action:button", "Join room")
icon.name: "irc-join-channel"
onClicked: {
RoomManager.resolveResource(root.room, "join");
RoomManager.resolveResource(root.room, "join_confirmed");
root.close();
}
}

View File

@@ -4,6 +4,7 @@
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
import QtQuick.Window
import QtQml
import org.kde.kirigami as Kirigami
@@ -170,6 +171,8 @@ Kirigami.Page {
return "";
}
}
isDone: root.session.state === KeyVerificationSession.DONE
onDone: root.closeDialog()
}
}

View File

@@ -45,6 +45,8 @@ Components.AbstractMaximizeComponent {
}
]
onOpened: forceActiveFocus()
PositionSource {
id: positionSource

View File

@@ -100,7 +100,8 @@ Kirigami.ApplicationWindow {
function onCurrentRoomChanged() {
if (RoomManager.currentRoom && root.pageStack.depth <= 1 && root.initialized && Kirigami.Settings.isMobile) {
let roomPage = root.pageStack.layers.push(Qt.createComponent('org.kde.neochat', 'RoomPage'));
let roomPage = pageStack.push(Qt.createComponent('org.kde.neochat', 'RoomPage'));
roomPage.forceActiveFocus();
roomPage.backRequested.connect(event => {
RoomManager.clearCurrentRoom();
});
@@ -233,7 +234,7 @@ Kirigami.ApplicationWindow {
RoomListPage {
id: roomList
onSearch: quickSwitcher.open()
onSearch: root.quickSwitcher.open()
connection: root.connection
@@ -267,6 +268,17 @@ Kirigami.ApplicationWindow {
}
}
Connections {
target: root.connection
function onLoggedOut(): void {
root.pageStack.clear();
let page = root.pageStack.push(Qt.createComponent('org.kde.neochat.login', 'WelcomePage'), {
showExisting: true,
}) as WelcomePage;
page.connectionChosen.connect(() => root.load())
}
}
Connections {
target: AccountRegistry
function onRowsRemoved() {
@@ -347,7 +359,11 @@ Kirigami.ApplicationWindow {
user: user,
connection: root.connection,
}) as UserDetailDialog;
dialog.parent = QmlUtils.focusedWindowItem(); // Kirigami Dialogs overwrite the parent, so we need to set it again
// FIXME: The reason why we don't want the focusedWindowItem for the room null case (aka QR codes) is because it will parent it to the soon-to-be-destroyed window item.
// But this won't be a problem if we turn it into a Kirigami.Dialog or some other in-scene item, which it really should be.
if (room != null) {
dialog.parent = QmlUtils.focusedWindowItem(); // Kirigami Dialogs overwrite the parent, so we need to set it again
}
dialog.open();
}

View File

@@ -0,0 +1,22 @@
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-only
import QtQuick
import org.kde.kirigami as Kirigami
Kirigami.PromptDialog {
id: root
required property bool hasExistingMeeting
title: hasExistingMeeting ? i18nc("@title", "Join Meeting") : i18nc("@title", "Start Meeting")
subtitle: hasExistingMeeting ? i18nc("@info:label", "You are about to join a Jitsi meeting in your web browser.") : i18nc("@info:label", "You are about to start a new Jitsi meeting in your web browser.")
standardButtons: Kirigami.Dialog.Cancel
customFooterActions: Kirigami.Action {
icon.name: "camera-video-symbolic"
text: hasExistingMeeting ? i18nc("@action:button Join the Jitsi meeting", "Join") : i18nc("@action:button Start a new Jitsi meeting", "Start")
onTriggered: root.accept()
}
}

View File

@@ -34,8 +34,8 @@ Kirigami.Page {
enabled: root.model
target: root.room
function onChanged(): void {
root.contentJson = model.stateEventContentJson(root.type, root.stateKey);
root.sourceText = model.stateEventJson(root.type, root.stateKey);
root.contentJson = root.model.stateEventContentJson(root.type, root.stateKey);
root.sourceText = root.model.stateEventJson(root.type, root.stateKey);
}
}
@@ -46,8 +46,8 @@ Kirigami.Page {
text: i18nc("@action As in 'edit the state of this room'", "Edit state")
icon.name: "document-edit"
visible: root.allowEdit
enabled: room.canSendState(root.type) && (!root.stateKey.startsWith("@") || root.stateKey === root.room.connection.localUserId) && root.type !== "m.room.create"
onTriggered: pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat", "EditStateDialog"), {
enabled: root.room.canSendState(root.type) && (!root.stateKey.startsWith("@") || root.stateKey === root.room.connection.localUserId) && root.type !== "m.room.create"
onTriggered: (root.Kirigami.PageStack.pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent("org.kde.neochat", "EditStateDialog"), {
room: root.room,
type: root.type,
stateKey: root.stateKey,

View File

@@ -1,6 +1,8 @@
// 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
pragma ComponentBehavior: Bound
import QtCore as Core
import QtQuick
import QtQuick.Controls as QQC2
@@ -21,13 +23,13 @@ Components.AlbumMaximizeComponent {
*/
required property NeoChatRoom currentRoom
readonly property string currentEventId: model.data(model.index(content.currentIndex, 0), TimelineMessageModel.EventIdRole)
readonly property string currentEventId: model.data(model.index((content as ListView).currentIndex, 0), TimelineMessageModel.EventIdRole)
readonly property var currentAuthor: model.data(model.index(content.currentIndex, 0), TimelineMessageModel.AuthorRole)
readonly property var currentAuthor: model.data(model.index((content as ListView).currentIndex, 0), TimelineMessageModel.AuthorRole)
readonly property var currentTime: model.data(model.index(content.currentIndex, 0), TimelineMessageModel.TimeRole)
readonly property var currentTime: model.data(model.index((content as ListView).currentIndex, 0), TimelineMessageModel.TimeRole)
readonly property var currentProgressInfo: model.data(model.index(content.currentIndex, 0), TimelineMessageModel.ProgressInfoRole)
readonly property var currentProgressInfo: model.data(model.index((content as ListView).currentIndex, 0), TimelineMessageModel.ProgressInfoRole)
actions: [
ShareAction {
@@ -59,28 +61,28 @@ Components.AlbumMaximizeComponent {
downloadAction: Components.DownloadAction {
onTriggered: {
currentRoom.downloadFile(root.currentEventId, Core.StandardPaths.writableLocation(Core.StandardPaths.CacheLocation) + "/" + root.currentEventId.replace(":", "_").replace("/", "_").replace("+", "_") + currentRoom.fileNameToDownload(root.currentEventId));
root.currentRoom.downloadFile(root.currentEventId, Core.StandardPaths.writableLocation(Core.StandardPaths.CacheLocation) + "/" + root.currentEventId.replace(":", "_").replace("/", "_").replace("+", "_") + root.currentRoom.fileNameToDownload(root.currentEventId));
}
}
playAction: Kirigami.Action {
onTriggered: {
MediaManager.startPlayback();
currentItem.play();
(root.currentItem as Components.VideoMaximizeDelegate).play();
}
}
Connections {
target: MediaManager
function onPlaybackStarted() {
if (currentItem.playbackState === MediaPlayer.PlayingState) {
currentItem.pause();
if ((root.currentItem as Components.VideoMaximizeDelegate).playbackState === MediaPlayer.PlayingState) {
(root.currentItem as Components.VideoMaximizeDelegate).pause();
}
}
}
Connections {
target: currentRoom
target: root.currentRoom
function onFileTransferProgress(id, progress, total) {
if (id == root.currentEventId) {
@@ -123,7 +125,7 @@ Components.AlbumMaximizeComponent {
onItemRightClicked: RoomManager.viewEventMenu(root.currentEventId, root.currentRoom)
onSaveItem: {
var dialog = saveAsDialog.createObject(QQC2.Overlay.overlay);
var dialog = saveAsDialog.createObject(QQC2.Overlay.overlay) as Dialogs.FileDialog;
dialog.selectedFile = currentRoom.fileNameToDownload(root.currentEventId);
dialog.open();
}
@@ -146,7 +148,7 @@ Components.AlbumMaximizeComponent {
if (!selectedFile) {
return;
}
currentRoom.downloadFile(root.currentEventId, selectedFile);
root.currentRoom.downloadFile(root.currentEventId, selectedFile);
}
}
}

View File

@@ -1,12 +1,13 @@
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigami.delegates as KD
import org.kde.kirigamiaddons.components as Components
import org.kde.neochat
@@ -41,15 +42,23 @@ Kirigami.ScrollablePage {
}
delegate: QQC2.ItemDelegate {
id: notificationDelegate
required property string uri
required property string authorAvatar
required property string authorName
required property string roomDisplayName
required property string notificationText
width: parent?.width ?? 0
onClicked: RoomManager.resolveResource(model.uri)
onClicked: RoomManager.resolveResource(uri)
contentItem: RowLayout {
spacing: Kirigami.Units.largeSpacing
Components.Avatar {
source: model.authorAvatar
name: model.authorName
source: notificationDelegate.authorAvatar
name: notificationDelegate.authorName
implicitHeight: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2
implicitWidth: implicitHeight
@@ -66,7 +75,7 @@ Kirigami.ScrollablePage {
QQC2.Label {
id: label
text: model.roomDisplayName
text: notificationDelegate.roomDisplayName
elide: Text.ElideRight
font.weight: Font.Normal
textFormat: Text.PlainText
@@ -78,10 +87,9 @@ Kirigami.ScrollablePage {
QQC2.Label {
id: subtitle
text: model.text
text: notificationDelegate.notificationText
elide: Text.ElideRight
font: Kirigami.Theme.smallFont
opacity: root.hasNotifications ? 0.9 : 0.7
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop

View File

@@ -27,9 +27,26 @@ Kirigami.Page {
}
}
MediaDevices {
id: devices
}
Rectangle {
anchors.fill: parent
color: Kirigami.Theme.backgroundColor
visible: devices.videoInputs.length === 0
Kirigami.PlaceholderMessage {
text: i18nc("@info", "No Camera Connected")
anchors.centerIn: parent
}
}
VideoOutput {
id: viewFinder
anchors.centerIn: parent
visible: devices.videoInputs.length > 0
}
Prison.VideoScanner {
@@ -47,6 +64,8 @@ Kirigami.Page {
}
CaptureSession {
id: session
camera: Camera {
id: camera
}

View File

@@ -22,7 +22,7 @@ Kirigami.SearchDialog {
}
onAccepted: if (currentItem) {
(currentItem as QQC2.ItemDelegate).clicked();
(root.currentItem as RoomDelegate).clicked();
}
onTextChanged: RoomManager.sortFilterRoomListModel.filterText = text

View File

@@ -31,7 +31,7 @@ Kirigami.Page {
Keys.onReturnPressed: event => {
if (event.modifiers & Qt.ControlModifier) {
root.accepted(reason.text);
root.closeDialog();
root.Kirigami.PageStack.closeDialog();
}
}
@@ -52,14 +52,14 @@ Kirigami.Page {
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
onClicked: {
root.accepted(reason.text);
root.closeDialog();
root.Kirigami.PageStack.closeDialog();
}
}
QQC2.Button {
icon.name: "dialog-cancel-symbolic"
text: i18nc("@action", "Cancel")
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole
onClicked: root.closeDialog()
onClicked: root.Kirigami.PageStack.closeDialog()
}
}
}

View File

@@ -2,9 +2,12 @@
// SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
// SPDX-License-Identifier: GPL-3.0-only
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Window
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
@@ -56,18 +59,92 @@ Kirigami.Page {
*/
property MediaMessageFilterModel mediaMessageFilterModel: RoomManager.mediaMessageFilterModel
/**
* @brief The WidgetModel to use.
*
* This model has the list of widgets available in the current room.
*
* @note For loading a room in a different window, override this with a new
* WidgetModel.
*
* @sa WidgetModel
*/
property WidgetModel widgetModel: RoomManager.widgetModel
title: root.currentRoom ? root.currentRoom.displayName : ""
focus: true
padding: 0
background: null // This needs to stay null, because of transparency blur
onHeightChanged: {
// HACK: See TimelineView for the hack details.
// We get the height change here *first* so we are informed this is because of a window resize and not due to the pinned message.
resetViewSettling();
}
// Resets the view settling of the timeline.
// This should be called whenever the apparent height of the timeline changes, or else the view will scroll on its own!
function resetViewSettling(): void {
(timelineViewLoader.item as TimelineView).resetViewSettling();
}
actions: [
Kirigami.Action {
visible: Kirigami.Settings.isMobile || !(root.Kirigami.PageStack.pageStack as Kirigami.PageRow).wideMode
id: jitsiMeetingAction
readonly property bool hasExistingMeeting: root.widgetModel.jitsiIndex >= 0
readonly property bool canStartNewMeeting: root.currentRoom.canSendState("im.vector.modular.widgets")
tooltip: {
if (hasExistingMeeting) {
return i18nc("@action:button", "Join Jitsi meeting…");
}
return canStartNewMeeting ? i18nc("@action:button", "Start Jitsi meeting…") : i18nc("@action:button", "You do not have permissions to start Jitsi meetings")
}
icon {
name: "camera-video-symbolic"
color: hasExistingMeeting ? Kirigami.Theme.highlightColor : "transparent"
}
enabled: hasExistingMeeting || canStartNewMeeting
visible: root.currentRoom && !root.currentRoom.isSpace
onTriggered: {
const dialog = Qt.createComponent("org.kde.neochat", "MeetingDialog").createObject(QQC2.Overlay.overlay, { hasExistingMeeting });
dialog.onAccepted.connect(doAction);
dialog.open();
}
function doAction(): void {
let url;
if (!hasExistingMeeting) {
url = root.widgetModel.addJitsiConference();
} else {
let idx = root.widgetModel.index(root.widgetModel.jitsiIndex, 0);
url = root.widgetModel.data(idx, WidgetModel.UrlRole);
}
Qt.openUrlExternally(url);
}
},
Kirigami.Action {
visible: Kirigami.Settings.isMobile || !(root.Kirigami.PageStack.pageStack as Kirigami.PageRow)?.wideMode
icon.name: "view-right-new"
onTriggered: (root.QQC2.ApplicationWindow.window as Main).openRoomDrawer()
}
]
Kirigami.Action {
enabled: root.currentRoom && !root.currentRoom.isSpace
shortcut: "Ctrl+F"
onTriggered: {
((root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomSearchPage'), {
room: root.currentRoom
}, {
title: i18nc("@action:title", "Search")
});
}
}
KeyNavigation.left: (root.Kirigami.PageStack.pageStack as Kirigami.PageRow).get(0)
onCurrentRoomChanged: {
@@ -77,9 +154,9 @@ Kirigami.Page {
if (root.currentRoom.tagNames.includes("m.server_notice")) {
banner.text = i18nc("@info", "This room contains official messages from your homeserver.")
banner.visible = true;
banner.show("message");
} else {
banner.visible = false;
banner.hideIf("message");
}
}
@@ -88,28 +165,106 @@ Kirigami.Page {
function onIsOnlineChanged() {
if (!root.currentRoom.connection.isOnline) {
banner.text = i18nc("@info:status", "NeoChat is offline. Please check your network connection.");
banner.visible = true;
banner.type = Kirigami.MessageType.Error;
banner.show("offline");
} else {
banner.visible = false;
banner.hideIf("offline");
}
}
}
header: Kirigami.InlineMessage {
id: banner
header: ColumnLayout {
id: headerLayout
showCloseButton: true
visible: false
position: Kirigami.InlineMessage.Position.Header
spacing: 0
readonly property bool shouldShowPins: root.currentRoom.pinnedMessage.length > 0 && !Kirigami.Settings.isMobile
QQC2.Control {
id: pinControl
visible: headerLayout.shouldShowPins
Layout.fillWidth: true
background: Rectangle {
color: Kirigami.Theme.backgroundColor
Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false
}
contentItem: RowLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.Icon {
source: "pin-symbolic"
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
}
QQC2.Label {
text: root.currentRoom.pinnedMessage
maximumLineCount: 1
elide: Text.ElideRight
onLinkActivated: link => UrlHelper.openUrl(link)
onHoveredLinkChanged: if (hoveredLink.length > 0 && hoveredLink !== "1") {
(QQC2.ApplicationWindow.window as Main).hoverLinkIndicator.text = hoveredLink;
} else {
(QQC2.ApplicationWindow.window as Main).hoverLinkIndicator.text = "";
}
Layout.fillWidth: true
}
}
TapHandler {
onTapped: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomPinnedMessagesPage'), {
room: root.currentRoom
}, {
title: i18nc("@title", "Pinned Messages")
});
}
}
Kirigami.Separator {
visible: headerLayout.shouldShowPins
Layout.fillWidth: true
}
Kirigami.InlineMessage {
id: banner
// Used to keep track of messages so we can hide the right one at the right time
property string messageId
Layout.fillWidth: true
showCloseButton: true
visible: false
position: Kirigami.InlineMessage.Position.Header
function show(msgid: string): void {
messageId = msgid;
visible = true;
}
function hideIf(msgid: string): void {
if (messageId == msgid) {
visible = false;
}
}
}
}
Loader {
id: timelineViewLoader
anchors.fill: parent
active: root.currentRoom && !root.currentRoom.isInvite && !root.currentRoom.isSpace
// We need the loader to be active but invisible while the room is loading messages so signals in TimelineView work.
visible: !root.loading
active: root.currentRoom && !root.currentRoom.isInvite && !root.currentRoom.isSpace
sourceComponent: TimelineView {
id: timelineView
messageFilterModel: root.messageFilterModel
@@ -147,21 +302,18 @@ Kirigami.Page {
}
}
background: Rectangle {
Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false
color: NeoChatConfig.compactLayout ? Kirigami.Theme.backgroundColor : "transparent"
}
footer: Loader {
id: chatBarLoader
height: active ? item.implicitHeight : 0
height: active ? (item as ChatBar)?.implicitHeight : 0
active: timelineViewLoader.active && !root.currentRoom.readOnly
sourceComponent: ChatBar {
id: chatBar
width: parent.width
currentRoom: root.currentRoom
connection: root.currentRoom.connection
connection: root.currentRoom.connection as NeoChatConnection
// Creating a reply (or doing anything in the chat bar) can change the height, but this isn't picked up on the root's onHeightChanged.
onHeightChanged: root.resetViewSettling()
}
}
@@ -203,7 +355,7 @@ Kirigami.Page {
function onShowMessage(messageType, message) {
banner.text = message;
banner.type = messageType;
banner.visible = true;
banner.show("generic");
}
function onShowEventSource(eventId) {
@@ -215,16 +367,17 @@ Kirigami.Page {
});
}
function onShowDelegateMenu(eventId: string, author, messageComponentType, plainText: string, richText: string, mimeType: string, progressInfo, isThread: bool, selectedText: string, hoveredLink: string) {
const contextMenu = delegateContextMenu.createObject(root, {
function onShowDelegateMenu(eventId: string, author, messageComponentType, plainText: string, richText: string, mimeType: string, progressInfo, selectedText: string, hoveredLink: string) {
(delegateContextMenu.createObject(root, {
author: author,
eventId: eventId,
plainText: plainText,
mimeType: mimeType,
progressInfo: progressInfo,
messageComponentType: messageComponentType,
});
contextMenu.popup();
selectedText,
hoveredLink,
}) as DelegateContextMenu).popup();
}
function onShowMaximizedMedia(index) {
@@ -239,12 +392,12 @@ Kirigami.Page {
}
function onShowMaximizedCode(author, time, codeText, language) {
let popup = Qt.createComponent('org.kde.neochat', 'CodeMaximizeComponent').createObject(QQC2.Overlay.overlay, {
(Qt.createComponent('org.kde.neochat', 'CodeMaximizeComponent').createObject(QQC2.Overlay.overlay, {
author: author,
time: time,
codeText: codeText,
language: language
}).open();
}) as CodeMaximizeComponent).open();
}
}
@@ -252,7 +405,7 @@ Kirigami.Page {
id: delegateContextMenu
DelegateContextMenu {
room: root.currentRoom
connection: root.currentRoom.connection
connection: root.currentRoom.connection as NeoChatConnection
}
}

View File

@@ -110,15 +110,15 @@ Kirigami.Dialog {
}
onClicked: {
let map = Qt.createComponent('org.kde.neochat', 'QrCodeMaximizeComponent').createObject(QQC2.Overlay.overlay, {
let qrCode = Qt.createComponent('org.kde.neochat', 'QrCodeMaximizeComponent').createObject(QQC2.Overlay.overlay, {
text: barcode.content,
title: root.room ? root.room.member(root.user.id).displayName : root.user.displayName,
subtitle: root.user.id,
avatarColor: root.room?.member(root.user.id).color,
avatarSource: root.room? root.room.member(root.user.id).avatarUrl : root.user.avatarUrl
});
}) as QrCodeMaximizeComponent;
root.close();
map.open();
qrCode.open();
}
QQC2.ToolTip.visible: hovered
@@ -152,7 +152,7 @@ Kirigami.Dialog {
}
FormCard.FormButtonDelegate {
visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("kick") && room.containsUser(root.user.id) && room.memberEffectivePowerLevel(root.user.id) < room.memberEffectivePowerLevel(root.connection.localUserId)
visible: root.room && root.user.id !== root.connection.localUserId && root.room.canSendState("kick") && root.room.containsUser(root.user.id) && root.room.memberEffectivePowerLevel(root.user.id) < root.room.memberEffectivePowerLevel(root.connection.localUserId)
text: i18nc("@action:button", "Kick this user")
icon.name: "im-kick-user"
@@ -174,7 +174,7 @@ Kirigami.Dialog {
}
FormCard.FormButtonDelegate {
visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("invite") && !room.containsUser(root.user.id)
visible: root.room && root.user.id !== root.connection.localUserId && root.room.canSendState("invite") && !root.room.containsUser(root.user.id)
enabled: root.room && !root.room.isUserBanned(root.user.id)
text: i18nc("@action:button", "Invite this user")
@@ -186,7 +186,7 @@ Kirigami.Dialog {
}
FormCard.FormButtonDelegate {
visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("ban") && !room.isUserBanned(root.user.id) && room.memberEffectivePowerLevel(root.user.id) < room.memberEffectivePowerLevel(root.connection.localUserId)
visible: root.room && root.user.id !== root.connection.localUserId && root.room.canSendState("ban") && !root.room.isUserBanned(root.user.id) && root.room.memberEffectivePowerLevel(root.user.id) < root.room.memberEffectivePowerLevel(root.connection.localUserId)
text: i18nc("@action:button", "Ban this user")
icon.name: "im-ban-user"
@@ -209,7 +209,7 @@ Kirigami.Dialog {
}
FormCard.FormButtonDelegate {
visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("ban") && room.isUserBanned(root.user.id)
visible: root.room && root.user.id !== root.connection.localUserId && root.room.canSendState("ban") && root.room.isUserBanned(root.user.id)
text: i18nc("@action:button", "Unban this user")
icon.name: "im-irc"
@@ -225,12 +225,11 @@ Kirigami.Dialog {
text: i18nc("@action:button", "Set user power level")
icon.name: "visibility"
onClicked: {
let dialog = powerLevelDialog.createObject(this, {
(powerLevelDialog.createObject(this, {
room: root.room,
userId: root.user.id,
powerLevel: root.room.memberEffectivePowerLevel(root.user.id)
});
dialog.open();
}) as PowerLevelDialog).open();
root.close();
}
@@ -243,13 +242,13 @@ Kirigami.Dialog {
}
FormCard.FormButtonDelegate {
visible: root.room && (root.user.id === root.connection.localUserId || room.canSendState("redact"))
visible: root.room && (root.user.id === root.connection.localUserId || root.room.canSendState("redact"))
text: i18nc("@action:button", "Remove recent messages by this user")
icon.name: "delete"
icon.color: Kirigami.Theme.negativeTextColor
onClicked: {
let dialog = pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
let dialog = ((QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
title: i18nc("@title:dialog", "Remove Messages"),
placeholder: i18nc("@info:placeholder", "Reason for removing this user's recent messages"),
actionText: i18nc("@action:button 'Remove' as in 'Remove these messages'", "Remove"),
@@ -279,7 +278,7 @@ Kirigami.Dialog {
text: i18nc("@action:button %1 is the name of the user.", "Search room for %1's messages", root.room ? root.room.member(root.user.id).htmlSafeDisplayName : QmlUtils.escapeString(root.user.displayName))
icon.name: "search-symbolic"
onClicked: {
pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomSearchPage'), {
((QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomSearchPage'), {
room: root.room,
senderId: root.user.id
}, {

View File

@@ -30,7 +30,7 @@ SearchPage {
*/
required property NeoChatConnection connection
title: i18nc("@action:title", "Find Your Friends")
title: i18nc("@action:title", "Find User")
Component.onCompleted: focusSearch()
@@ -53,6 +53,16 @@ SearchPage {
root.closeDialog();
}
QQC2.ContextMenu.menu: QQC2.Menu {
QQC2.MenuItem {
text: i18nc("@action:inmenu", "Copy User ID")
icon.name: "username-copy"
onTriggered: {
Clipboard.saveText(userDelegate.userId)
}
}
}
contentItem: RowLayout {
spacing: Kirigami.Units.smallSpacing
@@ -71,7 +81,7 @@ SearchPage {
}
QQC2.Label {
visible: userDelegate.directChatExists
text: i18nc("@info", "Friends")
text: i18nc("@info", "Direct Messages")
textFormat: Text.PlainText
color: Kirigami.Theme.positiveTextColor
}

View File

@@ -11,7 +11,19 @@ VerificationMessage {
required property int reason
icon: "security-low"
icon: {
switch (root.reason) {
case KeyVerificationSession.TIMEOUT:
case KeyVerificationSession.REMOTE_TIMEOUT:
case KeyVerificationSession.USER:
case KeyVerificationSession.REMOTE_USER:
case KeyVerificationSession.SESSION_ACCEPTED:
case KeyVerificationSession.REMOTE_SESSION_ACCEPTED:
return "dialog-information";
default:
return "security-low";
}
}
text: {
switch (root.reason) {
case KeyVerificationSession.NONE:

View File

@@ -13,6 +13,9 @@ ColumnLayout {
required property string icon
required property string text
required property bool isDone
signal done
anchors.fill: parent
@@ -32,6 +35,14 @@ ColumnLayout {
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
}
QQC2.Button {
text: i18nc("@action:button Done, we are finished with verification", "Done")
visible: root.isDone
onClicked: root.done()
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.alignment: Qt.AlignHCenter
}
Item {
Layout.fillHeight: true
}

View File

@@ -9,8 +9,6 @@
#include "controller.h"
#include "eventhandler.h"
#include "models/actionsmodel.h"
#include "models/messagefiltermodel.h"
#include "models/sortfilterroomtreemodel.h"
#include "neochatconfig.h"
#include "neochatconnection.h"
#include "neochatroom.h"
@@ -31,6 +29,28 @@
#include <KIO/OpenUrlJob>
#endif
/**
* @brief Stops RoomManager from updating the last room and space config.
*/
class LastRoomBlocker
{
public:
explicit LastRoomBlocker(RoomManager *manager)
: m_manager(manager)
{
Q_ASSERT(manager);
m_manager->m_dontUpdateLastRoom = true;
}
~LastRoomBlocker()
{
m_manager->m_dontUpdateLastRoom = false;
}
private:
RoomManager *m_manager;
};
RoomManager::RoomManager(QObject *parent)
: QObject(parent)
, m_config(KSharedConfig::openStateConfig())
@@ -43,6 +63,7 @@ RoomManager::RoomManager(QObject *parent)
, m_messageFilterModel(new MessageFilterModel(this, m_timelineModel))
, m_mediaMessageFilterModel(new MediaMessageFilterModel(this, m_messageFilterModel))
, m_userListModel(new UserListModel(this))
, m_widgetModel(new WidgetModel(this))
{
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(UBUNTU_TOUCH)
m_isMobile = true;
@@ -55,6 +76,7 @@ RoomManager::RoomManager(QObject *parent)
#endif
connect(this, &RoomManager::currentRoomChanged, this, [this]() {
m_widgetModel->setRoom(m_currentRoom);
m_userListModel->setRoom(m_currentRoom);
m_timelineModel->setRoom(m_currentRoom);
m_sortFilterRoomTreeModel->setCurrentRoom(m_currentRoom);
@@ -197,6 +219,11 @@ void RoomManager::activateUserModel()
m_userListModel->activate();
}
WidgetModel *RoomManager::widgetModel() const
{
return m_widgetModel;
}
void RoomManager::resolveResource(const QString &idOrUri, const QString &action)
{
resolveResource(Uri{idOrUri}, action);
@@ -209,24 +236,35 @@ void RoomManager::resolveResource(Uri uri, const QString &action)
return;
}
if (uri.type() == Uri::NonMatrix && action == "qr"_L1) {
Q_EMIT externalUrl(uri.toUrl());
return;
if (action == "qr"_L1) {
if (uri.type() == Uri::NonMatrix) {
Q_EMIT externalUrl(uri.toUrl());
return;
}
if (uri.type() != Uri::UserId) {
uri.setAction(QStringLiteral("join"));
} else {
uri.setAction(action);
}
}
// For matrix URIs:
if (uri.type() != Uri::NonMatrix) {
if (!m_connection) {
return;
}
if (!action.isEmpty() && (uri.type() != Uri::UserId || action != "join"_L1)) {
uri.setAction(action);
// Once a join is confirmed, set the action to "join" so it skips the confirmation check.
if (action == "join_confirmed"_L1) {
uri.setAction(QStringLiteral("join"));
}
// TODO we should allow the user to select a connection.
}
const auto result = visitResource(m_connection, uri);
// If we are not already in the room:
if (result == Quotient::CouldNotResolve) {
if ((uri.type() == Uri::RoomAlias || uri.type() == Uri::RoomId) && action != "no_join"_L1) {
if ((uri.type() == Uri::RoomAlias || uri.type() == Uri::RoomId) && action == "join"_L1) {
Q_EMIT askJoinRoom(uri.primaryId());
}
}
@@ -308,17 +346,6 @@ void RoomManager::loadInitialRoom()
resolveResource(m_arg);
}
if (m_isMobile) {
QString lastSpace = m_lastRoomConfig.readEntry(u"lastSpace"_s, QString());
// We can't have empty keys in KConfig, so we stored it as "Home"
if (lastSpace == u"Home"_s) {
lastSpace.clear();
}
setCurrentSpace(lastSpace, false);
// We don't want to open a room on startup on mobile
return;
}
if (m_currentRoom) {
// we opened a room with the arg parsing already
return;
@@ -331,16 +358,14 @@ void RoomManager::loadInitialRoom()
void RoomManager::openRoomForActiveConnection()
{
if (!m_connection) {
setCurrentRoom({});
setCurrentSpace({}, false);
return;
}
Q_ASSERT(m_connection);
auto lastSpace = m_lastRoomConfig.readEntry(u"lastSpace"_s, QString());
if (lastSpace == u"Home"_s) {
lastSpace.clear();
}
setCurrentSpace(lastSpace, true);
// We don't want to open a room on startup on mobile
setCurrentSpace(lastSpace, !m_isMobile);
}
UriResolveResult RoomManager::visitUser(User *user, const QString &action)
@@ -400,7 +425,7 @@ void RoomManager::joinRoom(Quotient::Connection *account, const QString &roomAli
job.get(),
&Quotient::BaseJob::finished,
this,
[this, account](Quotient::BaseJob *finish) {
[this, account, roomAliasOrId](Quotient::BaseJob *finish) {
if (finish->status() == Quotient::BaseJob::Success) {
connect(
account,
@@ -411,7 +436,7 @@ void RoomManager::joinRoom(Quotient::Connection *account, const QString &roomAli
},
Qt::SingleShotConnection);
} else {
Q_EMIT showMessage(MessageType::Warning, i18n("Failed to join room<br />%1", finish->errorString()));
Q_EMIT showMessage(MessageType::Warning, i18n("Failed to join %1:<br />%2", roomAliasOrId, finish->errorString()));
}
},
Qt::SingleShotConnection);
@@ -478,9 +503,8 @@ void RoomManager::setConnection(NeoChatConnection *connection)
m_connection = connection;
m_lastRoomConfig = m_config->group(m_connection->userId()).group(u"LastOpenRoom"_s);
if (m_connection != nullptr) {
m_lastRoomConfig = m_config->group(m_connection->userId()).group(u"LastOpenRoom"_s);
connect(m_connection, &NeoChatConnection::showMessage, this, &RoomManager::showMessage);
connect(m_connection, &NeoChatConnection::createdRoom, this, [this](Quotient::Room *room) {
resolveResource(room->id());
@@ -498,38 +522,85 @@ void RoomManager::setConnection(NeoChatConnection *connection)
Q_EMIT connectionChanged();
}
void RoomManager::setCurrentSpace(const QString &spaceId, bool setRoom)
void RoomManager::setCurrentSpace(const QString &spaceId, bool goToLastUsedRoom)
{
m_currentSpaceId = spaceId;
// This need to happen before the signal so TreeView.expandRecursively() can work nicely.
m_sortFilterRoomTreeModel->setActiveSpaceId(m_currentSpaceId);
m_sortFilterRoomTreeModel->setMode(m_currentSpaceId == u"DM"_s ? SortFilterRoomTreeModel::DirectChats : SortFilterRoomTreeModel::Rooms);
if (m_currentSpaceId == u"DM") {
m_sortFilterRoomTreeModel->setMode(SortFilterRoomTreeModel::DirectChats);
} else if (m_currentSpaceId.isEmpty()) {
m_sortFilterRoomTreeModel->setMode(SortFilterRoomTreeModel::Rooms);
} else {
m_sortFilterRoomTreeModel->setMode(SortFilterRoomTreeModel::All);
}
Q_EMIT currentSpaceChanged();
if (m_connection) {
m_lastRoomConfig.writeEntry(u"lastSpace"_s, spaceId.isEmpty() ? u"Home"_s : spaceId);
}
if (!setRoom) {
return;
}
// If we requested to change to the last opened room, do so:
if (goToLastUsedRoom) {
// We don't want to needlessly update the last room config here, that should only be done during explicit user action.
LastRoomBlocker blocker(this);
// We intentionally don't want to open the last room on mobile
if (m_isMobile) {
return;
}
// We can't have empty keys in KConfig, so it's stored as "Home":
if (const auto &lastRoom = m_lastRoomConfig.readEntry(spaceId.isEmpty() ? u"Home"_s : spaceId, QString()); !lastRoom.isEmpty()) {
resolveResource(lastRoom, "no_join"_L1);
return;
}
// We can't have empty keys in KConfig, so it's stored as "Home"
if (const auto &lastRoom = m_lastRoomConfig.readEntry(spaceId.isEmpty() ? u"Home"_s : spaceId, QString()); !lastRoom.isEmpty()) {
resolveResource(lastRoom, "no_join"_L1);
return;
// If no last room was opened, go to the space home:
if (!spaceId.isEmpty() && spaceId != u"DM"_s) {
resolveResource(spaceId, "no_join"_L1);
return;
}
// Fallback to no room opened:
setCurrentRoom({});
}
if (!spaceId.isEmpty() && spaceId != u"DM"_s) {
resolveResource(spaceId, "no_join"_L1);
return;
}
QString RoomManager::findSpaceIdForCurrentRoom() const
{
if (!m_currentRoom) {
return m_currentSpaceId;
}
setCurrentRoom({});
if (m_currentRoom->isDirectChat()) {
const auto roomsInSpace = SpaceHierarchyCache::instance().getRoomListForSpace(m_currentSpaceId, false);
if (roomsInSpace.contains(m_currentRoom->id())) {
return m_currentSpaceId;
}
return "DM"_L1;
}
const auto &parentSpaces = SpaceHierarchyCache::instance().parentSpaces(m_currentRoom->id());
if (parentSpaces.contains(m_currentSpaceId)) {
return m_currentSpaceId;
}
static auto config = NeoChatConfig::self();
if (config->allRoomsInHome()) {
return {};
}
if (const auto &parent = m_connection->room(m_currentRoom->canonicalParent())) {
for (const auto &parentParent : SpaceHierarchyCache::instance().parentSpaces(parent->id())) {
if (SpaceHierarchyCache::instance().parentSpaces(parentParent).isEmpty()) {
return parentParent;
}
}
return parent->id();
}
for (const auto &space : parentSpaces) {
if (SpaceHierarchyCache::instance().parentSpaces(space).isEmpty()) {
return space;
}
}
if (m_currentRoom->isSpace()) {
return m_currentSpaceId;
}
return {};
}
void RoomManager::setCurrentRoom(const QString &roomId)
@@ -549,56 +620,25 @@ void RoomManager::setCurrentRoom(const QString &roomId)
}
Q_EMIT currentRoomChanged();
if (m_connection) {
if (!m_dontUpdateLastRoom) {
if (roomId.isEmpty()) {
m_lastRoomConfig.deleteEntry(m_currentSpaceId);
} else {
// We can't have empty keys in KConfig, so name it "Home"
if (m_currentSpaceId.isEmpty()) {
m_lastRoomConfig.writeEntry(u"Home"_s, roomId);
} else {
m_lastRoomConfig.writeEntry(m_currentSpaceId, roomId);
}
}
}
if (roomId.isEmpty()) {
return;
}
if (m_currentRoom->isSpace()) {
return;
}
if (m_currentRoom->isDirectChat()) {
if (m_currentSpaceId != "DM"_L1) {
setCurrentSpace("DM"_L1, false);
}
return;
}
const auto &parentSpaces = SpaceHierarchyCache::instance().parentSpaces(roomId);
if (parentSpaces.contains(m_currentSpaceId)) {
return;
}
static auto config = NeoChatConfig::self();
if (config->allRoomsInHome()) {
setCurrentSpace({}, false);
return;
}
if (const auto &parent = m_connection->room(m_currentRoom->canonicalParent())) {
for (const auto &parentParent : SpaceHierarchyCache::instance().parentSpaces(parent->id())) {
if (SpaceHierarchyCache::instance().parentSpaces(parentParent).isEmpty()) {
setCurrentSpace(parentParent, false);
return;
}
}
setCurrentSpace(parent->id(), false);
return;
}
for (const auto &space : parentSpaces) {
if (SpaceHierarchyCache::instance().parentSpaces(space).isEmpty()) {
setCurrentSpace(space, false);
return;
}
const auto spaceIdForRoom = findSpaceIdForCurrentRoom();
// We can't have empty keys in KConfig, so name it "Home"
if (spaceIdForRoom.isEmpty()) {
m_lastRoomConfig.writeEntry(u"Home"_s, roomId);
} else {
m_lastRoomConfig.writeEntry(spaceIdForRoom, roomId);
}
if (m_currentSpaceId != spaceIdForRoom) {
setCurrentSpace(spaceIdForRoom, false);
}
}
setCurrentSpace({}, false);
}
void RoomManager::clearCurrentRoom()

View File

@@ -22,6 +22,7 @@
#include "models/sortfilterspacelistmodel.h"
#include "models/timelinemodel.h"
#include "models/userlistmodel.h"
#include "models/widgetmodel.h"
#include "neochatroommember.h"
class NeoChatRoom;
@@ -129,6 +130,14 @@ class RoomManager : public QObject, public UriResolverBase
*/
Q_PROPERTY(UserListModel *userListModel READ userListModel CONSTANT)
/**
* @brief The WidgetModel that should be used for room widget visualisation.
*
* @note Available here so that the room page and drawer both have access to the
* same model.
*/
Q_PROPERTY(WidgetModel *widgetModel READ widgetModel CONSTANT)
/**
* @brief Whether a room is currently open in NeoChat.
*
@@ -160,6 +169,8 @@ public:
UserListModel *userListModel() const;
Q_INVOKABLE void activateUserModel();
WidgetModel *widgetModel() const;
/**
* @brief Resolve the given resource.
*
@@ -326,6 +337,11 @@ Q_SIGNALS:
void currentSpaceChanged();
protected:
bool m_dontUpdateLastRoom = false; // Don't set directly, use LastRoomBlocker.
friend class LastRoomBlocker;
private:
bool m_isMobile = false;
@@ -356,13 +372,28 @@ private:
MediaMessageFilterModel *m_mediaMessageFilterModel;
UserListModel *m_userListModel;
WidgetModel *m_widgetModel;
QPointer<NeoChatConnection> m_connection;
void setCurrentRoom(const QString &roomId);
// Space ID, "DM", or empty string
void setCurrentSpace(const QString &spaceId, bool setRoom = true);
/**
* @brief Find the most appropriate space for the currently selected room
*
* Should be used to figure out what space to switch to after a room change.
*
* @return The Space ID that the currently set room should be displayed as part of. (or "DM" for DM and "" for Home)
*/
QString findSpaceIdForCurrentRoom() const;
/**
* @brief Sets the current space.
*
* @param spaceId The ID of the space, "DM" for direct messages or an empty string for Home.
* @param goToLastUsedRoom If true, we will navigate to the last opened room in this space.
*/
void setCurrentSpace(const QString &spaceId, bool goToLastUsedRoom = true);
/**
* @brief Resolve a user URI.

View File

@@ -8,8 +8,6 @@
#include <KWindowSystem>
#include "controller.h"
#include "models/roomlistmodel.h"
#include "models/sortfilterroomlistmodel.h"
#include "roommanager.h"
#include "windowcontroller.h"

View File

@@ -2,6 +2,8 @@
// SPDX-FileCopyrightText: 2020 Noah Davis <noahadvs@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
pragma ComponentBehavior: Bound
import QtCore
import QtQuick
import QtQuick.Controls as QQC2
@@ -87,9 +89,15 @@ QQC2.Control {
displayHint: Kirigami.DisplayHint.IconOnly
onTriggered: {
let dialog = (Clipboard.hasImage ? attachDialog : openFileDialog).createObject(root.QQC2.Overlay.overlay);
dialog.chosen.connect(path => _private.chatBarCache.attachmentPath = path);
dialog.open();
if (Clipboard.hasImage) {
let dialog = attachDialog.createObject(root.QQC2.Overlay.overlay) as AttachDialog;
dialog.chosen.connect(path => _private.chatBarCache.attachmentPath = path);
dialog.open();
} else {
let dialog = openFileDialog.createObject(root.QQC2.Overlay.overlay) as OpenFileDialog;
dialog.chosen.connect(path => _private.chatBarCache.attachmentPath = path);
dialog.open();
}
}
tooltip: text
@@ -122,9 +130,9 @@ QQC2.Control {
displayHint: QQC2.AbstractButton.IconOnly
onTriggered: {
locationChooser.createObject(QQC2.Overlay.overlay, {
(locationChooser.createObject(QQC2.Overlay.overlay, {
room: root.currentRoom
}).open();
}) as LocationChooser).open();
}
tooltip: text
},
@@ -136,9 +144,9 @@ QQC2.Control {
displayHint: QQC2.AbstractButton.IconOnly
onTriggered: {
newPollDialog.createObject(QQC2.Overlay.overlay, {
(newPollDialog.createObject(QQC2.Overlay.overlay, {
room: root.currentRoom
}).open();
}) as NewPollDialog).open();
}
tooltip: text
},
@@ -255,6 +263,7 @@ QQC2.Control {
wrapMode: TextEdit.Wrap
// This has to stay PlainText or else formatting starts breaking in strange ways
textFormat: TextEdit.PlainText
font.pointSize: Kirigami.Theme.defaultFont.pointSize * NeoChatConfig.fontScale
Accessible.description: placeholderText
@@ -367,7 +376,9 @@ QQC2.Control {
id: actionDelegate
required property BusyAction modelData
icon.name: modelData.isBusy ? "" : (modelData.icon.name.length > 0 ? modelData.icon.name : modelData.icon.source)
onClicked: modelData.trigger()
onClicked: if (!pieProgress.visible) {
modelData.trigger()
}
padding: Kirigami.Units.smallSpacing
@@ -375,7 +386,9 @@ QQC2.Control {
QQC2.ToolTip.text: modelData.tooltip
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
contentItem: PieProgressBar {
PieProgressBar {
id: pieProgress
anchors.fill: parent
visible: actionDelegate.modelData.isBusy
progress: root.currentRoom.fileUploadingProgress
}
@@ -402,7 +415,7 @@ QQC2.Control {
ReplyComponent {
id: replyComponent
replyContentModel: ContentProvider.contentModelForEvent(root.currentRoom, _private.chatBarCache.replyId, true)
Message.maxContentWidth: replyLoader.item.width
Message.maxContentWidth: (replyLoader.item as Item).width
// When the user replies to a message and the preview is loaded, make sure the text field is focused again
Component.onCompleted: textField.forceActiveFocus(Qt.OtherFocusReason)

View File

@@ -4,6 +4,7 @@
import QtQuick
import QtQuick.Controls as QQC2
import org.kde.kirigami as Kirigami
import org.kde.neochat
QQC2.ItemDelegate {
id: root
@@ -29,6 +30,7 @@ QQC2.ItemDelegate {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.family: "emoji"
font.pointSize: Kirigami.Theme.defaultFont.pointSize * NeoChatConfig.fontScale
Kirigami.Icon {
width: Kirigami.Units.gridUnit * 0.5

View File

@@ -65,7 +65,7 @@ QQC2.Popup {
padding: 2
implicitHeight: Kirigami.Units.gridUnit * 20 + 2 * padding
width: Math.min(contentItem.categoryIconSize * 11 + 2 * padding, QQC2.ApplicationWindow.window.width)
width: Math.min(contentItem.categoryIconSize * 11 + 2 * padding, QQC2.ApplicationWindow.window?.width)
contentItem: EmojiPicker {
id: emojiPicker
height: 400

View File

@@ -148,7 +148,7 @@ ColumnLayout {
id: quickReactions
Layout.fillWidth: true
model: ["👍", "👎", "😄", "🎉", "😕", "❤", "🚀", "👀"]
model: ["👍", "👎", "😄", "🎉", "😕", "❤", "🚀", "👀"]
delegate: EmojiDelegate {
required property string modelData

View File

@@ -3,14 +3,13 @@
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
import QtCore as Core
import org.kde.kirigami as Kirigami
import org.kde.kquickimageeditor as KQuickImageEditor
Kirigami.Page {
id: rootEditorView
id: root
property bool resizing: false
required property string imagePath
@@ -26,7 +25,7 @@ Kirigami.Page {
function crop() {
const ratioX = editImage.paintedWidth / editImage.nativeWidth;
const ratioY = editImage.paintedHeight / editImage.nativeHeight;
rootEditorView.resizing = false;
root.resizing = false;
imageDoc.crop(selectionTool.selectionX / ratioX, selectionTool.selectionY / ratioY, selectionTool.selectionWidth / ratioX, selectionTool.selectionHeight / ratioY);
}
@@ -43,9 +42,9 @@ Kirigami.Page {
text: i18nc("@action:button Accept image modification", "Accept")
icon.name: "dialog-ok"
onTriggered: {
let newPath = Core.StandardPaths.writableLocation(Core.StandardPaths.CacheLocation) + "/" + (new Date()).getTime() + "." + imagePath.split('.').pop();
let newPath = Core.StandardPaths.writableLocation(Core.StandardPaths.CacheLocation) + "/" + (new Date()).getTime() + "." + root.imagePath.split('.').pop();
if (imageDoc.saveAs(newPath)) {
newPathChanged(newPath);
root.newPathChanged(newPath);
} else {
msg.type = Kirigami.MessageType.Error;
msg.text = i18n("Unable to save file. Check if you have the correct permission to edit the cache directory.");
@@ -80,12 +79,12 @@ Kirigami.Page {
KQuickImageEditor.ImageDocument {
id: imageDoc
path: rootEditorView.imagePath
path: root.imagePath
}
KQuickImageEditor.SelectionTool {
id: selectionTool
visible: rootEditorView.resizing
visible: root.resizing
width: editImage.paintedWidth
height: editImage.paintedHeight
x: editImage.horizontalPadding
@@ -101,7 +100,7 @@ Kirigami.Page {
Connections {
target: selectionTool.selectionArea
function onDoubleClicked() {
rootEditorView.crop();
root.crop();
}
}
}
@@ -119,8 +118,8 @@ Kirigami.Page {
display: QQC2.Button.TextBesideIcon
actions: [
Kirigami.Action {
icon.name: rootEditorView.resizing ? "dialog-cancel" : "transform-crop"
text: rootEditorView.resizing ? i18n("Cancel") : i18nc("@action:button Crop an image", "Crop")
icon.name: root.resizing ? "dialog-cancel" : "transform-crop"
text: root.resizing ? i18n("Cancel") : i18nc("@action:button Crop an image", "Crop")
onTriggered: {
resizeRectangle.width = editImage.paintedWidth;
resizeRectangle.height = editImage.paintedHeight;
@@ -130,38 +129,38 @@ Kirigami.Page {
resizeRectangle.insideY = 100;
resizeRectangle.insideWidth = 100;
resizeRectangle.insideHeight = 100;
rootEditorView.resizing = !rootEditorView.resizing;
root.resizing = !root.resizing;
}
},
Kirigami.Action {
icon.name: "dialog-ok"
visible: rootEditorView.resizing
visible: root.resizing
text: i18nc("@action:button Crop an image", "Crop")
onTriggered: rootEditorView.crop()
onTriggered: root.crop()
},
Kirigami.Action {
icon.name: "object-rotate-left"
text: i18nc("@action:button Rotate an image to the left", "Rotate left")
onTriggered: imageDoc.rotate(-90)
visible: !rootEditorView.resizing
visible: !root.resizing
},
Kirigami.Action {
icon.name: "object-rotate-right"
text: i18nc("@action:button Rotate an image to the right", "Rotate right")
onTriggered: imageDoc.rotate(90)
visible: !rootEditorView.resizing
visible: !root.resizing
},
Kirigami.Action {
icon.name: "object-flip-vertical"
text: i18nc("@action:button Mirror an image vertically", "Flip")
onTriggered: imageDoc.mirror(false, true)
visible: !rootEditorView.resizing
visible: !root.resizing
},
Kirigami.Action {
icon.name: "object-flip-horizontal"
text: i18nc("@action:button Mirror an image horizontally", "Mirror")
onTriggered: imageDoc.mirror(true, false)
visible: !rootEditorView.resizing
visible: !root.resizing
}
]
}

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