Compare commits

...

130 Commits

Author SHA1 Message Date
l10n daemon script
9332910bcb GIT_SILENT Sync po/docbooks with svn 2025-01-06 03:17:39 +00:00
l10n daemon script
157c098af3 GIT_SILENT Sync po/docbooks with svn 2025-01-05 03:13:35 +00:00
l10n daemon script
9fe134e7f0 GIT_SILENT Sync po/docbooks with svn 2025-01-03 03:12:37 +00:00
l10n daemon script
46aaab3fb0 GIT_SILENT made messages (after extraction) 2025-01-03 02:32:10 +00:00
Heiko Becker
a5b37a78a0 GIT_SILENT Update Appstream for new release 2025-01-02 15:06:29 +01:00
Heiko Becker
59699abb94 GIT_SILENT Upgrade release service version to 24.12.1. 2025-01-02 13:56:27 +01:00
l10n daemon script
3cc0d89ee5 GIT_SILENT Sync po/docbooks with svn 2025-01-02 03:12:16 +00:00
l10n daemon script
96e83fc71b 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-01-02 03:06:21 +00:00
Carl Schwan
d89019d752 Use symbolic icon for purpose plugin
(cherry picked from commit 28c4c0b48c)

Co-authored-by: Carl Schwan <carl@carlschwan.eu>
2024-12-31 15:27:13 +00:00
l10n daemon script
51565dfdd2 GIT_SILENT Sync po/docbooks with svn 2024-12-30 03:20:50 +00:00
l10n daemon script
e1d09171d5 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-12-28 03:21:35 +00:00
l10n daemon script
f86572f880 GIT_SILENT Sync po/docbooks with svn 2024-12-27 03:13:18 +00:00
Joshua Goins
d7451834f3 Explicitly set the parent in QuickSwitcher
This sets the parent to the overlay, which makes sure it's actually
centered even when the right sidebar is opened.


(cherry picked from commit a456b10420)

Co-authored-by: Joshua Goins <josh@redstrate.com>
2024-12-25 15:29:34 +00:00
l10n daemon script
a4767cea7d GIT_SILENT Sync po/docbooks with svn 2024-12-25 03:41:51 +00:00
Joshua Goins
4c43869fd4 Port away from methods removed in libquotient. This fixes BUG: 497458
(cherry picked from commit b7dee707a3)

Co-authored-by: Jan Rathmann <jan.rathmann@gmx.de>
2024-12-25 02:01:12 +00:00
l10n daemon script
e603664521 GIT_SILENT Sync po/docbooks with svn 2024-12-24 03:09:17 +00:00
Nicolas Fella
369242ab31 [UserInfo] Fix shortcut
Set the keysequence on the action directly

This makes it actually work

(cherry picked from commit 7bef8c99ec)
2024-12-23 12:27:26 +01:00
l10n daemon script
013773d465 GIT_SILENT Sync po/docbooks with svn 2024-12-22 03:13:29 +00:00
l10n daemon script
20b17a58d3 GIT_SILENT Sync po/docbooks with svn 2024-12-20 03:18:28 +00:00
l10n daemon script
1c4bb79347 GIT_SILENT made messages (after extraction) 2024-12-19 02:30:43 +00:00
l10n daemon script
6d2b49f3eb GIT_SILENT Sync po/docbooks with svn 2024-12-16 03:58:38 +00:00
Joshua Goins
e3d5867da6 snap: use cmake snap and use . as source
- override the `PATH`
- use gcc from toolchains PPA


(cherry picked from commit e2b0a105a7)

Co-authored-by: Soumyadeep Ghosh <soumyadeepghosh2004@zohomail.in>
2024-12-15 13:43:11 +00:00
Joshua Goins
a046e3ed27 Add better support for colored text (and shrugs) from other clients
Some clients - such as Element - can send colored text through <span>,
which fails to display in Qt's rich text parser. So we need to transform
that into CSS styles which is supported by Qt.

Notably this allows you to exchange rainbow shrugs through Matrix, which
is really important. And this means colored backgrounds for text is
supported too, I guess.

(cherry picked from commit 843da2664f)
2024-12-15 07:55:46 -05:00
Joshua Goins
5b935c1d33 Fix web shortcuts not doing anything
This is because we're passing a QUrl into a QString, we need to turn it
into a string explicitly.

BUG: 496434
(cherry picked from commit 23eaa6a4c7)
2024-12-15 07:55:46 -05:00
l10n daemon script
fe6bc5a36e GIT_SILENT Sync po/docbooks with svn 2024-12-14 04:02:23 +00:00
Volker Krause
c085be4f6e Update Android Gradle plugin version to 8.6.0
Necessary for building against Android SDK 35.

(cherry picked from commit 9b0d01619c)
2024-12-13 17:15:11 +01:00
l10n daemon script
1f73a9dc90 GIT_SILENT Sync po/docbooks with svn 2024-12-13 03:10:02 +00:00
Thiago Sueto
63206ef1dd Don't set emoji size to font size
https://invent.kde.org/network/neochat/-/merge_requests/2005 changed the custom emoji height (whose default is 32 on every Matrix client) to match font height (on my machine it becomes 17, my font is 12pt).

It makes emojis unreadable on non-HiDPI resolutions (1366x768, 1920x1080), and even in the MR itself you can see how much detail is lost. This is compounded by some other rendering bug where the emoji image becomes very jagged when downscaled.

That MR however was correct in that:
* we want custom emojis to have a different size than unicode emojis
* we want custom emojis to be centered according to the text (to make better use of line spacing/paddings)
* we don't want the line height to be changed (too much) by custom emojis
* we (probably) want custom emojis to be _displayed_ proportionally to the text

I'm investigating ways to solve this issue. It seems other Matrix clients (and even chat applications like Telegram or Discord) all globally suffer from this issue and have dealt with it in different ways, sometimes masquerading it and sometimes working around it.

For now though, we shouldn't break emoji legibility for our users. Affecting line height by a few pt is a minor issue compared to being almost unable to tell what inline emoji you or your interlocutor is using. Even just the "center emoji with text" thing already makes the line height issue 1/3 less of a problem. Once we improve the emoji rendering so it's more readable, _then_ it would make sense to decrease the emoji height to something like font.height * 1.6 or so.

This does not affect unicode emojis, as far as I can tell those are handled elsewhere. This only affects inline custom emojis.

Illegible on 1366x768 with 100% scaling and font size 11:

![image](/uploads/1d074c78d63aa1f28d9f3d204a656cc7/image.png){width=1025 height=576}

![Screenshot_20241212_144737](/uploads/7ae8e080f383461dcef3320575c05b24/Screenshot_20241212_144737.png)

Legible:

![Screenshot_20241212_150257](/uploads/4f9395bd25025317005aaf1b9a1633c0/Screenshot_20241212_150257.png)

![Screenshot_20241212_150357](/uploads/a5fbb8885d601592591e99c0cc669794/Screenshot_20241212_150357.png)


(cherry picked from commit 29820e2ab2)

3cea53f5 Don't set emoji size to font size

Co-authored-by: Thiago Sueto <herzenschein@gmail.com>
2024-12-12 18:14:36 +00:00
Tobias Fella
0d286db0c2 Fix crash when sending messages
ECM recently started adding -fhardened, which makes us crash here since we're doing things that aren't valid, but happened to work out fine previously.
2024-12-11 17:16:10 +01:00
l10n daemon script
7d3f478a74 GIT_SILENT Sync po/docbooks with svn 2024-12-09 03:22:50 +00:00
l10n daemon script
6df2ebd1eb SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-12-09 03:17:34 +00:00
l10n daemon script
252fb6eb21 GIT_SILENT Sync po/docbooks with svn 2024-12-07 03:11:18 +00:00
l10n daemon script
5873092356 GIT_SILENT made messages (after extraction) 2024-12-07 02:32:10 +00:00
l10n daemon script
30822003d1 GIT_SILENT Sync po/docbooks with svn 2024-12-06 03:08:46 +00:00
l10n daemon script
52ae237eb7 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-12-06 03:05:39 +00:00
Joshua Goins
ee02abfe37 snap: Update libquotient 2024-12-04 20:04:56 +00:00
James Graham
f0de235f37 Fix removeConnection
Check m_accountsLoading and m_connectionsLoading separately for removal as when loadAccessTokenFromKeyChain() fails m_connectionsLoading won't have an entry for it


(cherry picked from commit 57e7004e05)

9aadd773 Check m_accountsLoading and m_connectionsLoading separately for removal as...

Co-authored-by: James Graham <james.h.graham@protonmail.com>
2024-12-04 17:01:38 +00:00
l10n daemon script
9e9fe6d275 GIT_SILENT Sync po/docbooks with svn 2024-12-04 03:10:16 +00:00
l10n daemon script
f4ca5f0f34 GIT_SILENT Sync po/docbooks with svn 2024-12-03 03:18:08 +00:00
l10n daemon script
5f240fa05c GIT_SILENT made messages (after extraction) 2024-12-03 02:33:48 +00:00
Heiko Becker
1e29eca59a GIT_SILENT Update Appstream for new release 2024-12-03 01:09:52 +01:00
Heiko Becker
1f71ec3bf8 GIT_SILENT Upgrade release service version to 24.12.0. 2024-12-03 00:09:15 +01:00
Carl Schwan
64c5ad88f6 Remove system information from device display name
BUG: 496901


(cherry picked from commit 9d887ba3e7)

Co-authored-by: Tobias Fella <fella@posteo.de>
2024-12-02 16:07:56 +00:00
l10n daemon script
fb5a3c1c5c GIT_SILENT Sync po/docbooks with svn 2024-12-02 04:15:51 +00:00
l10n daemon script
4a5a83f94a GIT_SILENT Sync po/docbooks with svn 2024-11-29 03:16:44 +00:00
l10n daemon script
133edc249f SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-29 03:11:59 +00:00
Albert Astals Cid
da30e66127 GIT_SILENT Upgrade release service version to 24.11.90. 2024-11-28 09:19:03 +01:00
l10n daemon script
4516e1e0f4 GIT_SILENT Sync po/docbooks with svn 2024-11-28 03:07:16 +00:00
l10n daemon script
bd80f65163 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-28 03:04:07 +00:00
l10n daemon script
f828ecf282 GIT_SILENT Sync po/docbooks with svn 2024-11-27 03:10:17 +00:00
l10n daemon script
a0483167c5 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-27 03:07:27 +00:00
l10n daemon script
87288f508c GIT_SILENT made messages (after extraction) 2024-11-27 02:32:20 +00:00
l10n daemon script
dc184ed2fd GIT_SILENT Sync po/docbooks with svn 2024-11-26 03:08:20 +00:00
l10n daemon script
49e1bf9ab1 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-26 03:05:24 +00:00
l10n daemon script
74acf3f9dc GIT_SILENT made messages (after extraction) 2024-11-24 02:34:26 +00:00
l10n daemon script
38205d2791 GIT_SILENT Sync po/docbooks with svn 2024-11-23 03:05:59 +00:00
l10n daemon script
81da926d4f SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-23 03:02:07 +00:00
Carl Schwan
1018fe5d3f Remove layout attached properties
They don't do anything

(cherry picked from commit fbb2afdb49)
2024-11-22 09:05:04 -05:00
Thiago Sueto
58b32dd50f Make height of chatbar, userinfo bar and side tab bar the same
|Current state|With this MR|
|-|-|
|![Screenshot_20241115_171736](/uploads/858a8ca21a6f4024a20f6ba32225aece/Screenshot_20241115_171736.png)|![Screenshot_20241115_171650](/uploads/115f99c7bb2b93a542c42647f9cc25c7/Screenshot_20241115_171650.png)|

(cherry picked from commit 240cf6a0ed)
2024-11-22 09:05:04 -05:00
Tobias Fella
82184b895a Escape display name in WelcomePage
(cherry picked from commit dcd9ee93de)
2024-11-22 09:05:04 -05:00
Joshua Goins
da0f6f78a4 Fix undefined access when loading stickers in chat
We need a check here, because stickers (and really, any images without a
tempSource) will try to access an undefined object.

This fixes the error:
"qrc:/qt/qml/org/kde/neochat/timeline/ImageComponent.qml:106: TypeError: Cannot read property 'source' of undefined"

(cherry picked from commit 2a8cd74ab1)
2024-11-22 09:05:03 -05:00
Joshua Goins
cfd06d064c Default to a more sensible sticker size
If we do not set the width/height for stickers (which don't have any)
then the height is okay, but the message has the maximum width which
looks odd.

Instead, let's limit all stickers to 256px and it makes them look much
nicer in chat.

(cherry picked from commit 63bc7055c2)
2024-11-22 09:05:03 -05:00
Joshua Goins
a90e9ae92a Add a comment that these are not normal quotation marks
It can be hard to tell depending on which font you're viewing the code
with.

(cherry picked from commit 1cca9733d6)
2024-11-22 09:05:03 -05:00
Joshua Goins
8ab0002057 TextHandler: Use the fancy Unicode quotation characters
As per our HIG, we should use these in quotations instead of the normal
quote characters.

(cherry picked from commit 1104da5e2c)
2024-11-22 09:05:03 -05:00
Joshua Goins
e1840be234 Limit the width of a user's QR code
This fixes the lopsided layout in the user details dialog.

(cherry picked from commit 3a9718c09d)
2024-11-22 09:05:02 -05:00
Joshua Goins
d6ecaaa344 RoomManager: Unify the resolveResource overloads
Every time I look at how resource resolving works, I always trip over
this unused overload. This behaves *different* than the other overload,
which has special cases for handling invalid Uris.

Now whether you pass in a Uri or a QString, it should behave the same.

(cherry picked from commit 55362c5573)
2024-11-22 09:05:02 -05:00
Joshua Goins
0c08c2ab89 Set the size of custom emoticons to the font height, and fix alignment
Currently custom emojis render weirdly in NeoChat. Not only are they
large, they're also in charge and like to mess up the layout of the
text.

Now that's fixed and they'll take up the same height as the surrounding
text. It's now centered in the text too.

(cherry picked from commit 0bba2299b3)
2024-11-22 09:05:02 -05:00
Joshua Goins
39ff11e059 Add icons to the recommended space actions, fix spacing of the items
(cherry picked from commit 45685af9e9)
2024-11-22 09:05:01 -05:00
Joshua Goins
93254431c5 Fix restoring the last used space on desktop
This was supposed to work, but it's done in the wrong order. We need to
set the current space first, and then select the room - otherwise
it doesn't get restored.

(cherry picked from commit 6c416a9338)
2024-11-22 09:05:01 -05:00
Joshua Goins
fc14a8eac8 Ensure it's not possible for the recommended space avatar to assert
(cherry picked from commit 1b0027e1d2)
2024-11-22 09:05:01 -05:00
Joshua Goins
50759bb3ca Fix avatars not loading in the room completion model
(cherry picked from commit 2409adf516)
2024-11-22 09:05:01 -05:00
Joshua Goins
23134d8e72 Make sure RoomInformation's source is type url
(cherry picked from commit 554801dfe4)
2024-11-22 09:05:01 -05:00
Joshua Goins
7cd095f76a Remove now unused NeoChatRoomMember::avatarMediaId()
(cherry picked from commit 20c23917e9)
2024-11-22 09:05:01 -05:00
Joshua Goins
d5c3054da4 Remove more needless usages of makeMediaUrl
This is only really needed in specific cases, e.g. localUser which isn't
attached to a connection and thus needs a little help. Notes for when
this is needed is added for future readers.

(cherry picked from commit ef953b7574)
2024-11-22 09:05:00 -05:00
Joshua Goins
ae12c838bd Change how room avatars are passed, fix friend avatars not loading
The problem lies in how media URLs work, in this case it the old
NeoChatRoom::avatarMediaId could pass a mxc url *or* a path that can
be put into root.connection.makeMediaUrl. So normal rooms with avatars
loaded, but never friends because room members gave the mxc URL.

Instead, change everything to use avatarMediaUrl which corrects this
issue by always passing a mxc URL to QML. This also removes the need to
call makeMediaUrl.

Fixes #675

(cherry picked from commit 6b79795229)
2024-11-22 09:05:00 -05:00
Joshua Goins
51727dd345 Fix ShareActionStub for Windows and Android
Apparently, we are supposed to be setting source file properties for our QML files *before*
the QML module is created. Doing it after seemed to work until Qt 6.8, where it finally
broke. Notably, this makes the Android version work again but might also affect Windows.

(cherry picked from commit a39194b2ad)

Co-authored-by: Joshua Goins <josh@redstrate.com>
2024-11-22 13:45:04 +00:00
l10n daemon script
5611b000fb GIT_SILENT Sync po/docbooks with svn 2024-11-20 03:11:39 +00:00
l10n daemon script
461896e228 GIT_SILENT Sync po/docbooks with svn 2024-11-19 03:09:14 +00:00
Carl Schwan
e388536a03 Make sure the loading text for a new login wraps
Title

BUG: 493869


(cherry picked from commit aff0402f71)

58b69cf1 Make sure the loading text for a new login wraps

Co-authored-by: James Graham <james.h.graham@protonmail.com>
2024-11-18 08:42:36 +00:00
Carl Schwan
61f22edd86 Make sure that for multiple sed edits we grab the eventID of the original message not the replacement
(cherry picked from commit 24e1a0a596)

Co-authored-by: James Graham <james.h.graham@protonmail.com>
2024-11-18 08:35:24 +00:00
l10n daemon script
9e368691d6 GIT_SILENT Sync po/docbooks with svn 2024-11-18 03:18:50 +00:00
l10n daemon script
dad2b3ec8f SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-18 03:14:09 +00:00
Joshua Goins
8821c37ff8 Don't show the file name underneath the image
This still keeps custom image descriptions, but no longer shows it for
images where it was the same as their filename.

(cherry picked from commit 437c981d30)
2024-11-16 13:54:46 -05:00
Thiago Sueto
c105170eca Make top margin consistent across Neochat settings
This standardizes on the same value used for KirigamiAddons pages like AboutKDE and About, namely largeSpacing * 4.

Now, when switching between settings pages you no longer have settings inconsistently changing heights willy nilly, header notwithstanding.

The only page that's missing is the Spellchecking page, as that needs to be fixed in Kirigami Addons' private Sonnet page.

(cherry picked from commit 396cc8e8ef)
2024-11-16 13:41:58 -05:00
Joshua Goins
b07c04eddc Change the room alias text color to disabled
It's less important than the title, and this should reduce it's visual
prominence.

(cherry picked from commit 0334cae4c8)
2024-11-16 13:30:20 -05:00
Joshua Goins
7aa0f68b10 DelegateContextMenu: Add support for separators in the mobile menu too
(cherry picked from commit a3f5962809)
2024-11-16 13:30:20 -05:00
Joshua Goins
cbdae4c312 DelegateContextMenu: Add support for separator actions
(cherry picked from commit d34f89fc4b)
2024-11-16 13:30:20 -05:00
Joshua Goins
9210940556 Hide the category list in the emoji picker when there is none
This is easy to test if you have no stickers. It should no longer have
a weird empty space above the placeholder message.

(cherry picked from commit a909ed498f)
2024-11-16 13:30:19 -05:00
Joshua Goins
d8489527b4 Improve how stickers appear in the emoji picker
First, the fill mode for the sticker images shouldn't stretch them.
Also make sure there is enough padding in the category so the image
doesn't appear larger than the button. Finally, set the source size for
the images so Qt can smooth them out better.

(cherry picked from commit 16f4e17e8f)
2024-11-16 13:30:19 -05:00
Joshua Goins
64c9cd97de Settings: Use symbolic version of the NeoChat icon
To match the rest of the icons in this sidebar, we can reuse our tray
icon.

(cherry picked from commit 0e9592a96c)
2024-11-16 13:30:19 -05:00
Joshua Goins
119a9890b1 Add placeholder icon when there's no emojis or stickers
(cherry picked from commit 704ee6a53a)
2024-11-16 13:30:19 -05:00
Joshua Goins
69be6b5939 Settings: Request symbolic versions of the icons
According to the HIG, we should be using symbolic versions of these
icons at this size. Not that we have symbolic versions for these icons
yet, but it's still safe to do as they'll fall back to the old ones.

(cherry picked from commit 5b9afbce9a)
2024-11-16 13:30:19 -05:00
Joshua Goins
112152f2df Port from deprecated AboutKDE component to AboutKDEPage
(cherry picked from commit f802dbe686)
2024-11-16 13:30:18 -05:00
Joshua Goins
2ef634a6cb Don't scroll up when clicking on the same room over and over
If you try to click on your current room in the list, it scrolls up the
messages a bit. This is because in RoomManager::visitRoom it's being
called with an empty eventId and we will happily emit a goToEvent. This
is despite there being nothing to go to.

Fixes #677.

(cherry picked from commit 2379e3d83b)
2024-11-16 13:30:18 -05:00
Joshua Goins
fd31b4fb74 Add margins to the room drawer header to match Kirigami
Otherwise it sticks to the left of the drawer and looks kinda ugly.

(cherry picked from commit 9e90ac0412)
2024-11-16 13:30:18 -05:00
Joshua Goins
3b12520fa2 Make it so the filename is filled out by default when saving files
This was never ported from the Qt labs platform FileDialog, because
currentFile doesn't exist anymore. It's now called selectedFile.

(cherry picked from commit 31ef0a5223)
2024-11-16 13:30:18 -05:00
Joshua Goins
24718a5f72 Improve the appearance of the welcome page user list
Before it only listed the user id, and nothing else. If you had multiple
accounts, it's a little difficult to tell them apart. Now the user
selection appears like how they are displayed elsewhere in NeoChat, with
the display name and avatar.

| Before | After |
| ------ | ------ |
|   ![Screenshot_20241115_221425](/uploads/3986e4c7bbb7dcdca67ee30bb529767e/Screenshot_20241115_221425.png){width=786 height=822}     |        ![Screenshot_20241115_221149](/uploads/57eb1a7e57ba5ae8c41dd922cbf39c62/Screenshot_20241115_221149.png){width=786 height=822} |

(cherry picked from commit 14c58acea1)
2024-11-16 13:30:18 -05:00
Joshua Goins
db62bacc7e Port from Kirigami Add-ons Banner to Kirigami InlineMessage
(cherry picked from commit 3f6fa94289)
2024-11-16 13:30:18 -05:00
l10n daemon script
6500669b67 GIT_SILENT Sync po/docbooks with svn 2024-11-15 03:10:56 +00:00
l10n daemon script
557d151ed4 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-15 03:06:59 +00:00
l10n daemon script
95ffd485b4 GIT_SILENT made messages (after extraction) 2024-11-15 02:31:39 +00:00
l10n daemon script
ebd38fb435 GIT_SILENT Sync po/docbooks with svn 2024-11-14 03:10:10 +00:00
l10n daemon script
a5b999e682 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-14 03:06:40 +00:00
l10n daemon script
41d34fc0e4 GIT_SILENT Sync po/docbooks with svn 2024-11-13 03:08:49 +00:00
l10n daemon script
b51194f90f SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-13 03:05:22 +00:00
l10n daemon script
80ac9e1ba7 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-12 03:11:52 +00:00
l10n daemon script
e3874c824a GIT_SILENT Sync po/docbooks with svn 2024-11-11 03:23:01 +00:00
l10n daemon script
6599c6b609 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-11 03:15:47 +00:00
l10n daemon script
13d522221c GIT_SILENT made messages (after extraction) 2024-11-11 02:40:16 +00:00
Joshua Goins
dd8f926f32 PollHandler: Make sure it's not constructible from QML
(cherry picked from commit d6b780762e)
2024-11-10 10:29:26 -05:00
Joshua Goins
258312e798 PollHandler: Ensure that m_pollStartEvent is always initialized to null
Otherwise it may be undefined, and we DO create default-constructed
PollHandler. For example, one is used as a fallback poll object
in NeoChatRoom::poll.

This is blind fix for a pretty nasty poll-related crash we saw a few
months ago.

BUG: 493649
(cherry picked from commit 5ef66b5cf6)
2024-11-10 10:29:17 -05:00
Joshua Goins
43d40c7e75 Add m.room.create state events to sync_response
In case we need to access the creation state in an appium test in the
future.

(cherry picked from commit 85ee5084b6)
2024-11-10 07:40:41 -05:00
Joshua Goins
cbcc9a6514 Hide rooms that have a defined room type
I have a room with a custom type that's only for holding data, and
doesn't need to be shown in the room list. Currently the spec is a bit
vague about what clients should do, but hiding them is probably fine
for now.

(cherry picked from commit bb9ce117de)
2024-11-10 07:40:41 -05:00
l10n daemon script
625048610b GIT_SILENT Sync po/docbooks with svn 2024-11-10 03:30:48 +00:00
l10n daemon script
fa47b67e3d SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-11-10 03:16:42 +00:00
Carl Schwan
9347a66acf RoomGeneralPage: Add missing separator
And some other minor fixes

(cherry picked from commit 00c5aa26bb)
2024-11-09 18:12:25 -05:00
Joshua Goins
317df56ffa Make closing link previews instant, as it should be
We were missing a endResetModel() call, now with it added the removal
happens instantly.

(cherry picked from commit bae4de227c)
2024-11-09 18:12:25 -05:00
Joshua Goins
fed9197716 Stop being able to crash NeoChat by pressing a button repeatedly
If you spam click the "Close link preview" button, it's possible to
crash NeoChat. This is because the index check is wrong for the array
size.

It's possible to even do this due to a bug causing the removal to be
reflected visually too slowly, that's fixed in the next commit.

(cherry picked from commit 253f891c5a)
2024-11-09 18:12:25 -05:00
Joshua Goins
1e892599e9 Improve clicking link previews
First of all, clicking on them actually works - because we were missing
an import for RoomManager. Secondly, we use a dedicated TapHandler
since onLinkActivated sucks. We want to be able to click anywhere on the
preview to go to the website/room anyway.

(cherry picked from commit 6966159062)
2024-11-09 18:12:25 -05:00
Joshua Goins
b7229ca0cf Don't set isThread on the message and file delegate context menus
It doesn't have a property called isThread, and I don't know where it
went - if it ever existed?

(cherry picked from commit 07d3b80c3e)
2024-11-09 18:12:25 -05:00
Joshua Goins
953b711823 Make fullscreen images focused when they're opened
Otherwise keyboard shortcuts don't work until you tap the image, which
makes no sense.

BUG: 484322
(cherry picked from commit a41d0f3214)
2024-11-09 18:12:25 -05:00
Joshua Goins
01d903efd3 Fix viewing any kind of data in developer tools
Fix pageStack being undefined, so we're able to view event data again.

(cherry picked from commit 1ee15de78b)
2024-11-09 18:12:25 -05:00
Carl Schwan
241dd81932 Update checkbox of PollComponent
Use FormCheckDelegate instead of a CheckBox inside a RowLayout. This
increase the click area particularly on mobile.

(cherry picked from commit b044358970)
2024-11-09 18:12:24 -05:00
Oliver Beard
f6dfe0cbcf timeline: Round separators for replies and link previews
(cherry picked from commit d2e11bb3bb)
2024-11-09 18:12:24 -05:00
Joshua Goins
f10b97139c README: Change snap store badge to the one from apps.kde.org
It seems CORS is blocking access to the badge, but we have rehosted on
apps.kde.org.

(cherry picked from commit a55bac899c)
2024-11-09 18:12:24 -05:00
Joshua Goins
385c5b3405 Update network proxy page with the improved version from Tokodon
This functions the same, but looks a bit nicer.

(cherry picked from commit c2380fb8df)
2024-11-09 16:28:47 -05:00
Joshua Goins
7bc6f906f8 Update desktop file and app description to match AppStream data
This was updated to "Chat on Matrix" but in other places it was never
switched from "Matrix client" and the like. Now it should be more
consistent.

(cherry picked from commit f31c644b13)
2024-11-09 16:28:47 -05:00
Joshua Goins
b8b1434a95 Clarify that sorting rooms by activity isn't the only thing it does
Recently, it also sorts rooms based on unread notification count and
importance. This adds a clarification to the setting so users (like me)
aren't confused why it isn't sorting only by activity.

(cherry picked from commit 26cd621d0e)
2024-11-09 16:28:47 -05:00
l10n daemon script
85c7a4bcb3 GIT_SILENT Sync po/docbooks with svn 2024-11-09 03:10:22 +00:00
Albert Astals Cid
84b698a7e8 GIT_SILENT Upgrade release service version to 24.11.80. 2024-11-08 19:06:28 +01:00
123 changed files with 10032 additions and 10142 deletions

View File

@@ -8,8 +8,8 @@ cmake_minimum_required(VERSION 3.16)
# KDE Applications version, managed by release script. # KDE Applications version, managed by release script.
set(RELEASE_SERVICE_VERSION_MAJOR "24") set(RELEASE_SERVICE_VERSION_MAJOR "24")
set(RELEASE_SERVICE_VERSION_MINOR "11") set(RELEASE_SERVICE_VERSION_MINOR "12")
set(RELEASE_SERVICE_VERSION_MICRO "70") set(RELEASE_SERVICE_VERSION_MICRO "1")
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}") set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION}) project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})

View File

@@ -11,7 +11,7 @@ A Qt/QML based Matrix client.
<a href='https://matrix.org'><img src='https://matrix.org/docs/legacy/made-for-matrix.png' alt='Made for Matrix' height=64 target=_blank /></a> <a href='https://matrix.org'><img src='https://matrix.org/docs/legacy/made-for-matrix.png' alt='Made for Matrix' height=64 target=_blank /></a>
<a href='https://flathub.org/apps/details/org.kde.neochat'><img width='190px' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-i-en.png'/></a> <a href='https://flathub.org/apps/details/org.kde.neochat'><img width='190px' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-i-en.png'/></a>
<a href='https://snapcraft.io/neochat'><img width='190px' alt='Download on the Snap Store' src='https://snapcraft.io/static/images/badges/en/snap-store-black.svg'/></a> <a href='https://snapcraft.io/neochat'><img width='190px' alt='Download on the Snap Store' src='https://apps.kde.org/store_badges/snapstore/en.svg'/></a>
## Introduction ## Introduction

View File

@@ -12,7 +12,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.4.1' classpath 'com.android.tools.build:gradle:8.6.0'
} }
} }

View File

@@ -5,6 +5,26 @@
"!room_id_1234:localhost:1234": { "!room_id_1234:localhost:1234": {
"state": { "state": {
"events": [ "events": [
{
"content": {
"m.federate": true,
"predecessor": {
"event_id": "$something:example.org",
"room_id": "!oldroom:example.org"
},
"room_version": "11"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "",
"type": "m.room.create",
"unsigned": {
"age": 1234,
"membership": "join"
}
},
{ {
"type": "m.room.member", "type": "m.room.member",
"state_key": "@user:localhost:1234", "state_key": "@user:localhost:1234",
@@ -26,6 +46,26 @@
}, },
"timeline": { "timeline": {
"events": [ "events": [
{
"content": {
"m.federate": true,
"predecessor": {
"event_id": "$something:example.org",
"room_id": "!oldroom:example.org"
},
"room_version": "11"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"sender": "@example:example.org",
"state_key": "",
"type": "m.room.create",
"unsigned": {
"age": 1234,
"membership": "join"
}
},
{ {
"type": "m.room.message", "type": "m.room.message",
"sender": "@user:localhost:1234", "sender": "@user:localhost:1234",

View File

@@ -63,6 +63,7 @@ private Q_SLOTS:
void receiveRichEdited(); void receiveRichEdited();
void receiveLineSeparator(); void receiveLineSeparator();
void receiveRichCodeUrl(); void receiveRichCodeUrl();
void receiveRichColor();
void componentOutput_data(); void componentOutput_data();
void componentOutput(); void componentOutput();
@@ -520,6 +521,25 @@ void TextHandlerTest::receiveRichCodeUrl()
QCOMPARE(testTextHandler.handleRecieveRichText(), input); QCOMPARE(testTextHandler.handleRecieveRichText(), input);
} }
void TextHandlerTest::receiveRichColor()
{
const QString testInputString = QStringLiteral(
"<span data-mx-color=\"#ff00be\">¯</span><span data-mx-color=\"#ff3b1d\">\\</span><span data-mx-color=\"#ffa600\">_</span><span "
"data-mx-color=\"#64d200\">(</span><span data-mx-color=\"#00e261\">ツ</span><span data-mx-color=\"#00e7ff\">)</span><span "
"data-mx-color=\"#00e1ff\">_</span><span data-mx-color=\"#00bdff\">/</span><span data-mx-color=\"#ff60ff\">¯</span>");
const QString testOutputString = QStringLiteral(
"<span style=\"color: #ff00be;\">¯</span><span style=\"color: #ff3b1d;\">\\</span><span style=\"color: #ffa600;\">_</span><span style=\"color: "
"#64d200;\">(</span><span style=\"color: #00e261;\">ツ</span><span style=\"color: #00e7ff;\">)</span><span style=\"color: #00e1ff;\">_</span><span "
"style=\"color: #00bdff;\">/</span><span style=\"color: #ff60ff;\">¯</span>");
TextHandler testTextHandler;
testTextHandler.setData(testInputString);
qInfo() << testTextHandler.handleRecieveRichText();
QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
}
void TextHandlerTest::componentOutput_data() void TextHandlerTest::componentOutput_data()
{ {
QTest::addColumn<QString>("testInputString"); QTest::addColumn<QString>("testInputString");
@@ -535,7 +555,7 @@ void TextHandlerTest::componentOutput_data()
QVariantMap{{QStringLiteral("class"), QStringLiteral("html")}}}}; QVariantMap{{QStringLiteral("class"), QStringLiteral("html")}}}};
QTest::newRow("quote") << QStringLiteral("<p>Text</p>\n<blockquote>\n<p>blockquote</p>\n</blockquote>") QTest::newRow("quote") << QStringLiteral("<p>Text</p>\n<blockquote>\n<p>blockquote</p>\n</blockquote>")
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, QStringLiteral("Text"), {}}, << QList<MessageComponent>{MessageComponent{MessageComponentType::Text, QStringLiteral("Text"), {}},
MessageComponent{MessageComponentType::Quote, QStringLiteral("\"blockquote\""), {}}}; MessageComponent{MessageComponentType::Quote, QStringLiteral("blockquote"), {}}};
QTest::newRow("no tag first paragraph") << QStringLiteral("Text\n<p>Text</p>") QTest::newRow("no tag first paragraph") << QStringLiteral("Text\n<p>Text</p>")
<< QList<MessageComponent>{MessageComponent{MessageComponentType::Text, QStringLiteral("Text"), {}}, << QList<MessageComponent>{MessageComponent{MessageComponentType::Text, QStringLiteral("Text"), {}},
MessageComponent{MessageComponentType::Text, QStringLiteral("Text"), {}}}; MessageComponent{MessageComponentType::Text, QStringLiteral("Text"), {}}};

View File

@@ -54,10 +54,16 @@
<summary xml:lang="ar">دردش على ماتركس</summary> <summary xml:lang="ar">دردش على ماتركس</summary>
<summary xml:lang="ca">Xat a Matrix</summary> <summary xml:lang="ca">Xat a Matrix</summary>
<summary xml:lang="ca-valencia">Xat a Matrix</summary> <summary xml:lang="ca-valencia">Xat a Matrix</summary>
<summary xml:lang="de">Über Matrix unterhalten</summary>
<summary xml:lang="en-GB">Chat on Matrix</summary> <summary xml:lang="en-GB">Chat on Matrix</summary>
<summary xml:lang="eo">Babilo en Matrix</summary>
<summary xml:lang="es">Charle en Matrix</summary> <summary xml:lang="es">Charle en Matrix</summary>
<summary xml:lang="eu">Berriketa Matrix-en</summary> <summary xml:lang="eu">Berriketa Matrix-en</summary>
<summary xml:lang="fi">Keskustelu Matrixissä</summary>
<summary xml:lang="fr">Discuter sur Matrix</summary> <summary xml:lang="fr">Discuter sur Matrix</summary>
<summary xml:lang="gl">Charlar en Matrix</summary>
<summary xml:lang="he">התכתבות דרך Matrix</summary>
<summary xml:lang="hu">Csevegés Matrixon</summary>
<summary xml:lang="ia">Conversation en ditecto sur Matrix</summary> <summary xml:lang="ia">Conversation en ditecto sur Matrix</summary>
<summary xml:lang="it">Chat su Matrix</summary> <summary xml:lang="it">Chat su Matrix</summary>
<summary xml:lang="ka">ისაუბრეთ Matrix-ზე</summary> <summary xml:lang="ka">ისაუბრეთ Matrix-ზე</summary>
@@ -65,6 +71,7 @@
<summary xml:lang="nn">Prat med via Matrix</summary> <summary xml:lang="nn">Prat med via Matrix</summary>
<summary xml:lang="pl">Rozmawiaj na Matriksie</summary> <summary xml:lang="pl">Rozmawiaj na Matriksie</summary>
<summary xml:lang="sl">Klepet na Matrixu</summary> <summary xml:lang="sl">Klepet na Matrixu</summary>
<summary xml:lang="sv">Chatta på Matrix</summary>
<summary xml:lang="ta">மேட்ரிக்ஸுக்கான உரையாடல் செயலி</summary> <summary xml:lang="ta">மேட்ரிக்ஸுக்கான உரையாடல் செயலி</summary>
<summary xml:lang="tr">Matrix Üzerinde Sohbet</summary> <summary xml:lang="tr">Matrix Üzerinde Sohbet</summary>
<summary xml:lang="uk">Спілкування у Matrix</summary> <summary xml:lang="uk">Спілкування у Matrix</summary>
@@ -112,7 +119,7 @@
<p xml:lang="eu">«NeoChat»ek «Matrix» zehaztapenaren ezaugarri guztiak eskaintzen dituen aplikazio bat izan nahi du. Beraz, egungo zehaztapen egonkorrean dagoen guztiaren euskarria du, VoIP, hariak eta muturren artean zifratzeko salbuespen nabarmenekin. Badira beste ez-betetze txikiago batzuk, «Matrix»en zehaztapena etengabe eboluzioan dagoelako, baina azken helburua zehaztapen osoaren euskarria ematea izaten jarraitzen du.</p> <p xml:lang="eu">«NeoChat»ek «Matrix» zehaztapenaren ezaugarri guztiak eskaintzen dituen aplikazio bat izan nahi du. Beraz, egungo zehaztapen egonkorrean dagoen guztiaren euskarria du, VoIP, hariak eta muturren artean zifratzeko salbuespen nabarmenekin. Badira beste ez-betetze txikiago batzuk, «Matrix»en zehaztapena etengabe eboluzioan dagoelako, baina azken helburua zehaztapen osoaren euskarria ematea izaten jarraitzen du.</p>
<p xml:lang="fi">NeoChat pyrkii olemaan Matrix-määritelmän täysominaisuuksinen sovellus, joten se tukee kaikkea nykyisessä vakaassa määritelmässä muutamaa huomattavaa poikkeusta lukuun ottamatta (VoIP, säikeet ja jotkin piirteet päästä päähän -salauksessa). Joitakin pienempiäkin puutteita on Matrix-määritelmän jatkuvan kehityksen vuoksi, mutta lopputavoitteena on tarjota määritelmän täysi tuki.</p> <p xml:lang="fi">NeoChat pyrkii olemaan Matrix-määritelmän täysominaisuuksinen sovellus, joten se tukee kaikkea nykyisessä vakaassa määritelmässä muutamaa huomattavaa poikkeusta lukuun ottamatta (VoIP, säikeet ja jotkin piirteet päästä päähän -salauksessa). Joitakin pienempiäkin puutteita on Matrix-määritelmän jatkuvan kehityksen vuoksi, mutta lopputavoitteena on tarjota määritelmän täysi tuki.</p>
<p xml:lang="fr">L'objectif de NeoChat est d'être une application complète pour le protocole Matrix. En tant que tel, tout dans la spécification stable actuelle avec les exceptions notables de VoIP, les processus et certains aspects du chiffrement de bout en bout sont pris en charge. Il y a quelques autres petites omissions en raison du fait que la spécification du protocole Matrix est en constante évolution. Cependant, l'objectif reste de fournir un soutien éventuel pour l'ensemble de la spécification.</p> <p xml:lang="fr">L'objectif de NeoChat est d'être une application complète pour le protocole Matrix. En tant que tel, tout dans la spécification stable actuelle avec les exceptions notables de VoIP, les processus et certains aspects du chiffrement de bout en bout sont pris en charge. Il y a quelques autres petites omissions en raison du fait que la spécification du protocole Matrix est en constante évolution. Cependant, l'objectif reste de fournir un soutien éventuel pour l'ensemble de la spécification.</p>
<p xml:lang="gl">NeoChat pretende ser unha aplicación completa para a especificación de Matrix. Coas excepcións de VoIP, conversas fiadas e algúns aspectos da cifraxe de extremo a extremo, a versión estábel segue as especificacións. Existen algunhas outras pequenas omisións debido ao feito de que Matrix está en continua evolución pero a intención é implementar a especificación completa.</p> <p xml:lang="gl">NeoChat pretende ser unha aplicación completa para a especificación de Matrix. Coas excepcións de VoIP, conversas fiadas e algúns aspectos da cifraxe de extremo a extremo, a versión estábel segue as especificacións. Existen algunhas outras pequenas omisións debido ao feito de que Matrix está en continua evolución pero a intención é fornecer compatibilidade coa especificación completa.</p>
<p xml:lang="he">NeoChat מתיימר להיות יישום עתיר יכולות לפי מפרט Matrix. כיוון שזה ייעודו, כל מה שבמפרט היציב עם חריגות משמעותיות כגון VoIP, שרשורים ועוד מגוון היבטים של הצפנה מקצה לקצה נתמכים גם הם. יש מספר השמטות קטן עקב העובדה שהמפרט של Matrix ממשיך להתפתח אך המטרה היא להמשיך לספק תמיכה בסופו של דבר לכל המפרט.</p> <p xml:lang="he">NeoChat מתיימר להיות יישום עתיר יכולות לפי מפרט Matrix. כיוון שזה ייעודו, כל מה שבמפרט היציב עם חריגות משמעותיות כגון VoIP, שרשורים ועוד מגוון היבטים של הצפנה מקצה לקצה נתמכים גם הם. יש מספר השמטות קטן עקב העובדה שהמפרט של Matrix ממשיך להתפתח אך המטרה היא להמשיך לספק תמיכה בסופו של דבר לכל המפרט.</p>
<p xml:lang="hu">A NeoChat célja, hogy a Matrix specifikációnak megfelelő teljes funkcionalitású alkalmazás legyen. Mint ilyen, a jelenlegi stabil specifikáció támogatott a VoIP, a szálak és a végpontok közötti titkosítás egyes elemeinek kivételével. Van még néhány kisebb hiányosság annak köszönhetően, hogy a Matrix specifikáció folyamatosan fejlődik, de végső cél a teljes specifikáció megvalósítása.</p> <p xml:lang="hu">A NeoChat célja, hogy a Matrix specifikációnak megfelelő teljes funkcionalitású alkalmazás legyen. Mint ilyen, a jelenlegi stabil specifikáció támogatott a VoIP, a szálak és a végpontok közötti titkosítás egyes elemeinek kivételével. Van még néhány kisebb hiányosság annak köszönhetően, hogy a Matrix specifikáció folyamatosan fejlődik, de végső cél a teljes specifikáció megvalósítása.</p>
<p xml:lang="ia">NeoChat aspira a esser un application plenmente eminente per le specification de Matrix. Tal como omne cosas in le specification currentemente stabile con le exceptiones notabile de VOIP, threads e alcun aspectos del cryptation End-to-End es supportate. Il ha ltere pauc omissiones, debite al facto que le specification de Matrix es in evolution constante ma le aspiration remane a fornir supporto eventual per le integre specification.</p> <p xml:lang="ia">NeoChat aspira a esser un application plenmente eminente per le specification de Matrix. Tal como omne cosas in le specification currentemente stabile con le exceptiones notabile de VOIP, threads e alcun aspectos del cryptation End-to-End es supportate. Il ha ltere pauc omissiones, debite al facto que le specification de Matrix es in evolution constante ma le aspiration remane a fornir supporto eventual per le integre specification.</p>
@@ -440,6 +447,8 @@
<content_attribute id="social-chat">intense</content_attribute> <content_attribute id="social-chat">intense</content_attribute>
</content_rating> </content_rating>
<releases> <releases>
<release version="24.12.1" date="2025-01-09"/>
<release version="24.12.0" date="2024-12-12"/>
<release version="24.08.3" date="2024-11-07"/> <release version="24.08.3" date="2024-11-07"/>
<release version="24.08.2" date="2024-10-10"/> <release version="24.08.2" date="2024-10-10"/>
<release version="24.08.1" date="2024-09-12"/> <release version="24.08.1" date="2024-09-12"/>

View File

@@ -87,47 +87,30 @@ GenericName[uk]=Клієнт Matrix
GenericName[x-test]=xxMatrix Clientxx GenericName[x-test]=xxMatrix Clientxx
GenericName[zh_CN]=Matrix 客户端 GenericName[zh_CN]=Matrix 客户端
GenericName[zh_TW]=Matrix 用戶端 GenericName[zh_TW]=Matrix 用戶端
Comment=Client for the Matrix protocol Comment=Chat on Matrix
Comment[ar]=عميل لميفاق ماتركس Comment[ar]=دردش على ماتركس
Comment[az]=Matrix protokolu üçün müştəri Comment[ca]=Xat a Matrix
Comment[ca]=Client per al protocol Matrix Comment[ca@valencia]=Xat a Matrix
Comment[ca@valencia]=Client per al protocol Matrix Comment[de]=Über Matrix unterhalten
Comment[de]=Programm für das Matrix-Protokoll Comment[en_GB]=Chat on Matrix
Comment[el]=Πελάτης για το πρωτόκολλο Matrix Comment[eo]=Babilo en Matrix
Comment[en_GB]=Client for the Matrix protocol Comment[es]=Chat en Matrix
Comment[eo]=Kliento por la Matrix-protokolo Comment[eu]=Berriketa Matrix-en
Comment[es]=Cliente para el protocolo Matrix Comment[fi]=Keskustele Matrixissä
Comment[eu]=Matrix protokolorako bezeroa Comment[fr]=Clavarder sur Matrix
Comment[fi]=Asiakas Matrix-yhteyskäytännölle Comment[gl]=Charle en Matrix
Comment[fr]=Client pour le protocole « Matrix » Comment[he]=התכתבות דרך Matrix
Comment[gl]=Cliente para o protocolo Matrix. Comment[hu]=Csevegés Matrixon
Comment[he]=לקוח לפרוטוקול Matrix Comment[ia]=Conversation en ditecto sur Matrix
Comment[hu]=Kliens a Matrix protokollhoz Comment[it]= su Matrix
Comment[ia]=Cliente per le protocollo de Matrix Comment[ka]=საუბარი Matrix-ზე
Comment[id]=Klien untuk protokol Matrix Comment[pl]=Rozmawiaj na Matriksie
Comment[ie]=Un cliente del protocol Matrix Comment[sl]=Klepet na Matrixu
Comment[it]=Client per il protocollo Matrix Comment[sv]=Chatta på Matrix
Comment[ka]=კლიენტი Matrix-ის პროტოკოლისთვის Comment[ta]=மேட்ரிக்ஸில் உரையாட உதவும்
Comment[ko]=Matrix 프로토콜용 클라이언트 Comment[tr]=Matrix üzerinde sohbet edin
Comment[lt]=Matrix protokolo kliento programa Comment[uk]=Спілкування у Matrix
Comment[lv]=Klients „Matrix“ protokolam Comment[zh_TW]=在 Matrix 上聊天
Comment[nl]=Client voor het Matrix-protocol
Comment[nn]=Klient for Matrix-protokollen
Comment[pa]=ਮੈਟਰਿਕਸ ਪਰੋਟੋਕਾਲ ਲਈ ਕਲਾਈਂਟ ਹੈ
Comment[pl]=Program obsługi protokołu Matriksa
Comment[pt]=Cliente para o protocolo Matrix
Comment[pt_BR]=Cliente para o protocolo Matrix
Comment[ro]=Client pentru protocolul Matrix
Comment[ru]=Клиент для протокола Matrix
Comment[sk]=Klient protokolu Matrix
Comment[sl]=Odjemalec za protokol Matrix
Comment[sv]=Klient för protokollet Matrix
Comment[ta]=Matrix நெறிமுறைக்கான வாங்கி
Comment[tr]=Matrix protokolü için istemci
Comment[uk]=Клієнт протоколу Matrix
Comment[x-test]=xxClient for the Matrix protocolxx
Comment[zh_CN]=为 Matrix 协议打造的客户端
Comment[zh_TW]=Matrix 通訊協定的用戶端
MimeType=x-scheme-handler/matrix; MimeType=x-scheme-handler/matrix;
Exec=neochat %u Exec=neochat %u
Terminal=false Terminal=false

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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

@@ -27,6 +27,10 @@ apps:
compression: lzo compression: lzo
package-repositories:
- type: apt
ppa: ubuntu-toolchain-r/test
slots: slots:
session-dbus-interface: session-dbus-interface:
interface: dbus interface: dbus
@@ -62,7 +66,7 @@ parts:
- -Dcrypto=disabled - -Dcrypto=disabled
- -Dgtk_doc=false - -Dgtk_doc=false
build-packages: build-packages:
- meson - meson
- libglib2.0-dev - libglib2.0-dev
- libgcrypt20-dev - libgcrypt20-dev
prime: prime:
@@ -76,6 +80,7 @@ parts:
source-depth: 1 source-depth: 1
plugin: cmake plugin: cmake
build-environment: build-environment:
- PATH: /snap/bin:${PATH}
- PKG_CONFIG_PATH: $CRAFT_STAGE/usr/lib/$CRAFT_ARCH_TRIPLET/pkgconfig:$PKG_CONFIG_PATH - PKG_CONFIG_PATH: $CRAFT_STAGE/usr/lib/$CRAFT_ARCH_TRIPLET/pkgconfig:$PKG_CONFIG_PATH
cmake-parameters: cmake-parameters:
- -DCMAKE_INSTALL_PREFIX=/usr - -DCMAKE_INSTALL_PREFIX=/usr
@@ -92,10 +97,16 @@ parts:
- olm - olm
- qtkeychain - qtkeychain
source: https://github.com/quotient-im/libQuotient.git source: https://github.com/quotient-im/libQuotient.git
source-tag: 0.9.0 source-tag: 0.9.1
source-depth: 1 source-depth: 1
plugin: cmake plugin: cmake
build-environment:
- PATH: /snap/bin:${PATH}
build-snaps:
- cmake
build-packages: build-packages:
- gcc-13
- g++-13
- libssl-dev - libssl-dev
cmake-parameters: cmake-parameters:
- -DCMAKE_INSTALL_PREFIX=/usr - -DCMAKE_INSTALL_PREFIX=/usr
@@ -103,6 +114,9 @@ parts:
- -DBUILD_TESTING=OFF - -DBUILD_TESTING=OFF
- -DQuotient_ENABLE_E2EE=ON - -DQuotient_ENABLE_E2EE=ON
- -DBUILD_WITH_QT6=ON - -DBUILD_WITH_QT6=ON
override-build: |
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 100 --slave /usr/bin/g++ g++ /usr/bin/g++-13 --slave /usr/bin/gcov gcov /usr/bin/gcov-13
craftctl default
prime: prime:
- -usr/include - -usr/include
- -usr/lib/*/pkgconfig - -usr/lib/*/pkgconfig
@@ -113,6 +127,8 @@ parts:
source-tag: 'v0.3.0' source-tag: 'v0.3.0'
source-depth: 1 source-depth: 1
plugin: cmake plugin: cmake
build-environment:
- PATH: /snap/bin:${PATH}
cmake-parameters: cmake-parameters:
- -DCMAKE_INSTALL_PREFIX=/usr - -DCMAKE_INSTALL_PREFIX=/usr
- -DCMAKE_BUILD_TYPE=Release - -DCMAKE_BUILD_TYPE=Release
@@ -130,9 +146,10 @@ parts:
- kquickimageeditor - kquickimageeditor
parse-info: parse-info:
- usr/share/metainfo/org.kde.neochat.appdata.xml - usr/share/metainfo/org.kde.neochat.appdata.xml
source: https://invent.kde.org/network/neochat.git source: .
source-tag: 'v24.08.1'
plugin: cmake plugin: cmake
build-environment:
- PATH: /snap/bin:${PATH}
build-packages: build-packages:
- cmark - cmark
- libcmark-dev - libcmark-dev

View File

@@ -200,6 +200,12 @@ set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
QT_QML_SINGLETON_TYPE TRUE QT_QML_SINGLETON_TYPE TRUE
) )
if(ANDROID OR WIN32)
set_source_files_properties(qml/ShareActionStub.qml PROPERTIES
QT_QML_SOURCE_TYPENAME ShareAction
)
endif()
ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/org/kde/neochat OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/org/kde/neochat
QML_FILES QML_FILES
@@ -311,13 +317,9 @@ if(NOT ANDROID AND NOT WIN32)
qml/EditMenu.qml qml/EditMenu.qml
) )
else() else()
set_source_files_properties(qml/ShareActionStub.qml PROPERTIES
QT_RESOURCE_ALIAS qml/ShareAction.qml
)
qt_target_qml_sources(neochat QML_FILES qml/ShareActionStub.qml) qt_target_qml_sources(neochat QML_FILES qml/ShareActionStub.qml)
endif() endif()
configure_file(config-neochat.h.in ${CMAKE_CURRENT_BINARY_DIR}/config-neochat.h) configure_file(config-neochat.h.in ${CMAKE_CURRENT_BINARY_DIR}/config-neochat.h)
if(WIN32) if(WIN32)

View File

@@ -176,13 +176,14 @@ QQC2.Control {
RowLayout { RowLayout {
QQC2.ScrollView { QQC2.ScrollView {
id: chatBarScrollView id: chatBarScrollView
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.bottomMargin: Kirigami.Units.smallSpacing
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumHeight: Kirigami.Units.gridUnit * 8 Layout.maximumHeight: Kirigami.Units.gridUnit * 8
Layout.minimumHeight: Kirigami.Units.gridUnit * 3
Layout.topMargin: Kirigami.Units.smallSpacing
Layout.bottomMargin: Kirigami.Units.smallSpacing
Layout.minimumHeight: Kirigami.Units.gridUnit * 2
// HACK: This is to stop the ScrollBar flickering on and off as the height is increased // HACK: This is to stop the ScrollBar flickering on and off as the height is increased
QQC2.ScrollBar.vertical.policy: chatBarHeightAnimation.running && implicitHeight <= height ? QQC2.ScrollBar.AlwaysOff : QQC2.ScrollBar.AsNeeded QQC2.ScrollBar.vertical.policy: chatBarHeightAnimation.running && implicitHeight <= height ? QQC2.ScrollBar.AlwaysOff : QQC2.ScrollBar.AsNeeded
@@ -320,12 +321,11 @@ QQC2.Control {
id: actionsRow id: actionsRow
spacing: 0 spacing: 0
Layout.alignment: Qt.AlignBottom Layout.alignment: Qt.AlignBottom
Layout.bottomMargin: Kirigami.Units.smallSpacing * 1.5 Layout.bottomMargin: Kirigami.Units.smallSpacing * 4
Repeater { Repeater {
model: root.actions model: root.actions
delegate: QQC2.ToolButton { delegate: QQC2.ToolButton {
Layout.alignment: Qt.AlignVCenter
icon.name: modelData.isBusy ? "" : (modelData.icon.name.length > 0 ? modelData.icon.name : modelData.icon.source) icon.name: modelData.isBusy ? "" : (modelData.icon.name.length > 0 ? modelData.icon.name : modelData.icon.source)
onClicked: modelData.trigger() onClicked: modelData.trigger()
@@ -342,7 +342,6 @@ QQC2.Control {
} }
} }
} }
DelegateSizeHelper { DelegateSizeHelper {
id: chatBarSizeHelper id: chatBarSizeHelper
startBreakpoint: Kirigami.Units.gridUnit * 46 startBreakpoint: Kirigami.Units.gridUnit * 46

View File

@@ -43,6 +43,9 @@ QQC2.ItemDelegate {
anchors.fill: parent anchors.fill: parent
visible: root.emoji.startsWith("mxc") || root.isImage visible: root.emoji.startsWith("mxc") || root.isImage
source: visible ? root.emoji : "" source: visible ? root.emoji : ""
fillMode: Image.PreserveAspectFit
sourceSize.width: width
sourceSize.height: height
} }
} }

View File

@@ -84,6 +84,7 @@ QQC2.ScrollView {
Kirigami.PlaceholderMessage { Kirigami.PlaceholderMessage {
anchors.centerIn: parent anchors.centerIn: parent
icon.name: root.stickers ? "stickers" : "preferences-desktop-emoticons"
text: root.stickers ? i18n("No stickers") : i18n("No emojis") text: root.stickers ? i18n("No stickers") : i18n("No emojis")
visible: emojis.count === 0 visible: emojis.count === 0
} }

View File

@@ -66,6 +66,7 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: root.categoryIconSize + QQC2.ScrollBar.horizontal.height Layout.preferredHeight: root.categoryIconSize + QQC2.ScrollBar.horizontal.height
QQC2.ScrollBar.horizontal.height: QQC2.ScrollBar.horizontal.visible ? QQC2.ScrollBar.horizontal.implicitHeight : 0 QQC2.ScrollBar.horizontal.height: QQC2.ScrollBar.horizontal.visible ? QQC2.ScrollBar.horizontal.implicitHeight : 0
visible: categories.count !== 0
ListView { ListView {
id: categories id: categories
@@ -201,8 +202,13 @@ ColumnLayout {
width: root.categoryIconSize width: root.categoryIconSize
height: width height: width
checked: stickerModel.packIndex === model.index checked: stickerModel.packIndex === model.index
padding: Kirigami.Units.largeSpacing
contentItem: Image { contentItem: Image {
source: model.avatarUrl source: model.avatarUrl
fillMode: Image.PreserveAspectFit
sourceSize.width: width
sourceSize.height: height
} }
QQC2.ToolTip.text: model.name QQC2.ToolTip.text: model.name
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay

View File

@@ -319,7 +319,8 @@ void ChatBarCache::postMessage()
return; return;
} }
room->postMessage(text(), sendText, *std::get<std::optional<Quotient::RoomMessageEvent::MsgType>>(result), replyId(), editId(), threadId()); auto type = std::get<std::optional<Quotient::RoomMessageEvent::MsgType>>(result);
room->postMessage(text(), sendText, type ? *type : Quotient::RoomMessageEvent::MsgType::Text, replyId(), editId(), threadId());
clearCache(); clearCache();
} }

View File

@@ -423,10 +423,14 @@ void Controller::setTestMode(bool test)
void Controller::removeConnection(const QString &userId) void Controller::removeConnection(const QString &userId)
{ {
if (m_connectionsLoading.contains(userId) && m_connectionsLoading[userId]) { // When loadAccessTokenFromKeyChain() fails m_connectionsLoading won't have an
auto connection = m_connectionsLoading[userId]; // entry for it so we need to check both separately.
if (m_accountsLoading.contains(userId)) {
m_accountsLoading.removeAll(userId); m_accountsLoading.removeAll(userId);
Q_EMIT accountsLoadingChanged(); Q_EMIT accountsLoadingChanged();
}
if (m_connectionsLoading.contains(userId) && m_connectionsLoading[userId]) {
auto connection = m_connectionsLoading[userId];
SettingsGroup("Accounts"_ls).remove(userId); SettingsGroup("Accounts"_ls).remove(userId);
} }
} }

View File

@@ -4,6 +4,7 @@
import QtQuick import QtQuick
import QtQuick.Controls as QQC2 import QtQuick.Controls as QQC2
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard import org.kde.kirigamiaddons.formcard as FormCard
@@ -23,7 +24,7 @@ ColumnLayout {
model: root.connection.accountDataEventTypes model: root.connection.accountDataEventTypes
delegate: FormCard.FormButtonDelegate { delegate: FormCard.FormButtonDelegate {
text: modelData text: modelData
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), { onClicked: root.Window.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
sourceText: root.connection.accountDataJsonString(modelData) sourceText: root.connection.accountDataJsonString(modelData)
}, { }, {
title: i18nc("@title:window", "Event Source"), title: i18nc("@title:window", "Event Source"),

View File

@@ -3,6 +3,7 @@
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard import org.kde.kirigamiaddons.formcard as FormCard
@@ -47,7 +48,7 @@ ColumnLayout {
model: root.room.accountDataEventTypes model: root.room.accountDataEventTypes
delegate: FormCard.FormButtonDelegate { delegate: FormCard.FormButtonDelegate {
text: modelData text: modelData
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), { onClicked: root.Window.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
sourceText: root.room.roomAcountDataJson(text) sourceText: root.room.roomAcountDataJson(text)
}, { }, {
title: i18n("Event Source"), title: i18n("Event Source"),
@@ -77,7 +78,7 @@ ColumnLayout {
if (model.eventCount === 1) { if (model.eventCount === 1) {
openEventSource(model.type, model.stateKey); openEventSource(model.type, model.stateKey);
} else { } else {
pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.devtools', 'StateKeys'), { root.Window.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat.devtools', 'StateKeys'), {
room: root.room, room: root.room,
eventType: model.type eventType: model.type
}, { }, {
@@ -89,7 +90,7 @@ ColumnLayout {
} }
} }
function openEventSource(type: string, stateKey: string): void { function openEventSource(type: string, stateKey: string): void {
onClicked: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), { onClicked: root.Window.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'MessageSourceSheet'), {
model: stateModel, model: stateModel,
allowEdit: true, allowEdit: true,
room: root.room, room: root.room,

View File

@@ -25,8 +25,7 @@ void LoginHelper::init()
m_connection = new NeoChatConnection(); m_connection = new NeoChatConnection();
m_matrixId = QString(); m_matrixId = QString();
m_password = QString(); m_password = QString();
m_deviceName = QStringLiteral("NeoChat %1 %2 %3 %4") m_deviceName = QStringLiteral("NeoChat");
.arg(QSysInfo::machineHostName(), QSysInfo::productType(), QSysInfo::productVersion(), QSysInfo::currentCpuArchitecture());
m_supportsSso = false; m_supportsSso = false;
m_supportsPassword = false; m_supportsPassword = false;
m_ssoUrl = QUrl(); m_ssoUrl = QUrl();

View File

@@ -13,6 +13,7 @@ LoginStep {
id: root id: root
FormCard.FormTextDelegate { FormCard.FormTextDelegate {
textItem.wrapMode: Text.Wrap
text: i18n("Please wait while your messages are loaded from the server. This might take a little while.") text: i18n("Please wait while your messages are loaded from the server. This might take a little while.")
} }
FormCard.AbstractFormDelegate { FormCard.AbstractFormDelegate {

View File

@@ -7,6 +7,7 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.kirigamiaddons.labs.components as KirigamiComponents
import org.kde.neochat import org.kde.neochat
import org.kde.neochat.settings import org.kde.neochat.settings
@@ -90,11 +91,27 @@ Kirigami.Page {
id: loadedAccounts id: loadedAccounts
model: AccountRegistry model: AccountRegistry
delegate: FormCard.FormButtonDelegate { delegate: FormCard.FormButtonDelegate {
text: model.userId id: delegate
required property string userId
required property NeoChatConnection connection
text: QmlUtils.escapeString(connection.localUser.displayName)
description: connection.localUser.id
leadingPadding: Kirigami.Units.largeSpacing
onClicked: { onClicked: {
Controller.activeConnection = model.connection; Controller.activeConnection = delegate.connection;
root.connectionChosen(); root.connectionChosen();
} }
leading: KirigamiComponents.Avatar {
id: avatar
name: delegate.text
// Note: User::avatarUrl does not set user_id, and thus cannot be used directly here. Hence the makeMediaUrl.
source: delegate.connection.localUser.avatarUrl.toString().length > 0 ? delegate.connection.makeMediaUrl(delegate.connection.localUser.avatarUrl) : ""
implicitWidth: Kirigami.Units.iconSizes.medium
implicitHeight: Kirigami.Units.iconSizes.medium
}
} }
} }
Repeater { Repeater {

View File

@@ -140,7 +140,7 @@ int main(int argc, char *argv[])
KAboutData about(QStringLiteral("neochat"), KAboutData about(QStringLiteral("neochat"),
i18n("NeoChat"), i18n("NeoChat"),
QStringLiteral(NEOCHAT_VERSION_STRING), QStringLiteral(NEOCHAT_VERSION_STRING),
i18n("Matrix client"), i18n("Chat on Matrix"),
KAboutLicense::GPL_V3, KAboutLicense::GPL_V3,
i18n("© 2018-2020 Black Hat, 2020-2024 KDE Community")); i18n("© 2018-2020 Black Hat, 2020-2024 KDE Community"));
about.addAuthor(i18n("Carl Schwan"), about.addAuthor(i18n("Carl Schwan"),

View File

@@ -600,14 +600,19 @@ bool ActionsModel::handleQuickEditAction(NeoChatRoom *room, const QString &messa
} else { } else {
originalString = event->plainBody(); originalString = event->plainBody();
} }
QString replaceId = event->id();
const auto eventRelation = event->relatesTo();
if (eventRelation && eventRelation->type == "m.replace"_L1) {
replaceId = eventRelation->eventId;
}
if (flags == "/g"_L1) { if (flags == "/g"_L1) {
room->postHtmlMessage(messageText, originalString.replace(regex, replacement), event->msgtype(), {}, event->id()); room->postHtmlMessage(messageText, originalString.replace(regex, replacement), event->msgtype(), {}, replaceId);
} else { } else {
room->postHtmlMessage(messageText, room->postHtmlMessage(messageText,
originalString.replace(originalString.indexOf(regex), regex.size(), replacement), originalString.replace(originalString.indexOf(regex), regex.size(), replacement),
event->msgtype(), event->msgtype(),
{}, {},
event->id()); replaceId);
} }
return true; return true;
} }

View File

@@ -85,13 +85,7 @@ QVariant CompletionModel::data(const QModelIndex &index, int role) const
return m_filterModel->data(filterIndex, RoomListModel::CanonicalAliasRole); return m_filterModel->data(filterIndex, RoomListModel::CanonicalAliasRole);
} }
if (role == IconNameRole) { if (role == IconNameRole) {
auto mediaId = m_filterModel->data(filterIndex, RoomListModel::AvatarRole).toString(); return m_filterModel->data(filterIndex, RoomListModel::AvatarRole).toString();
if (mediaId.isEmpty()) {
return QVariant();
}
if (m_room) {
return m_room->connection()->makeMediaUrl(QUrl(QStringLiteral("mxc://%1").arg(mediaId)));
}
} }
} }
if (m_autoCompletionType == Emoji) { if (m_autoCompletionType == Emoji) {

View File

@@ -569,15 +569,22 @@ QList<MessageComponent> MessageContentModel::componentsForType(MessageComponentT
case MessageComponentType::Video: { case MessageComponentType::Video: {
if (!event->is<StickerEvent>()) { if (!event->is<StickerEvent>()) {
const auto roomMessageEvent = eventCast<const Quotient::RoomMessageEvent>(event); const auto roomMessageEvent = eventCast<const Quotient::RoomMessageEvent>(event);
QList<MessageComponent> components; const auto fileContent = roomMessageEvent->get<EventContent::FileContentBase>();
components += MessageComponent{type, QString(), {}}; if (fileContent != nullptr) {
auto body = EventHandler::rawMessageBody(*roomMessageEvent); const auto fileInfo = fileContent->commonInfo();
components += TextHandler().textComponents(body, const auto body = EventHandler::rawMessageBody(*roomMessageEvent);
EventHandler::messageBodyInputFormat(*roomMessageEvent), // Do not attach the description to the image, if it's the same as the original filename.
m_room, if (fileInfo.originalName != body) {
roomMessageEvent, QList<MessageComponent> components;
roomMessageEvent->isReplaced()); components += MessageComponent{type, QString(), {}};
return components; components += TextHandler().textComponents(body,
EventHandler::messageBodyInputFormat(*roomMessageEvent),
m_room,
roomMessageEvent,
roomMessageEvent->isReplaced());
return components;
}
}
} }
} }
default: default:
@@ -635,7 +642,7 @@ QList<MessageComponent> MessageContentModel::addLinkPreviews(QList<MessageCompon
void MessageContentModel::closeLinkPreview(int row) void MessageContentModel::closeLinkPreview(int row)
{ {
if (row < 0 || row > m_components.size()) { if (row < 0 || row >= m_components.size()) {
qWarning() << "closeLinkPreview() called with row" << row << "which does not exist. m_components.size() =" << m_components.size(); qWarning() << "closeLinkPreview() called with row" << row << "which does not exist. m_components.size() =" << m_components.size();
return; return;
} }
@@ -645,6 +652,7 @@ void MessageContentModel::closeLinkPreview(int row)
m_removedLinkPreviews += m_components[row].attributes["link"_ls].toUrl(); m_removedLinkPreviews += m_components[row].attributes["link"_ls].toUrl();
m_components.remove(row); m_components.remove(row);
m_components.squeeze(); m_components.squeeze();
endResetModel();
resetContent(); resetContent();
} }
} }

View File

@@ -212,7 +212,7 @@ QVariant RoomListModel::data(const QModelIndex &index, int role) const
return room->displayName().toHtmlEscaped(); return room->displayName().toHtmlEscaped();
} }
if (role == AvatarRole) { if (role == AvatarRole) {
return room->avatarMediaId(); return room->avatarMediaUrl();
} }
if (role == CanonicalAliasRole) { if (role == CanonicalAliasRole) {
return room->canonicalAlias(); return room->canonicalAlias();

View File

@@ -286,6 +286,7 @@ QHash<int, QByteArray> RoomTreeModel::roleNames() const
roles[IconRole] = "icon"; roles[IconRole] = "icon";
roles[AttentionRole] = "attention"; roles[AttentionRole] = "attention";
roles[FavouriteRole] = "favourite"; roles[FavouriteRole] = "favourite";
roles[RoomTypeRole] = "roomType";
return roles; return roles;
} }
@@ -323,7 +324,7 @@ QVariant RoomTreeModel::data(const QModelIndex &index, int role) const
return room->displayName(); return room->displayName();
} }
if (role == AvatarRole) { if (role == AvatarRole) {
return room->avatarMediaId(); return room->avatarMediaUrl();
} }
if (role == CanonicalAliasRole) { if (role == CanonicalAliasRole) {
return room->canonicalAlias(); return room->canonicalAlias();
@@ -385,6 +386,11 @@ QVariant RoomTreeModel::data(const QModelIndex &index, int role) const
if (role == FavouriteRole) { if (role == FavouriteRole) {
return room->isFavourite(); return room->isFavourite();
} }
if (role == RoomTypeRole) {
if (room->creation()) {
return room->creation()->contentPart<QString>("type"_L1);
}
}
return {}; return {};
} }

View File

@@ -50,6 +50,7 @@ public:
IconRole, IconRole,
AttentionRole, /**< Whether there are any notifications. */ AttentionRole, /**< Whether there are any notifications. */
FavouriteRole, /**< Whether the room is favourited. */ FavouriteRole, /**< Whether the room is favourited. */
RoomTypeRole, /**< The room's type. */
}; };
Q_ENUM(EventRoles) Q_ENUM(EventRoles)
explicit RoomTreeModel(QObject *parent = nullptr); explicit RoomTreeModel(QObject *parent = nullptr);

View File

@@ -157,6 +157,11 @@ bool SortFilterRoomTreeModel::filterAcceptsRow(int source_row, const QModelIndex
return false; return false;
} }
// Hide rooms with defined types, assuming that data-holding rooms have a defined type
if (!sourceModel()->data(index, RoomTreeModel::RoomTypeRole).toString().isEmpty()) {
return false;
}
static auto config = NeoChatConfig::self(); static auto config = NeoChatConfig::self();
if (config->allRoomsInHome() && RoomManager::instance().currentSpace().isEmpty()) { if (config->allRoomsInHome() && RoomManager::instance().currentSpace().isEmpty()) {
return acceptRoom; return acceptRoom;

View File

@@ -261,7 +261,7 @@ Action=Popup
Name=Share Name=Share
Name[ar]=شارك Name[ar]=شارك
Name[ca]=Compartició Name[ca]=Compartició
Name[ca@valencia]=Compartició Name[ca@valencia]=Compartiu
Name[cs]=Sdílet Name[cs]=Sdílet
Name[de]=Teilen Name[de]=Teilen
Name[el]=Κοινοποίηση Name[el]=Κοινοποίηση

View File

@@ -431,9 +431,9 @@ QDateTime NeoChatRoom::lastActiveTime()
return messageEvents().rbegin()->get()->originTimestamp(); return messageEvents().rbegin()->get()->originTimestamp();
} }
QString NeoChatRoom::avatarMediaId() const QUrl NeoChatRoom::avatarMediaUrl() const
{ {
if (const auto avatar = Room::avatarMediaId(); !avatar.isEmpty()) { if (const auto avatar = Room::avatarUrl(); !avatar.isEmpty()) {
return avatar; return avatar;
} }
@@ -441,7 +441,7 @@ QString NeoChatRoom::avatarMediaId() const
const auto directChatMembers = this->directChatMembers(); const auto directChatMembers = this->directChatMembers();
for (const auto member : directChatMembers) { for (const auto member : directChatMembers) {
if (member != localMember()) { if (member != localMember()) {
return member.avatarMediaId(); return member.avatarUrl();
} }
} }

View File

@@ -69,9 +69,9 @@ class NeoChatRoom : public Quotient::Room
Q_PROPERTY(bool readMarkerLoaded READ readMarkerLoaded NOTIFY readMarkerLoadedChanged) Q_PROPERTY(bool readMarkerLoaded READ readMarkerLoaded NOTIFY readMarkerLoadedChanged)
/** /**
* @brief The avatar image to be used for the room. * @brief The avatar image to be used for the room, as a mxc:// URL.
*/ */
Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged STORED false) Q_PROPERTY(QUrl avatarMediaUrl READ avatarMediaUrl NOTIFY avatarChanged STORED false)
/** /**
* @brief Get a RoomMember object for the other person in a direct chat. * @brief Get a RoomMember object for the other person in a direct chat.
@@ -320,7 +320,7 @@ public:
[[nodiscard]] bool readMarkerLoaded() const; [[nodiscard]] bool readMarkerLoaded() const;
[[nodiscard]] QString avatarMediaId() const; [[nodiscard]] QUrl avatarMediaUrl() const;
NeochatRoomMember *directChatRemoteMember(); NeochatRoomMember *directChatRemoteMember();

View File

@@ -153,15 +153,6 @@ QColor NeochatRoomMember::color() const
return m_room->member(m_memberId).color(); return m_room->member(m_memberId).color();
} }
QString NeochatRoomMember::avatarMediaId() const
{
if (m_room == nullptr || m_memberId.isEmpty()) {
return {};
}
return m_room->member(m_memberId).avatarMediaId();
}
QUrl NeochatRoomMember::avatarUrl() const QUrl NeochatRoomMember::avatarUrl() const
{ {
if (m_room == nullptr || m_memberId.isEmpty()) { if (m_room == nullptr || m_memberId.isEmpty()) {

View File

@@ -70,7 +70,6 @@ public:
int hue() const; int hue() const;
qreal hueF() const; qreal hueF() const;
QColor color() const; QColor color() const;
QString avatarMediaId() const;
QUrl avatarUrl() const; QUrl avatarUrl() const;
Q_SIGNALS: Q_SIGNALS:

View File

@@ -77,7 +77,7 @@ Comment[ru]=Поиск комнат NeoChat
Comment[sl]=Najdi sobe v NeoChatu Comment[sl]=Najdi sobe v NeoChatu
Comment[sv]=Sök efter rum i NeoChat Comment[sv]=Sök efter rum i NeoChat
Comment[ta]=நியோச்சாட்டில் அரங்குகளை கண்டுபிடிக்கும் Comment[ta]=நியோச்சாட்டில் அரங்குகளை கண்டுபிடிக்கும்
Comment[tr]=NeoChat'te odalar bulun Comment[tr]=NeoChatte odalar bulun
Comment[uk]=Пошук кімнат у NeoChat Comment[uk]=Пошук кімнат у NeoChat
Comment[x-test]=xxFind rooms in NeoChatxx Comment[x-test]=xxFind rooms in NeoChatxx
Comment[zh_CN]=在 NeoChat 查找聊天室 Comment[zh_CN]=在 NeoChat 查找聊天室

View File

@@ -30,6 +30,7 @@ class PollHandler : public QObject
{ {
Q_OBJECT Q_OBJECT
QML_ELEMENT QML_ELEMENT
QML_UNCREATABLE("Use NeoChatRoom::poll")
/** /**
* @brief The question for the poll. * @brief The question for the poll.
@@ -91,7 +92,7 @@ Q_SIGNALS:
void hasEndedChanged(); void hasEndedChanged();
private: private:
const Quotient::PollStartEvent *m_pollStartEvent; const Quotient::PollStartEvent *m_pollStartEvent = nullptr;
void updatePoll(Quotient::RoomEventsRange events); void updatePoll(Quotient::RoomEventsRange events);

View File

@@ -26,6 +26,7 @@
"Name[nn]": "Tobias Fella", "Name[nn]": "Tobias Fella",
"Name[pl]": "Tobias Fella", "Name[pl]": "Tobias Fella",
"Name[ru]": "Tobias Fella", "Name[ru]": "Tobias Fella",
"Name[sk]": "Tobias Fella",
"Name[sl]": "Tobias Fella", "Name[sl]": "Tobias Fella",
"Name[sv]": "Tobias Fella", "Name[sv]": "Tobias Fella",
"Name[ta]": "டோபியாஸ் ஃபெல்லா", "Name[ta]": "டோபியாஸ் ஃபெல்லா",
@@ -66,7 +67,7 @@
"Description[uk]": "Оприлюднити за допомогою NeoChat", "Description[uk]": "Оприлюднити за допомогою NeoChat",
"Description[x-test]": "xxShare via NeoChatxx", "Description[x-test]": "xxShare via NeoChatxx",
"Description[zh_TW]": "透過 NeoChat 分享", "Description[zh_TW]": "透過 NeoChat 分享",
"Icon": "org.kde.neochat", "Icon": "org.kde.neochat.tray",
"License": "GPL", "License": "GPL",
"Name": "NeoChat", "Name": "NeoChat",
"Name[ar]": "نيوتشات", "Name[ar]": "نيوتشات",
@@ -93,6 +94,7 @@
"Name[nn]": "NeoChat", "Name[nn]": "NeoChat",
"Name[pl]": "NeoChat", "Name[pl]": "NeoChat",
"Name[ru]": "NeoChat", "Name[ru]": "NeoChat",
"Name[sk]": "NeoChat",
"Name[sl]": "NeoChat", "Name[sl]": "NeoChat",
"Name[sv]": "NeoChat", "Name[sv]": "NeoChat",
"Name[ta]": "நியோச்சாட்", "Name[ta]": "நியோச்சாட்",

View File

@@ -27,7 +27,8 @@ QQC2.Menu {
text: "https://matrix.to/#/" + root.connection.localUser.id, text: "https://matrix.to/#/" + root.connection.localUser.id,
title: root.connection.localUser.displayName, title: root.connection.localUser.displayName,
subtitle: root.connection.localUser.id, subtitle: root.connection.localUser.id,
avatarSource: root.connection.makeMediaUrl(root.connection.localUser.avatarUrl) // Note: User::avatarUrl does not set user_id, and thus cannot be used directly here. Hence the makeMediaUrl.
avatarSource: root.connection.localUser.avatarUrl.toString().length > 0 ? root.connection.makeMediaUrl(root.connection.localUser.avatarUrl) : ""
}); });
if (typeof root.closeDialog === "function") { if (typeof root.closeDialog === "function") {
root.closeDialog(); root.closeDialog();

View File

@@ -125,7 +125,7 @@ Kirigami.Dialog {
width: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing width: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing
height: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing height: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing
} }
source: userDelegate.connection.localUser.avatarMediaId ? userDelegate.connection.makeMediaUrl("mxc://" + userDelegate.connection.localUser.avatarMediaId) : "" source: userDelegate.connection.localUser.avatarUrl.toString().length > 0 ? userDelegate.connection.makeMediaUrl(userDelegate.connection.localUser.avatarUrl) : ""
name: userDelegate.connection.localUser.displayName ?? userDelegate.connection.localUser.id name: userDelegate.connection.localUser.displayName ?? userDelegate.connection.localUser.id
} }

View File

@@ -18,7 +18,7 @@ QQC2.ItemDelegate {
required property NeoChatRoom currentRoom required property NeoChatRoom currentRoom
required property bool categoryVisible required property bool categoryVisible
required property string filterText required property string filterText
required property string avatar required property url avatar
required property string displayName required property string displayName
topPadding: Kirigami.Units.largeSpacing topPadding: Kirigami.Units.largeSpacing
@@ -32,7 +32,7 @@ QQC2.ItemDelegate {
visible: root.categoryVisible || filterText.length > 0 visible: root.categoryVisible || filterText.length > 0
contentItem: KirigamiComponents.Avatar { contentItem: KirigamiComponents.Avatar {
source: root.avatar ? root.currentRoom.connection.makeMediaUrl("mxc://" + root.avatar) : "" source: root.avatar
name: root.displayName name: root.displayName
sourceSize { sourceSize {

View File

@@ -163,7 +163,7 @@ Loader {
spacing: Kirigami.Units.largeSpacing spacing: Kirigami.Units.largeSpacing
KirigamiComponents.Avatar { KirigamiComponents.Avatar {
id: avatar id: avatar
source: room.avatarMediaId ? root.connection.makeMediaUrl("mxc://" + room.avatarMediaId) : "" source: room.avatarMediaUrl
name: room.displayName name: room.displayName
Layout.preferredWidth: Kirigami.Units.gridUnit * 3 Layout.preferredWidth: Kirigami.Units.gridUnit * 3
Layout.preferredHeight: Kirigami.Units.gridUnit * 3 Layout.preferredHeight: Kirigami.Units.gridUnit * 3

View File

@@ -5,6 +5,7 @@
import QtQuick import QtQuick
import QtQuick.Controls as QQC2 import QtQuick.Controls as QQC2
import QtQuick.Layouts import QtQuick.Layouts
import Qt.labs.qmlmodels
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.components as KirigamiComponents import org.kde.kirigamiaddons.components as KirigamiComponents
import org.kde.kirigamiaddons.formcard as FormCard import org.kde.kirigamiaddons.formcard as FormCard
@@ -177,10 +178,25 @@ Loader {
Repeater { Repeater {
model: root.actions model: root.actions
QQC2.MenuItem { DelegateChooser {
visible: modelData.visible role: "separator"
action: modelData DelegateChoice {
onClicked: root.item.close() roleValue: true
QQC2.MenuSeparator {
visible: modelData.visible
}
}
DelegateChoice {
roleValue: false
QQC2.MenuItem {
visible: modelData.visible
action: modelData
onClicked: root.item.close()
}
}
} }
} }
QQC2.Menu { QQC2.Menu {
@@ -196,7 +212,7 @@ Loader {
model: WebShortcutModel { model: WebShortcutModel {
id: webshortcutmodel id: webshortcutmodel
selectedText: root.selectedText.length > 0 ? root.selectedText : root.plainText selectedText: root.selectedText.length > 0 ? root.selectedText : root.plainText
onOpenUrl: RoomManager.resolveResource(url) onOpenUrl: url => RoomManager.resolveResource(url.toString())
} }
delegate: QQC2.MenuItem { delegate: QQC2.MenuItem {
text: model.display text: model.display
@@ -341,15 +357,30 @@ Loader {
id: listViewAction id: listViewAction
model: root.actions model: root.actions
FormCard.FormButtonDelegate { DelegateChooser {
icon.name: modelData.icon.name role: "separator"
icon.color: modelData.icon.color ?? undefined DelegateChoice {
enabled: modelData.enabled roleValue: true
visible: modelData.visible
text: modelData.text FormCard.FormDelegateSeparator {
onClicked: { visible: modelData.visible
modelData.triggered(); }
root.item.close(); }
DelegateChoice {
roleValue: false
FormCard.FormButtonDelegate {
icon.name: modelData.icon.name
icon.color: modelData.icon.color ?? undefined
enabled: modelData.enabled
visible: modelData.visible
text: modelData.text
onClicked: {
modelData.triggered();
root.item.close();
}
}
} }
} }
} }

View File

@@ -38,7 +38,7 @@ ColumnLayout {
contentItem: KirigamiComponents.Avatar { contentItem: KirigamiComponents.Avatar {
name: root.room ? root.room.displayName : "" name: root.room ? root.room.displayName : ""
source: root.room ? root.room.connection.makeMediaUrl("mxc://" + root.room.avatarMediaId) : "" source: root.room ? root.room.avatarMediaUrl : ""
Rectangle { Rectangle {
visible: root.room.usesEncryption visible: root.room.usesEncryption

View File

@@ -54,8 +54,8 @@ DelegateContextMenu {
icon.name: "document-save" icon.name: "document-save"
onTriggered: { onTriggered: {
var dialog = saveAsDialog.createObject(QQC2.Overlay.overlay); var dialog = saveAsDialog.createObject(QQC2.Overlay.overlay);
dialog.selectedFile = currentRoom.fileNameToDownload(eventId);
dialog.open(); dialog.open();
dialog.currentFile = dialog.folder + "/" + currentRoom.fileNameToDownload(eventId);
} }
}, },
DelegateContextMenu.ReplyMessageAction {}, DelegateContextMenu.ReplyMessageAction {},

View File

@@ -102,7 +102,7 @@ Labs.MenuBar {
} }
Labs.MenuItem { Labs.MenuItem {
text: i18nc("menu", "About KDE") text: i18nc("menu", "About KDE")
onTriggered: pageStack.pushDialogLayer(Qt.createComponent("org.kde.kirigamiaddons.formcard", "AboutKDE")) onTriggered: pageStack.pushDialogLayer(Qt.createComponent("org.kde.kirigamiaddons.formcard", "AboutKDEPage"))
} }
} }
} }

View File

@@ -34,7 +34,7 @@ ColumnLayout {
Layout.preferredHeight: Kirigami.Units.iconSizes.large Layout.preferredHeight: Kirigami.Units.iconSizes.large
name: root.room ? root.room.displayName : "" name: root.room ? root.room.displayName : ""
source: root.room ? root.room.connection.makeMediaUrl("mxc://" + root.room.avatarMediaId) : "" source: root.room ? root.room.avatarMediaUrl : ""
Rectangle { Rectangle {
visible: room.usesEncryption visible: room.usesEncryption
@@ -75,6 +75,7 @@ ColumnLayout {
textFormat: TextEdit.PlainText textFormat: TextEdit.PlainText
visible: root.room && root.room.canonicalAlias visible: root.room && root.room.canonicalAlias
text: root.room && root.room.canonicalAlias ? root.room.canonicalAlias : "" text: root.room && root.room.canonicalAlias ? root.room.canonicalAlias : ""
color: Kirigami.Theme.disabledTextColor
} }
} }
QQC2.AbstractButton { QQC2.AbstractButton {
@@ -92,7 +93,7 @@ ColumnLayout {
text: barcode.content, text: barcode.content,
title: root.room ? root.room.displayName : "", title: root.room ? root.room.displayName : "",
subtitle: root.room ? root.room.id : "", subtitle: root.room ? root.room.id : "",
avatarSource: root.room && root.room.avatarMediaId ? root.room.connection.makeMediaUrl("mxc://" + root.room.avatarMediaId) : "" avatarSource: root.room ? root.room.avatarMediaUrl : ""
}); });
map.open(); map.open();
} }

View File

@@ -7,7 +7,6 @@ import QtQuick.Layouts
import QtCore as Core import QtCore as Core
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.labs.components as KirigamiComponents
import org.kde.kquickimageeditor as KQuickImageEditor import org.kde.kquickimageeditor as KQuickImageEditor
Kirigami.Page { Kirigami.Page {
@@ -168,10 +167,11 @@ Kirigami.Page {
} }
} }
footer: KirigamiComponents.Banner { footer: Kirigami.InlineMessage {
id: msg id: msg
type: Kirigami.MessageType.Error type: Kirigami.MessageType.Error
showCloseButton: true showCloseButton: true
visible: false visible: false
position: Kirigami.InlineMessage.Position.Header
} }
} }

View File

@@ -104,12 +104,14 @@ Components.AlbumMaximizeComponent {
} }
} }
onOpened: forceActiveFocus()
onItemRightClicked: RoomManager.viewEventMenu(root.currentEventId, root.currentRoom) onItemRightClicked: RoomManager.viewEventMenu(root.currentEventId, root.currentRoom)
onSaveItem: { onSaveItem: {
var dialog = saveAsDialog.createObject(QQC2.Overlay.overlay); var dialog = saveAsDialog.createObject(QQC2.Overlay.overlay);
dialog.selectedFile = currentRoom.fileNameToDownload(root.currentEventId);
dialog.open(); dialog.open();
dialog.currentFile = dialog.folder + "/" + currentRoom.fileNameToDownload(root.currentEventId);
} }
Connections { Connections {

View File

@@ -12,7 +12,9 @@ Components.AbstractMaximizeComponent {
required property string text required property string text
property color avatarColor property color avatarColor
required property string avatarSource required property url avatarSource
onOpened: forceActiveFocus()
Shortcut { Shortcut {
sequences: [StandardKey.Cancel] sequences: [StandardKey.Cancel]

View File

@@ -27,6 +27,7 @@ Kirigami.SearchDialog {
onTextChanged: RoomManager.sortFilterRoomListModel.filterText = text onTextChanged: RoomManager.sortFilterRoomListModel.filterText = text
model: RoomManager.sortFilterRoomListModel model: RoomManager.sortFilterRoomListModel
emptyText: i18nc("Placeholder message", "No room found") emptyText: i18nc("Placeholder message", "No room found")
parent: QQC2.Overlay.overlay
delegate: RoomDelegate { delegate: RoomDelegate {
connection: root.connection connection: root.connection

View File

@@ -30,9 +30,9 @@ Kirigami.Dialog {
FormCard.AbstractFormDelegate { FormCard.AbstractFormDelegate {
background: null background: null
contentItem: RowLayout { contentItem: RowLayout {
spacing: Kirigami.Units.largeSpacing * 4 spacing: Kirigami.Units.largeSpacing
Avatar { Avatar {
source: root.connection.makeMediaUrl(SpaceHierarchyCache.recommendedSpaceAvatar) source: SpaceHierarchyCache.recommendedSpaceAvatar.toString().length > 0 ? root.connection.makeMediaUrl(SpaceHierarchyCache.recommendedSpaceAvatar) : 0
name: SpaceHierarchyCache.recommendedSpaceDisplayName name: SpaceHierarchyCache.recommendedSpaceDisplayName
} }
ColumnLayout { ColumnLayout {
@@ -51,6 +51,7 @@ Kirigami.Dialog {
FormCard.FormDelegateSeparator {} FormCard.FormDelegateSeparator {}
FormCard.FormButtonDelegate { FormCard.FormButtonDelegate {
text: i18nc("@action:button", "Join") text: i18nc("@action:button", "Join")
icon.name: "list-add-symbolic"
onClicked: { onClicked: {
SpaceHierarchyCache.recommendedSpaceHidden = true; SpaceHierarchyCache.recommendedSpaceHidden = true;
RoomManager.resolveResource(SpaceHierarchyCache.recommendedSpaceId, "join"); RoomManager.resolveResource(SpaceHierarchyCache.recommendedSpaceId, "join");
@@ -58,6 +59,7 @@ Kirigami.Dialog {
} }
} }
FormCard.FormButtonDelegate { FormCard.FormButtonDelegate {
icon.name: "mail-thread-ignored-symbolic"
text: i18nc("@action:button", "Ignore") text: i18nc("@action:button", "Ignore")
onClicked: { onClicked: {
SpaceHierarchyCache.recommendedSpaceHidden = true; SpaceHierarchyCache.recommendedSpaceHidden = true;

View File

@@ -21,7 +21,7 @@ Delegates.RoundedItemDelegate {
required property bool hasHighlightNotifications required property bool hasHighlightNotifications
required property NeoChatRoom currentRoom required property NeoChatRoom currentRoom
required property NeoChatConnection connection required property NeoChatConnection connection
required property string avatar required property url avatar
required property string subtitleText required property string subtitleText
required property string displayName required property string displayName
@@ -55,7 +55,7 @@ Delegates.RoundedItemDelegate {
spacing: Kirigami.Units.largeSpacing spacing: Kirigami.Units.largeSpacing
AvatarNotification { AvatarNotification {
source: root.avatar ? root.connection.makeMediaUrl("mxc://" + root.avatar) : "" source: root.avatar
name: root.displayName name: root.displayName
visible: NeoChatConfig.showAvatarInRoomDrawer visible: NeoChatConfig.showAvatarInRoomDrawer
implicitHeight: Kirigami.Units.gridUnit + (NeoChatConfig.compactRoomList ? 0 : Kirigami.Units.largeSpacing * 2) implicitHeight: Kirigami.Units.gridUnit + (NeoChatConfig.compactRoomList ? 0 : Kirigami.Units.largeSpacing * 2)

View File

@@ -99,8 +99,11 @@ Kirigami.OverlayDrawer {
Layout.preferredHeight: pageStack.globalToolBar.preferredHeight Layout.preferredHeight: pageStack.globalToolBar.preferredHeight
contentItem: RowLayout { contentItem: RowLayout {
spacing: 0
Kirigami.Heading { Kirigami.Heading {
Layout.fillWidth: true Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing
text: drawerItemLoader.item ? drawerItemLoader.item.title : "" text: drawerItemLoader.item ? drawerItemLoader.item.title : ""
} }

View File

@@ -219,7 +219,7 @@ QQC2.ScrollView {
required property int index required property int index
required property string name required property string name
required property string userId required property string userId
required property string avatar required property url avatar
required property int powerLevel required property int powerLevel
required property string powerLevelString required property string powerLevelString

View File

@@ -7,7 +7,6 @@ import QtQuick.Controls as QQC2
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Window import QtQuick.Window
import org.kde.kirigamiaddons.labs.components as KirigamiComponents
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.kitemmodels import org.kde.kitemmodels
@@ -99,11 +98,12 @@ Kirigami.Page {
} }
} }
header: KirigamiComponents.Banner { header: Kirigami.InlineMessage {
id: banner id: banner
showCloseButton: true showCloseButton: true
visible: false visible: false
position: Kirigami.InlineMessage.Position.Header
} }
Loader { Loader {
@@ -198,7 +198,7 @@ Kirigami.Page {
Shortcut { Shortcut {
sequence: StandardKey.Cancel sequence: StandardKey.Cancel
onActivated: { onActivated: {
if (!timelineViewLoader.item.atYEnd || root.currentRoom.hasUnreadMessages) { if (!timelineViewLoader.item.atYEnd || !root.currentRoom.partiallyReadStats.empty()) {
timelineViewLoader.item.goToLastMessage(); timelineViewLoader.item.goToLastMessage();
root.currentRoom.markAllMessagesAsRead(); root.currentRoom.markAllMessagesAsRead();
} else { } else {
@@ -253,7 +253,6 @@ Kirigami.Page {
messageComponentType: messageComponentType, messageComponentType: messageComponentType,
plainText: plainText, plainText: plainText,
htmlText: htmlText, htmlText: htmlText,
isThread: isThread
}); });
contextMenu.open(); contextMenu.open();
} }
@@ -265,7 +264,6 @@ Kirigami.Page {
plainText: plainText, plainText: plainText,
mimeType: mimeType, mimeType: mimeType,
progressInfo: progressInfo, progressInfo: progressInfo,
isThread: isThread
}); });
contextMenu.open(); contextMenu.open();
} }

View File

@@ -182,7 +182,7 @@ QQC2.Control {
id: spaceDelegate id: spaceDelegate
required property string displayName required property string displayName
required property string avatar required property url avatar
required property string roomId required property string roomId
required property var currentRoom required property var currentRoom
@@ -191,7 +191,7 @@ QQC2.Control {
Layout.maximumHeight: width - Kirigami.Units.smallSpacing Layout.maximumHeight: width - Kirigami.Units.smallSpacing
text: displayName text: displayName
source: avatar ? root.connection.makeMediaUrl("mxc://" + avatar) : "" source: avatar
notificationCount: spaceDelegate.currentRoom.childrenNotificationCount notificationCount: spaceDelegate.currentRoom.childrenNotificationCount
notificationHighlight: spaceDelegate.currentRoom.childrenHaveHighlightNotifications notificationHighlight: spaceDelegate.currentRoom.childrenHaveHighlightNotifications
@@ -219,7 +219,7 @@ QQC2.Control {
visible: SpaceHierarchyCache.recommendedSpaceId.length > 0 && !root.connection.room(SpaceHierarchyCache.recommendedSpaceId) && !SpaceHierarchyCache.recommendedSpaceHidden visible: SpaceHierarchyCache.recommendedSpaceId.length > 0 && !root.connection.room(SpaceHierarchyCache.recommendedSpaceId) && !SpaceHierarchyCache.recommendedSpaceHidden
text: i18nc("Join <name of a space>", "Join %1", SpaceHierarchyCache.recommendedSpaceDisplayName) text: i18nc("Join <name of a space>", "Join %1", SpaceHierarchyCache.recommendedSpaceDisplayName)
source: SpaceHierarchyCache.recommendedSpaceAvatar.length > 0 ? root.connection.makeMediaUrl(SpaceHierarchyCache.recommendedSpaceAvatar) : "" source: SpaceHierarchyCache.recommendedSpaceAvatar.toString().length > 0 ? root.connection.makeMediaUrl(SpaceHierarchyCache.recommendedSpaceAvatar) : ""
onSelected: { onSelected: {
recommendedSpaceDialogComponent.createObject(QQC2.Overlay.overlay, { recommendedSpaceDialogComponent.createObject(QQC2.Overlay.overlay, {
connection: root.connection connection: root.connection

View File

@@ -96,7 +96,7 @@ Loader {
KirigamiComponents.Avatar { KirigamiComponents.Avatar {
id: avatar id: avatar
source: room.avatarMediaId ? root.room.connection.makeMediaUrl("mxc://" + room.avatarMediaId) : "" source: room.avatarMediaUrl
Layout.preferredWidth: Kirigami.Units.gridUnit * 3 Layout.preferredWidth: Kirigami.Units.gridUnit * 3
Layout.preferredHeight: Kirigami.Units.gridUnit * 3 Layout.preferredHeight: Kirigami.Units.gridUnit * 3
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop

View File

@@ -186,7 +186,7 @@ QQC2.ScrollView {
padding: Kirigami.Units.largeSpacing padding: Kirigami.Units.largeSpacing
z: 2 z: 2
visible: (root.currentRoom?.hasUnreadMessages ?? false) visible: (!root.currentRoom?.partiallyReadStats.empty())
text: root.currentRoom.readMarkerLoaded ? i18n("Jump to first unread message") : i18n("Jump to oldest loaded message") text: root.currentRoom.readMarkerLoaded ? i18n("Jump to first unread message") : i18n("Jump to oldest loaded message")
action: Kirigami.Action { action: Kirigami.Action {
@@ -195,7 +195,7 @@ QQC2.ScrollView {
root.focusChatBar(); root.focusChatBar();
} }
goReadMarkerFab.textChanged() goReadMarkerFab.textChanged()
messageListView.goToEvent(root.currentRoom.readMarkerEventId); messageListView.goToEvent(root.currentRoom.lastFullyReadEventId);
} }
icon.name: "go-up" icon.name: "go-up"
shortcut: "Shift+PgUp" shortcut: "Shift+PgUp"
@@ -354,7 +354,7 @@ QQC2.ScrollView {
} }
function allUnreadVisible() { function allUnreadVisible() {
let readMarkerRow = eventToIndex(root.currentRoom.readMarkerEventId); let readMarkerRow = eventToIndex(root.currentRoom.lastFullyReadEventId);
if (readMarkerRow >= 0 && readMarkerRow < firstVisibleIndex() && messageListView.atYEnd) { if (readMarkerRow >= 0 && readMarkerRow < firstVisibleIndex() && messageListView.atYEnd) {
return true; return true;
} }

View File

@@ -7,7 +7,6 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.kirigamiaddons.labs.components as KirigamiComponents
import org.kde.neochat import org.kde.neochat
@@ -20,11 +19,12 @@ FormCard.FormCardPage {
leftPadding: 0 leftPadding: 0
rightPadding: 0 rightPadding: 0
header: KirigamiComponents.Banner { header: Kirigami.InlineMessage {
id: banner id: banner
showCloseButton: true showCloseButton: true
visible: false visible: false
type: Kirigami.MessageType.Error type: Kirigami.MessageType.Error
position: Kirigami.InlineMessage.Position.Header
} }
property SSSSHandler ssssHandler: SSSSHandler { property SSSSHandler ssssHandler: SSSSHandler {

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