Compare commits

..

22 Commits

Author SHA1 Message Date
Bhushan Shah
3f8d2a11d0 Update version number for 22.11
GIT_SILENT
2022-11-30 13:30:05 +05:30
l10n daemon script
eb38741486 GIT_SILENT Sync po/docbooks with svn 2022-11-30 02:06:44 +00:00
Tobias Fella
f207f57bd5 Various Qt6 fixes 2022-11-30 00:13:29 +00:00
Tobias Fella
74b9f5fa4f Make sure at most one layer is pushed from the menu
BUG: 459738
2022-11-30 00:07:33 +00:00
Tobias Fella
6347c02d8b Delete access token file infrastructure
We've never supported it and it's broken, unsecure and leads to crashes-

BUG: 460407
2022-11-29 23:43:35 +00:00
Tobias Fella
8dbfc093fa Don't show "Configure Web Shortcuts" in flatpak
Doesn't work as it requires kcmshell5
2022-11-29 23:34:43 +00:00
James Graham
6acb847843 Migrate room general settings to mobileform
![image](/uploads/98b895cbbf59ef9215b2085e120e5db5/image.png)
2022-11-29 23:27:30 +00:00
Tobias Fella
e270a46a36 Add Kirigami-Addons to CI 2022-11-29 22:57:23 +00:00
Tobias Fella
e010116232 Re-enable windows CI 2022-11-29 23:51:46 +01:00
Tobias Fella
9bcbdb78fd Revert "Fix /me giving extra newline"
This reverts commit 42d728ac4b.
2022-11-29 16:21:45 +01:00
Devin Lin
85b0ec1e96 Add compile time Kirigami Addons dependency 2022-11-29 03:15:50 +00:00
l10n daemon script
e4f42e2c2b GIT_SILENT Sync po/docbooks with svn 2022-11-29 02:06:38 +00:00
Tobias Fella
8b5910773c Fix avatar name in RoomDrawer for DMs 2022-11-28 20:36:28 +01:00
Tobias Fella
1366158b45 Add menu items to copy matrix.to links for users and messages
BUG: 456637
2022-11-28 19:01:27 +00:00
Tobias Fella
d0dd86e6e8 Add option to hide deleted messages
Implements #430
2022-11-28 18:52:49 +00:00
James Graham
af40860315 Fix roompage up/down button highlights
Set the focus to the chatbar after clicking the jump up/down buttons so that they don't stay highlighted.
Also remove messageListView.headerItem.height as part of the down button margin calc as it no longer exists

BUG: 456075
2022-11-28 18:43:52 +00:00
Tobias Fella
f3d7fbc483 Don't convert emotes to HTML
BUG: 461837
2022-11-28 18:31:42 +00:00
Nicolas Fella
d07066e540 Don't hardcode Qt5 2022-11-28 03:06:45 +01:00
Akseli Lahtinen
dfb569c0f6 Possible typing notification fixes
I've made few possible fixes for the typing notification getting stuck for long periods of time.

I could use some help testing these to see if they help others too. 

For me the typing notification doesn't linger around that long after these changes.
2022-11-27 20:44:41 +00:00
Tobias Fella
fda433706b Remember last used folder in save dialogs
BUG: 460166
2022-11-27 19:54:07 +00:00
Tobias Fella
a734be5f9e Open target room when using join command with an already joined room
BUG: 455825
2022-11-27 18:04:17 +00:00
Tobias Fella
7ebd82d441 Port Loading.qml to LoadingPlaceholder
BUG: 456629
2022-11-27 18:31:42 +01:00
73 changed files with 11467 additions and 9617 deletions

View File

@@ -136,8 +136,8 @@
"sources": [
{
"type": "archive",
"url": "https://github.com/danvratil/qcoro/archive/refs/tags/v0.4.0.tar.gz",
"sha256": "0e68b3f0ce7bf521ffbdd731464d2d60d8d7a39a749b551ed26855a1707d86d1",
"url": "https://github.com/danvratil/qcoro/archive/refs/tags/v0.7.0.tar.gz",
"sha256": "23ef0217926e67c8d2eb861cf91617da2f7d8d5a9ae6c62321b21448b1669210",
"x-checker-data": {
"type": "anitya",
"project-id": 236236,

View File

@@ -7,7 +7,6 @@ include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
# TODO enable once we can have qt6 libQuotient on the CI
# - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
# TODO re-enable once cmark is in the CI again
# - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/flatpak.yml

View File

@@ -14,6 +14,7 @@ Dependencies:
'frameworks/knotifications': '@stable'
'libraries/kquickimageeditor': '@stable'
'frameworks/sonnet': '@stable'
'libraries/kirigami-addons': '@latest'
- 'on': ['Windows', 'Linux', 'FreeBSD']
'require':
'frameworks/qqc2-desktop-style': '@stable'

View File

@@ -7,7 +7,7 @@
cmake_minimum_required(VERSION 3.16)
project(NeoChat)
set(PROJECT_VERSION "22.09")
set(PROJECT_VERSION "22.11")
set(KF5_MIN_VERSION "5.91.0")
set(QT_MIN_VERSION "5.15.2")
@@ -58,6 +58,7 @@ set_package_properties(KF5Kirigami2 PROPERTIES
TYPE REQUIRED
PURPOSE "Kirigami application UI framework"
)
find_package(KF5KirigamiAddons 0.6 REQUIRED)
find_package(Qt${QT_MAJOR_VERSION}Keychain)
set_package_properties(Qt${QT_MAJOR_VERSION}Keychain PROPERTIES
@@ -80,8 +81,6 @@ else()
ecm_find_qmlmodule(org.kde.syntaxhighlighting 1.0)
endif()
ecm_find_qmlmodule(org.kde.kirigamiaddons.labs.mobileform 0.1)
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
find_package(KF5DBusAddons ${KF5_MIN_VERSION} REQUIRED)
endif()
@@ -145,7 +144,7 @@ add_definitions(-DQT_NO_FOREACH)
add_subdirectory(src)
if (BUILD_TESTING AND Quotient_VERSION_MINOR GREATER 6)
find_package(Qt5 ${QT_MIN_VERSION} NO_MODULE COMPONENTS Test)
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} NO_MODULE COMPONENTS Test)
add_subdirectory(autotests)
endif()

View File

@@ -218,6 +218,9 @@
<content_attribute id="social-chat">intense</content_attribute>
</content_rating>
<releases>
<release version="22.11" date="2022-11-30">
<url>https://plasma-mobile.org/2022/11/30/plasma-mobile-gear-22-11/</url>
</release>
<release version="22.09" date="2022-09-27">
<url>https://www.plasma-mobile.org/2022/09/27/plasma-mobile-gear-22-09/</url>
</release>

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

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: neochat\n"
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
"POT-Creation-Date: 2022-11-23 00:47+0000\n"
"POT-Creation-Date: 2022-11-27 00:46+0000\n"
"PO-Revision-Date: 2021-12-15 11:17+0100\n"
"Last-Translator: Øystein Steffensen-Alværvik <oysteins.omsetting@protonmail."
"com>\n"
@@ -53,7 +53,7 @@ msgid "Sends the given emote colored as a rainbow"
msgstr ""
#: src/actionsmodel.cpp:111
msgid "Sends the given given message as plain text"
msgid "Sends the given message as plain text"
msgstr ""
#: src/actionsmodel.cpp:127
@@ -387,16 +387,106 @@ msgstr ""
msgid "Unable to read access token"
msgstr ""
#: src/controller.cpp:720
#: src/controller.cpp:709
#, kde-format
msgid "Room creation failed: \"%1\""
msgstr "Feil ved romregistrering: «%1»"
#: src/controller.cpp:733
#: src/controller.cpp:722
#, kde-format
msgid "The room id you are trying to join is not valid"
msgstr "Rom-ID-en du prøver å bruka, er ikkje gyldig"
#: src/emojimodel.cpp:133
#, kde-format
msgctxt "Previously used emojis"
msgid "History"
msgstr ""
#: src/emojimodel.cpp:138
#, kde-format
msgctxt "'Custom' is a category of emoji"
msgid "Custom"
msgstr ""
#: src/emojimodel.cpp:143
#, kde-format
msgctxt "'Smileys' is a category of emoji"
msgid "Smileys"
msgstr ""
#: src/emojimodel.cpp:148
#, kde-format
msgctxt "'People' is a category of emoji"
msgid "People"
msgstr ""
#: src/emojimodel.cpp:153
#, kde-format
msgctxt "'Nature' is a category of emoji"
msgid "Nature"
msgstr ""
#: src/emojimodel.cpp:158
#, kde-format
msgctxt "'Food' is a category of emoji"
msgid "Food"
msgstr ""
#: src/emojimodel.cpp:163
#, kde-format
msgctxt "'Activities' is a category of emoji"
msgid "Activities"
msgstr ""
#: src/emojimodel.cpp:168
#, kde-format
msgctxt "'Travel' is a category of emoji"
msgid "Travel"
msgstr ""
#: src/emojimodel.cpp:173
#, kde-format
msgctxt "'Objects' is a category of emoji"
msgid "Objects"
msgstr ""
#: src/emojimodel.cpp:178
#, kde-format
msgctxt "'Symbols' is a category of emoji"
msgid "Symbols"
msgstr ""
#: src/emojimodel.cpp:183
#, kde-format
msgctxt "'Flags' is a category of emoji"
msgid "Flags"
msgstr ""
#: src/filetransferpseudojob.cpp:47
#, kde-format
msgctxt "Job heading, like 'Copying'"
msgid "Downloading"
msgstr ""
#: src/filetransferpseudojob.cpp:47
#, kde-format
msgctxt "Job heading, like 'Copying'"
msgid "Uploading"
msgstr ""
#: src/filetransferpseudojob.cpp:48
#, kde-format
msgctxt "The URL being downloaded/uploaded"
msgid "Source"
msgstr ""
#: src/filetransferpseudojob.cpp:49
#, kde-format
msgctxt "The location being downloaded to"
msgid "Destination"
msgstr ""
#: src/login.cpp:88 src/login.cpp:99
#, kde-format
msgid "Network Error"
@@ -480,12 +570,12 @@ msgctxt "<version number> (built against <possibly different version number>)"
msgid "%1 (built against %2)"
msgstr ""
#: src/main.cpp:270
#: src/main.cpp:273
#, kde-format
msgid "Client for the matrix communication protocol"
msgstr "Lynmeldings­klient for Matrix-protokollen"
#: src/main.cpp:271
#: src/main.cpp:274
#, kde-format
msgid "Supports matrix: url scheme"
msgstr ""
@@ -536,232 +626,232 @@ msgstr "[TREKT TILBAKE]"
msgid "[REDACTED: %1]"
msgstr "[TREKT TILBAKE: %1]"
#: src/neochatroom.cpp:480
#: src/neochatroom.cpp:493
#, kde-format
msgid "a file"
msgstr "ei fil"
#: src/neochatroom.cpp:529
#: src/neochatroom.cpp:542
#, kde-format
msgid "reinvited %1 to the room"
msgstr "inviterte %1 på nytt til rommet"
#: src/neochatroom.cpp:531
#: src/neochatroom.cpp:544
#, kde-format
msgctxt "Optional reason for an invitation"
msgid ": %1"
msgstr ": %1"
#: src/neochatroom.cpp:540
#: src/neochatroom.cpp:553
#, kde-format
msgid "joined the room (repeated)"
msgstr "kom inn i rommet (på nytt)"
#: src/neochatroom.cpp:542
#: src/neochatroom.cpp:555
#, kde-format
msgid "invited %1 to the room"
msgstr "inviterte %1 til rommet"
#: src/neochatroom.cpp:542
#: src/neochatroom.cpp:555
#, kde-format
msgid "joined the room"
msgstr "kom inn i rommet"
#: src/neochatroom.cpp:546
#: src/neochatroom.cpp:559
#, kde-format
msgid ": %1"
msgstr ": %1"
#: src/neochatroom.cpp:553
#: src/neochatroom.cpp:566
#, kde-format
msgctxt "their refers to a singular user"
msgid "cleared their display name"
msgstr "fjerna visingsnamnet"
#: src/neochatroom.cpp:555
#: src/neochatroom.cpp:568
#, kde-format
msgctxt "their refers to a singular user"
msgid "changed their display name to %1"
msgstr "endra visingsnamn til %1"
#: src/neochatroom.cpp:560
#: src/neochatroom.cpp:573
#, kde-format
msgid " and "
msgstr " og "
#: src/neochatroom.cpp:563
#: src/neochatroom.cpp:576
#, kde-format
msgctxt "their refers to a singular user"
msgid "cleared their avatar"
msgstr "fjerna avataren"
#: src/neochatroom.cpp:569
#: src/neochatroom.cpp:582
#, kde-format
msgid "set an avatar"
msgstr "valde ein avatar"
#: src/neochatroom.cpp:571
#: src/neochatroom.cpp:584
#, kde-format
msgctxt "their refers to a singular user"
msgid "updated their avatar"
msgstr "bytte avataren sin"
#: src/neochatroom.cpp:575
#: src/neochatroom.cpp:588
#, kde-format
msgctxt "<user> changed nothing"
msgid "changed nothing"
msgstr ""
#: src/neochatroom.cpp:581
#: src/neochatroom.cpp:594
#, kde-format
msgid "withdrew %1's invitation"
msgstr "trekte tilbake invitasjonen til %1"
#: src/neochatroom.cpp:581
#: src/neochatroom.cpp:594
#, kde-format
msgid "rejected the invitation"
msgstr "avviste invitasjonen"
#: src/neochatroom.cpp:585
#: src/neochatroom.cpp:598
#, kde-format
msgid "unbanned %1"
msgstr "oppheva utestenging av %1"
#: src/neochatroom.cpp:585
#: src/neochatroom.cpp:598
#, kde-format
msgid "self-unbanned"
msgstr "utestengde seg sjølv"
#: src/neochatroom.cpp:588
#: src/neochatroom.cpp:601
#, kde-format
msgid "has put %1 out of the room: %2"
msgstr "fjerna %1 frå rommet: %2"
#: src/neochatroom.cpp:589
#: src/neochatroom.cpp:602
#, kde-format
msgid "left the room"
msgstr "forlét rommet"
#: src/neochatroom.cpp:593
#: src/neochatroom.cpp:606
#, kde-format
msgid "banned %1 from the room"
msgstr ""
#: src/neochatroom.cpp:595
#: src/neochatroom.cpp:608
#, kde-format
msgid "banned %1 from the room: %2"
msgstr "utestengde %1 frå rommet: %2"
#: src/neochatroom.cpp:598
#: src/neochatroom.cpp:611
#, kde-format
msgid "self-banned from the room"
msgstr "utestengde seg sjølv frå rommet"
#: src/neochatroom.cpp:601
#: src/neochatroom.cpp:614
#, kde-format
msgid "requested an invite"
msgstr ""
#: src/neochatroom.cpp:604
#: src/neochatroom.cpp:617
#, kde-format
msgid "made something unknown"
msgstr "gjorde noko ukjend"
#: src/neochatroom.cpp:607
#: src/neochatroom.cpp:620
#, kde-format
msgid "cleared the room main alias"
msgstr "fjerna hovudaliaset til rommet"
#: src/neochatroom.cpp:607
#: src/neochatroom.cpp:620
#, kde-format
msgid "set the room main alias to: %1"
msgstr "bytte hovudalias for rommet til: %1"
#: src/neochatroom.cpp:610
#: src/neochatroom.cpp:623
#, kde-format
msgid "cleared the room name"
msgstr "fjerna romnamnet"
#: src/neochatroom.cpp:610
#: src/neochatroom.cpp:623
#, kde-format
msgid "set the room name to: %1"
msgstr "bytte romnamnet til: %1"
#: src/neochatroom.cpp:613
#: src/neochatroom.cpp:626
#, kde-format
msgid "cleared the topic"
msgstr "tømte emnefeltet"
#: src/neochatroom.cpp:613
#: src/neochatroom.cpp:626
#, kde-format
msgid "set the topic to: %1"
msgstr "bytte emnet til: %1"
#: src/neochatroom.cpp:616
#: src/neochatroom.cpp:629
#, kde-format
msgid "changed the room avatar"
msgstr "bytte ut romavataren"
#: src/neochatroom.cpp:619
#: src/neochatroom.cpp:632
#, kde-format
msgid "activated End-to-End Encryption"
msgstr "slå på ende-til-ende-kryptering"
#: src/neochatroom.cpp:622
#: src/neochatroom.cpp:635
#, kde-format
msgid "upgraded the room to version %1"
msgstr "oppgraderte rommet til versjon %1"
#: src/neochatroom.cpp:623
#: src/neochatroom.cpp:636
#, kde-format
msgid "created the room, version %1"
msgstr "oppretta rommet, versjon %1"
#: src/neochatroom.cpp:626
#: src/neochatroom.cpp:639
#, kde-format
msgctxt "'power level' means permission level"
msgid "changed the power levels for this room"
msgstr ""
#: src/neochatroom.cpp:630
#: src/neochatroom.cpp:643
#, kde-format
msgid "changed the server access control lists for this room"
msgstr ""
#: src/neochatroom.cpp:634
#: src/neochatroom.cpp:647
#, kde-format
msgctxt "[User] added <name> widget"
msgid "added %1 widget"
msgstr ""
#: src/neochatroom.cpp:637
#: src/neochatroom.cpp:650
#, kde-format
msgctxt "[User] removed <name> widget"
msgid "removed %1 widget"
msgstr ""
#: src/neochatroom.cpp:639
#: src/neochatroom.cpp:652
#, kde-format
msgctxt "[User] configured <name> widget"
msgid "configured %1 widget"
msgstr ""
#: src/neochatroom.cpp:641
#: src/neochatroom.cpp:654
#, kde-format
msgid "updated %1 state"
msgstr "oppdaterte %1-tilstand"
#: src/neochatroom.cpp:642
#: src/neochatroom.cpp:655
#, kde-format
msgid "updated %1 state for %2"
msgstr "oppdaterte %1-tilstand for %2"
#: src/neochatroom.cpp:649
#: src/neochatroom.cpp:662
#, kde-format
msgid "Unknown event"
msgstr "Ukjend hending"
#: src/neochatroom.cpp:1141 src/neochatroom.cpp:1142
#: src/neochatroom.cpp:1188 src/neochatroom.cpp:1189
#, kde-format
msgid "Report sent successfully."
msgstr ""
@@ -779,7 +869,7 @@ msgstr "Opna NeoChat i dette rommet"
#: src/notificationsmanager.cpp:77
#: src/qml/Menu/Timeline/FileDelegateContextMenu.qml:50
#: src/qml/Menu/Timeline/MessageDelegateContextMenu.qml:37
#: src/qml/Page/RoomPage.qml:539
#: src/qml/Page/RoomPage.qml:540
#, kde-format
msgid "Reply"
msgstr "Svar"
@@ -816,7 +906,7 @@ msgstr "Vedlegg:"
#: src/qml/Component/ChatBox/AttachmentPane.qml:159
#: src/qml/Menu/Timeline/MessageDelegateContextMenu.qml:28
#: src/qml/Page/ImageEditorPage.qml:20 src/qml/Page/RoomPage.qml:527
#: src/qml/Page/ImageEditorPage.qml:20 src/qml/Page/RoomPage.qml:528
#, kde-format
msgid "Edit"
msgstr "Rediger"
@@ -826,38 +916,38 @@ msgstr "Rediger"
msgid "Cancel sending Image"
msgstr ""
#: src/qml/Component/ChatBox/ChatBar.qml:81
#: src/qml/Component/ChatBox/ChatBar.qml:82
#, kde-format
msgid ""
"This room is encrypted. Sending encrypted messages is not yet supported."
msgstr ""
#: src/qml/Component/ChatBox/ChatBar.qml:81
#: src/qml/Component/ChatBox/ChatBar.qml:82
#, kde-format
msgid "Edit Message"
msgstr "Rediger melding"
#: src/qml/Component/ChatBox/ChatBar.qml:81
#: src/qml/Component/ChatBox/ChatBar.qml:82
#, kde-format
msgid "Send an encrypted message…"
msgstr ""
#: src/qml/Component/ChatBox/ChatBar.qml:81
#: src/qml/Component/ChatBox/ChatBar.qml:82
#, kde-format
msgid "Send a message…"
msgstr ""
#: src/qml/Component/ChatBox/ChatBar.qml:168
#: src/qml/Component/ChatBox/ChatBar.qml:169
#, kde-format
msgid "Attach an image or file"
msgstr "Legg ved bilete eller fil"
#: src/qml/Component/ChatBox/ChatBar.qml:200
#: src/qml/Component/ChatBox/ChatBar.qml:201
#, kde-format
msgid "Add an Emoji"
msgstr "Legg til emoji"
#: src/qml/Component/ChatBox/ChatBar.qml:211
#: src/qml/Component/ChatBox/ChatBar.qml:212
#, kde-format
msgid "Send message"
msgstr "Send melding"
@@ -883,7 +973,7 @@ msgctxt "@action:button"
msgid "Cancel reply"
msgstr ""
#: src/qml/Component/Emoji/EmojiPicker.qml:61
#: src/qml/Component/Emoji/EmojiPicker.qml:46
#, kde-format
msgid "Custom"
msgstr ""
@@ -1117,7 +1207,7 @@ msgctxt "Relative time since the room was last read"
msgid "Last read: %1"
msgstr ""
#: src/qml/Component/Timeline/RichLabel.qml:77
#: src/qml/Component/Timeline/RichLabel.qml:82
#, kde-format
msgid " (edited)"
msgstr ""
@@ -1127,7 +1217,7 @@ msgstr ""
msgid "Video"
msgstr "Video"
#: src/qml/Component/UserInfo.qml:58 src/qml/Settings/AccountsPage.qml:82
#: src/qml/Component/UserInfo.qml:58 src/qml/Settings/AccountsPage.qml:83
#, kde-format
msgid "Add Account"
msgstr ""
@@ -1148,7 +1238,7 @@ msgstr ""
msgid "Edit this account"
msgstr "Rediger kontoen"
#: src/qml/Component/UserInfo.qml:145 src/qml/Settings/AccountsPage.qml:35
#: src/qml/Component/UserInfo.qml:145 src/qml/Settings/AccountsPage.qml:36
#, kde-format
msgid "Account editor"
msgstr ""
@@ -1456,23 +1546,29 @@ msgstr "Kast ut brukaren"
msgid "Ban this user"
msgstr "Utesteng brukaren"
#: src/qml/Dialog/UserDetailDialog.qml:124
#: src/qml/Dialog/UserDetailDialog.qml:116
#, kde-format
msgctxt "@title"
msgid "Ban User"
msgstr ""
#: src/qml/Dialog/UserDetailDialog.qml:127
#, kde-format
msgid "Unban this user"
msgstr ""
#: src/qml/Dialog/UserDetailDialog.qml:137
#: src/qml/Dialog/UserDetailDialog.qml:140
#, kde-format
msgid "Remove recent messages by this user"
msgstr ""
#: src/qml/Dialog/UserDetailDialog.qml:142
#: src/qml/Dialog/UserDetailDialog.qml:145
#, kde-format
msgctxt "@title"
msgid "Remove Messages"
msgstr ""
#: src/qml/Dialog/UserDetailDialog.qml:152
#: src/qml/Dialog/UserDetailDialog.qml:155
#, kde-format
msgid "Open a private chat"
msgstr "Start privat prat"
@@ -1807,6 +1903,30 @@ msgctxt "'Space' is a matrix space"
msgid "Leave Space"
msgstr ""
#: src/qml/Menu/Timeline/BanSheet.qml:16
#, kde-format
msgid "Ban User"
msgstr ""
#: src/qml/Menu/Timeline/BanSheet.qml:20
#, kde-format
msgid "Reason for banning this user"
msgstr ""
#: src/qml/Menu/Timeline/BanSheet.qml:32
#, kde-format
msgctxt "@action:button 'Ban' as in 'Ban this user'"
msgid "Ban"
msgstr ""
#: src/qml/Menu/Timeline/BanSheet.qml:41
#: src/qml/Menu/Timeline/RemoveSheet.qml:47
#: src/qml/Menu/Timeline/ReportSheet.qml:41 src/qml/Page/InviteUserPage.qml:22
#, kde-format
msgctxt "@action"
msgid "Cancel"
msgstr "Avbryt"
#: src/qml/Menu/Timeline/FileDelegateContextMenu.qml:23
#, kde-format
msgid "Open Externally"
@@ -1905,13 +2025,6 @@ msgctxt "@action:button 'Remove' as in 'Remove this message'"
msgid "Remove"
msgstr ""
#: src/qml/Menu/Timeline/RemoveSheet.qml:47
#: src/qml/Menu/Timeline/ReportSheet.qml:41 src/qml/Page/InviteUserPage.qml:22
#, kde-format
msgctxt "@action"
msgid "Cancel"
msgstr "Avbryt"
#: src/qml/Menu/Timeline/ReportSheet.qml:16
#, kde-format
msgid "Report Message"
@@ -2095,7 +2208,12 @@ msgstr "Søk i romkatalogen"
msgid "No Name"
msgstr "Namnlaus"
#: src/qml/Page/RoomListPage.qml:353
#: src/qml/Page/RoomListPage.qml:342
#, kde-format
msgid "Muted room"
msgstr ""
#: src/qml/Page/RoomListPage.qml:362
#, kde-format
msgid "Configure room"
msgstr "Set opp rommet"
@@ -2130,12 +2248,12 @@ msgstr "Gå til første ulesne melding"
msgid "Jump to latest message"
msgstr "Gå til nyaste melding"
#: src/qml/Page/RoomPage.qml:404
#: src/qml/Page/RoomPage.qml:405
#, kde-format
msgid "Drag items here to share them"
msgstr "Dra element her for å dela dei"
#: src/qml/Page/RoomPage.qml:436
#: src/qml/Page/RoomPage.qml:437
#, kde-format
msgctxt "Message displayed when some users are typing"
msgid "%2 is typing"
@@ -2143,12 +2261,12 @@ msgid_plural "%2 are typing"
msgstr[0] "%2 skriv"
msgstr[1] "%2 skriv"
#: src/qml/Page/RoomPage.qml:507
#: src/qml/Page/RoomPage.qml:508
#, kde-format
msgid "This message was sent from a verified device"
msgstr ""
#: src/qml/Page/RoomPage.qml:513
#: src/qml/Page/RoomPage.qml:514
#, kde-format
msgid "React"
msgstr "Reager"
@@ -2316,7 +2434,7 @@ msgstr "Rommet er bytt ut."
msgid "See new room..."
msgstr "Sjå det nye rommet …"
#: src/qml/RoomSettings/General.qml:186 src/qml/RoomSettings/Security.qml:71
#: src/qml/RoomSettings/General.qml:186 src/qml/RoomSettings/Security.qml:118
#: src/qml/Settings/NetworkProxyPage.qml:108
#: src/qml/Settings/SonnetConfigPage.qml:326
#, kde-format
@@ -2379,6 +2497,64 @@ msgctxt "@option:check"
msgid "Anyone can find and join."
msgstr ""
#: src/qml/RoomSettings/Security.qml:68
#, kde-format
msgctxt "@option:check"
msgid "Message history visibility"
msgstr ""
#: src/qml/RoomSettings/Security.qml:71
#, kde-format
msgctxt "@option:check"
msgid "Anyone"
msgstr ""
#: src/qml/RoomSettings/Security.qml:72
#, kde-format
msgctxt "@option:check"
msgid "Anyone, regardless of whether they have joined, can view history."
msgstr ""
#: src/qml/RoomSettings/Security.qml:80
#, kde-format
msgctxt "@option:check"
msgid "Members only"
msgstr ""
#: src/qml/RoomSettings/Security.qml:81
#, kde-format
msgctxt "@option:check"
msgid ""
"All members can view the entire message history, even before they joined."
msgstr ""
#: src/qml/RoomSettings/Security.qml:89
#, kde-format
msgctxt "@option:check"
msgid "Members only (since invite)"
msgstr ""
#: src/qml/RoomSettings/Security.qml:90
#, kde-format
msgctxt "@option:check"
msgid ""
"New members can view the message history from the point they were invited to "
"the room."
msgstr ""
#: src/qml/RoomSettings/Security.qml:98
#, kde-format
msgctxt "@option:check"
msgid "Members only (since joining)"
msgstr ""
#: src/qml/RoomSettings/Security.qml:99
#, kde-format
msgctxt "@option:check"
msgid ""
"New members can view the message history from the point they joined the room."
msgstr ""
#: src/qml/Settings/About.qml:11
#, kde-format
msgctxt "@title:window"
@@ -2467,17 +2643,17 @@ msgstr ""
msgid "Accounts"
msgstr "Kontoar"
#: src/qml/Settings/AccountsPage.qml:99
#: src/qml/Settings/AccountsPage.qml:100
#, kde-format
msgid "Password changed successfully"
msgstr "Passordet er no endra"
#: src/qml/Settings/AccountsPage.qml:101
#: src/qml/Settings/AccountsPage.qml:102
#, kde-format
msgid "Wrong password entered"
msgstr "Du skreiv inn feil passord"
#: src/qml/Settings/AccountsPage.qml:103
#: src/qml/Settings/AccountsPage.qml:104
#, kde-format
msgid "Unknown problem while trying to change password"
msgstr "Ukjent problem ved endring av passord"
@@ -2503,37 +2679,32 @@ msgstr ""
msgid "Compact"
msgstr ""
#: src/qml/Settings/AppearanceSettingsPage.qml:210
#: src/qml/Settings/AppearanceSettingsPage.qml:221
#, kde-format
msgid "Timeline"
msgid "Show fancy effects in chat"
msgstr ""
#: src/qml/Settings/AppearanceSettingsPage.qml:214
#, kde-format
msgid "Show Fancy Effects"
msgstr "Vis fancy effektar"
#: src/qml/Settings/AppearanceSettingsPage.qml:241
#: src/qml/Settings/AppearanceSettingsPage.qml:235
#, kde-format
msgid "Use transparent chat page"
msgstr ""
#: src/qml/Settings/AppearanceSettingsPage.qml:259
#: src/qml/Settings/AppearanceSettingsPage.qml:254
#, kde-format
msgid "Transparency"
msgstr ""
#: src/qml/Settings/AppearanceSettingsPage.qml:276
#: src/qml/Settings/AppearanceSettingsPage.qml:271
#, kde-format
msgid "Only enabled if the transparent chat page is enabled."
msgstr ""
#: src/qml/Settings/AppearanceSettingsPage.qml:289
#: src/qml/Settings/AppearanceSettingsPage.qml:284
#, kde-format
msgid "Show your messages on the right"
msgstr ""
#: src/qml/Settings/AppearanceSettingsPage.qml:302
#: src/qml/Settings/AppearanceSettingsPage.qml:297
#, kde-format
msgid "Show links preview in the chat messages"
msgstr ""
@@ -2545,17 +2716,17 @@ msgstr ""
#: src/qml/Settings/AppearanceSettingsPage.qml:318
#, kde-format
msgid "In Chat"
msgid "In chat"
msgstr ""
#: src/qml/Settings/AppearanceSettingsPage.qml:328
#, kde-format
msgid "In Sidebar"
msgid "In sidebar"
msgstr ""
#: src/qml/Settings/ColorScheme.qml:15
#, kde-format
msgid "Themes"
msgid "Color theme"
msgstr ""
#: src/qml/Settings/DevicesPage.qml:14 src/qml/Settings/DevicesPage.qml:26
@@ -2569,32 +2740,42 @@ msgstr "Einingar"
msgid "New device name"
msgstr ""
#: src/qml/Settings/DevicesPage.qml:114
#: src/qml/Settings/DevicesPage.qml:95
#, kde-format
msgid "Cancel editing display name"
msgstr ""
#: src/qml/Settings/DevicesPage.qml:102
#, kde-format
msgid "Confirm new display name"
msgstr ""
#: src/qml/Settings/DevicesPage.qml:117
#, kde-format
msgid "Edit device name"
msgstr "Rediger einingsnamn"
#: src/qml/Settings/DevicesPage.qml:123
#: src/qml/Settings/DevicesPage.qml:131
#, kde-format
msgid "Verify device"
msgstr ""
#: src/qml/Settings/DevicesPage.qml:133
#: src/qml/Settings/DevicesPage.qml:146
#, kde-format
msgid "Logout device"
msgstr "Logg ut av eininga"
#: src/qml/Settings/DevicesPage.qml:153
#: src/qml/Settings/DevicesPage.qml:170
#, kde-format
msgid "Remove device"
msgstr "Fjern eininga"
#: src/qml/Settings/DevicesPage.qml:157
#: src/qml/Settings/DevicesPage.qml:174
#, kde-format
msgid "Password:"
msgstr "Passord:"
#: src/qml/Settings/DevicesPage.qml:161
#: src/qml/Settings/DevicesPage.qml:178
#, kde-format
msgid "Confirm"
msgstr "Stadfest"
@@ -2620,6 +2801,11 @@ msgstr ""
msgid "Add Emoji..."
msgstr ""
#: src/qml/Settings/Emoticons.qml:113
#, kde-format
msgid "Images (*.png *.gif *.webp)"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:15
#: src/qml/Settings/NetworkProxyPage.qml:14
#, kde-format
@@ -2632,80 +2818,80 @@ msgstr ""
msgid "General settings"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:30
#: src/qml/Settings/GeneralSettingsPage.qml:31
#, kde-format
msgid "Close to system tray"
msgstr "Minimer til systemtrauet"
#: src/qml/Settings/GeneralSettingsPage.qml:44
#: src/qml/Settings/GeneralSettingsPage.qml:45
#, kde-format
msgid "Minimize to system tray on startup"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:58
#: src/qml/Settings/GeneralSettingsPage.qml:59
#, kde-format
msgid "Automatically hide/unhide the room information when resizing the window"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:76
#: src/qml/Settings/GeneralSettingsPage.qml:77
#, kde-format
msgid "Timeline Events"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:81
#: src/qml/Settings/GeneralSettingsPage.qml:82
#, kde-format
msgid "Show leave and join events"
msgstr "Vis når personar kjem eller går"
#: src/qml/Settings/GeneralSettingsPage.qml:94
#: src/qml/Settings/GeneralSettingsPage.qml:95
#, kde-format
msgid "Show name change events"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:107
#: src/qml/Settings/GeneralSettingsPage.qml:108
#, kde-format
msgid "Show avatar update events"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:124
#: src/qml/Settings/GeneralSettingsPage.qml:125
#, kde-format
msgid "Rooms and private chats"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:127
#: src/qml/Settings/GeneralSettingsPage.qml:128
#, kde-format
msgid "Separated"
msgstr "Skilde"
#: src/qml/Settings/GeneralSettingsPage.qml:136
#: src/qml/Settings/GeneralSettingsPage.qml:137
#, kde-format
msgid "Intermixed"
msgstr "Blanda"
#: src/qml/Settings/GeneralSettingsPage.qml:153
#: src/qml/Settings/GeneralSettingsPage.qml:154
#, kde-format
msgctxt "Chat Editor"
msgid "Editor:"
msgid "Editor"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:157
#: src/qml/Settings/GeneralSettingsPage.qml:158
#, kde-format
msgid "Use s/text/replacement syntax to edit your last message"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:168
#: src/qml/Settings/GeneralSettingsPage.qml:169
#, kde-format
msgid "Send Typing Notifications"
msgid "Send typing notifications"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:185
#: src/qml/Settings/GeneralSettingsPage.qml:186
#, kde-format
msgid "Developer Settings"
msgstr ""
#: src/qml/Settings/GeneralSettingsPage.qml:188
#: src/qml/Settings/GeneralSettingsPage.qml:189
#, kde-format
msgid "Enable Developer Tools"
msgid "Enable developer tools"
msgstr ""
#: src/qml/Settings/GlobalNotificationsPage.qml:14

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

@@ -165,6 +165,8 @@ if(ANDROID)
"download"
"smiley"
"tools-check-spelling"
"username-copy"
"edit-copy"
)
else()
target_link_libraries(neochat PUBLIC Qt::Widgets KF5::KIOWidgets)

View File

@@ -139,6 +139,10 @@ void ActionsHandler::handleMessage()
handledText = CustomEmojiModel::instance().preprocessText(handledText);
handledText = markdownToHTML(handledText);
if (handledText.count("<p>") == 1 && handledText.count("</p>") == 1) {
handledText.remove("<p>");
handledText.remove("</p>");
}
if (handledText.length() == 0) {
return;

View File

@@ -7,7 +7,8 @@
#include <events/roommessageevent.h>
class NeoChatRoom;
#include "neochatroom.h"
class CustomEmojiModel;
class NeoChatRoom;

View File

@@ -6,6 +6,7 @@
#include "controller.h"
#include "neochatroom.h"
#include "neochatuser.h"
#include "roommanager.h"
#include <events/roommemberevent.h>
#include <events/roompowerlevelsevent.h>
@@ -193,8 +194,9 @@ QVector<ActionsModel::Action> actions{
i18nc("'<text>' does not look like a room id or alias.", "'%1' does not look like a room id or alias.", text));
return QString();
}
if (Controller::instance().activeConnection()->room(text) || Controller::instance().activeConnection()->roomByAlias(text)) {
Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("You are already in room <roomname>.", "You are already in room %1.", text));
auto targetRoom = text.startsWith(QLatin1Char('!')) ? room->connection()->room(text) : room->connection()->roomByAlias(text);
if (targetRoom) {
RoomManager::instance().enterRoom(dynamic_cast<NeoChatRoom *>(targetRoom));
return QString();
}
Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("Joining room <roomname>.", "Joining room %1.", text));

View File

@@ -135,7 +135,11 @@ int ChatDocumentHandler::completionStartIndex() const
return 0;
}
const auto &cursor = cursorPosition();
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
const long long cursor = cursorPosition();
#else
const auto cursor = cursorPosition();
#endif
const auto &text = m_room->chatBoxText();
auto start = std::min(cursor, text.size()) - 1;
while (start > -1) {
@@ -199,7 +203,7 @@ void ChatDocumentHandler::setRoom(NeoChatRoom *room)
void ChatDocumentHandler::complete(int index)
{
if (m_completionModel->autoCompletionType() == ChatDocumentHandler::User) {
if (m_completionModel->autoCompletionType() == CompletionModel::User) {
auto name = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Text).toString();
auto id = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
auto text = m_room->chatBoxText();
@@ -213,7 +217,7 @@ void ChatDocumentHandler::complete(int index)
cursor.setKeepPositionOnInsert(true);
m_room->mentions()->push_back({cursor, name, 0, 0, id});
m_highlighter->rehighlight();
} else if (m_completionModel->autoCompletionType() == ChatDocumentHandler::Command) {
} else if (m_completionModel->autoCompletionType() == CompletionModel::Command) {
auto command = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
auto text = m_room->chatBoxText();
auto at = text.lastIndexOf(QLatin1Char('/'));
@@ -221,7 +225,7 @@ void ChatDocumentHandler::complete(int index)
cursor.setPosition(at);
cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor);
cursor.insertText(QStringLiteral("/%1 ").arg(command));
} else if (m_completionModel->autoCompletionType() == ChatDocumentHandler::Room) {
} else if (m_completionModel->autoCompletionType() == CompletionModel::Room) {
auto alias = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
auto text = m_room->chatBoxText();
auto at = text.lastIndexOf(QLatin1Char('#'), cursorPosition() - 1);
@@ -234,7 +238,7 @@ void ChatDocumentHandler::complete(int index)
cursor.setKeepPositionOnInsert(true);
m_room->mentions()->push_back({cursor, alias, 0, 0, alias});
m_highlighter->rehighlight();
} else if (m_completionModel->autoCompletionType() == ChatDocumentHandler::Emoji) {
} else if (m_completionModel->autoCompletionType() == CompletionModel::Emoji) {
auto shortcode = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
auto text = m_room->chatBoxText();
auto at = text.lastIndexOf(QLatin1Char(':'));

View File

@@ -4,16 +4,15 @@
#pragma once
#include <QObject>
#include <QQuickTextDocument>
#include <QTextCursor>
#include "completionmodel.h"
#include "userlistmodel.h"
class QTextDocument;
class QQuickTextDocument;
class NeoChatRoom;
class SyntaxHighlighter;
class CompletionModel;
class ChatDocumentHandler : public QObject
{
@@ -28,15 +27,6 @@ class ChatDocumentHandler : public QObject
Q_PROPERTY(NeoChatRoom *room READ room NOTIFY roomChanged)
public:
enum AutoCompletionType {
User,
Room,
Emoji,
Command,
None,
};
Q_ENUM(AutoCompletionType)
explicit ChatDocumentHandler(QObject *parent = nullptr);
[[nodiscard]] QQuickTextDocument *document() const;
@@ -80,9 +70,7 @@ private:
SyntaxHighlighter *m_highlighter = nullptr;
AutoCompletionType m_completionType = None;
CompletionModel::AutoCompletionType m_completionType = CompletionModel::None;
CompletionModel *m_completionModel = nullptr;
};
Q_DECLARE_METATYPE(ChatDocumentHandler::AutoCompletionType);

View File

@@ -42,7 +42,7 @@ void CompletionModel::setText(const QString &text, const QString &fullText)
int CompletionModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
if (m_autoCompletionType == ChatDocumentHandler::None) {
if (m_autoCompletionType == None) {
return 0;
}
return m_filterModel->rowCount();
@@ -54,7 +54,7 @@ QVariant CompletionModel::data(const QModelIndex &index, int role) const
return {};
}
auto filterIndex = m_filterModel->index(index.row(), 0);
if (m_autoCompletionType == ChatDocumentHandler::User) {
if (m_autoCompletionType == User) {
if (role == Text) {
return m_filterModel->data(filterIndex, UserListModel::NameRole);
}
@@ -66,7 +66,7 @@ QVariant CompletionModel::data(const QModelIndex &index, int role) const
}
}
if (m_autoCompletionType == ChatDocumentHandler::Command) {
if (m_autoCompletionType == Command) {
if (role == Text) {
return m_filterModel->data(filterIndex, ActionsModel::Prefix).toString() + QStringLiteral(" ")
+ m_filterModel->data(filterIndex, ActionsModel::Parameters).toString();
@@ -81,7 +81,7 @@ QVariant CompletionModel::data(const QModelIndex &index, int role) const
return m_filterModel->data(filterIndex, ActionsModel::Prefix);
}
}
if (m_autoCompletionType == ChatDocumentHandler::Room) {
if (m_autoCompletionType == Room) {
if (role == Text) {
return m_filterModel->data(filterIndex, RoomListModel::DisplayNameRole);
}
@@ -92,7 +92,7 @@ QVariant CompletionModel::data(const QModelIndex &index, int role) const
return m_filterModel->data(filterIndex, RoomListModel::AvatarRole);
}
}
if (m_autoCompletionType == ChatDocumentHandler::Emoji) {
if (m_autoCompletionType == Emoji) {
if (role == Text) {
return m_filterModel->data(filterIndex, CustomEmojiModel::DisplayRole);
}
@@ -125,7 +125,7 @@ void CompletionModel::updateCompletion()
m_filterModel->setSecondaryFilterRole(UserListModel::NameRole);
m_filterModel->setFullText(m_fullText);
m_filterModel->setFilterText(m_text);
m_autoCompletionType = ChatDocumentHandler::User;
m_autoCompletionType = User;
m_filterModel->invalidate();
} else if (text().startsWith(QLatin1Char('/'))) {
m_filterModel->setSourceModel(&ActionsModel::instance());
@@ -133,10 +133,10 @@ void CompletionModel::updateCompletion()
m_filterModel->setSecondaryFilterRole(-1);
m_filterModel->setFullText(m_fullText);
m_filterModel->setFilterText(m_text.mid(1));
m_autoCompletionType = ChatDocumentHandler::Command;
m_autoCompletionType = Command;
m_filterModel->invalidate();
} else if (text().startsWith(QLatin1Char('#'))) {
m_autoCompletionType = ChatDocumentHandler::Room;
m_autoCompletionType = Room;
m_filterModel->setSourceModel(m_roomListModel);
m_filterModel->setFilterRole(RoomListModel::CanonicalAliasRole);
m_filterModel->setSecondaryFilterRole(RoomListModel::DisplayNameRole);
@@ -146,15 +146,15 @@ void CompletionModel::updateCompletion()
} else if (text().startsWith(QLatin1Char(':'))
&& (m_fullText.indexOf(QLatin1Char(':'), 1) == -1
|| (m_fullText.indexOf(QLatin1Char(' ')) != -1 && m_fullText.indexOf(QLatin1Char(':'), 1) > m_fullText.indexOf(QLatin1Char(' '), 1)))) {
m_autoCompletionType = ChatDocumentHandler::Emoji;
m_filterModel->setSourceModel(m_emojiModel);
m_autoCompletionType = Emoji;
m_filterModel->setFilterRole(CustomEmojiModel::Name);
m_filterModel->setSecondaryFilterRole(-1);
m_filterModel->setFullText(m_fullText);
m_filterModel->setFilterText(m_text);
m_filterModel->invalidate();
} else {
m_autoCompletionType = ChatDocumentHandler::None;
m_autoCompletionType = None;
}
beginResetModel();
endResetModel();
@@ -171,12 +171,12 @@ void CompletionModel::setRoom(NeoChatRoom *room)
Q_EMIT roomChanged();
}
ChatDocumentHandler::AutoCompletionType CompletionModel::autoCompletionType() const
CompletionModel::AutoCompletionType CompletionModel::autoCompletionType() const
{
return m_autoCompletionType;
}
void CompletionModel::setAutoCompletionType(ChatDocumentHandler::AutoCompletionType autoCompletionType)
void CompletionModel::setAutoCompletionType(AutoCompletionType autoCompletionType)
{
m_autoCompletionType = autoCompletionType;
Q_EMIT autoCompletionTypeChanged();

View File

@@ -7,7 +7,7 @@
#include <KConcatenateRowsProxyModel>
#include "chatdocumenthandler.h"
#include "roomlistmodel.h"
class CompletionProxyModel;
class UserListModel;
@@ -19,10 +19,19 @@ class CompletionModel : public QAbstractListModel
Q_OBJECT
Q_PROPERTY(QString text READ text NOTIFY textChanged)
Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged)
Q_PROPERTY(ChatDocumentHandler::AutoCompletionType autoCompletionType READ autoCompletionType NOTIFY autoCompletionTypeChanged);
Q_PROPERTY(AutoCompletionType autoCompletionType READ autoCompletionType NOTIFY autoCompletionTypeChanged);
Q_PROPERTY(RoomListModel *roomListModel READ roomListModel WRITE setRoomListModel NOTIFY roomListModelChanged);
public:
enum AutoCompletionType {
User,
Room,
Emoji,
Command,
None,
};
Q_ENUM(AutoCompletionType)
enum Roles {
Text = Qt::DisplayRole,
Subtitle,
@@ -47,7 +56,7 @@ public:
RoomListModel *roomListModel() const;
void setRoomListModel(RoomListModel *roomListModel);
ChatDocumentHandler::AutoCompletionType autoCompletionType() const;
AutoCompletionType autoCompletionType() const;
Q_SIGNALS:
void textChanged();
@@ -60,11 +69,12 @@ private:
QString m_fullText;
CompletionProxyModel *m_filterModel;
NeoChatRoom *m_room = nullptr;
ChatDocumentHandler::AutoCompletionType m_autoCompletionType = ChatDocumentHandler::None;
AutoCompletionType m_autoCompletionType = None;
void setAutoCompletionType(ChatDocumentHandler::AutoCompletionType autoCompletionType);
void setAutoCompletionType(AutoCompletionType autoCompletionType);
UserListModel *m_userListModel;
RoomListModel *m_roomListModel;
KConcatenateRowsProxyModel *m_emojiModel;
};
Q_DECLARE_METATYPE(CompletionModel::AutoCompletionType);

View File

@@ -18,7 +18,11 @@ bool CompletionProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &so
&& sourceModel()
->data(sourceModel()->index(sourceRow, 0), secondaryFilterRole())
.toString()
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
.startsWith(QStringView(m_filterText).sliced(1), Qt::CaseInsensitive));
#else
.startsWith(m_filterText.midRef(1), Qt::CaseInsensitive));
#endif
}
int CompletionProxyModel::secondaryFilterRole() const

View File

@@ -234,13 +234,6 @@ void Controller::showWindow()
WindowController::instance().showAndRaiseWindow(QString());
}
inline QString accessTokenFileName(const AccountSettings &account)
{
QString fileName = account.userId();
fileName.replace(':', '_');
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + '/' + fileName;
}
void Controller::loginWithAccessToken(const QString &serverAddr, const QString &user, const QString &token, const QString &deviceName)
{
if (user.isEmpty() || token.isEmpty()) {
@@ -281,7 +274,6 @@ void Controller::logout(Connection *conn, bool serverSideLogout)
}
SettingsGroup("Accounts").remove(conn->userId());
QFile(accessTokenFileName(AccountSettings(conn->userId()))).remove();
QKeychain::DeletePasswordJob job(qAppName());
job.setAutoDelete(true);
@@ -374,15 +366,7 @@ void Controller::invokeLogin()
if (accessTokenLoadingJob->error() == QKeychain::Error::NoError) {
accessToken = accessTokenLoadingJob->binaryData();
} else {
// No access token from the keychain, try token file
// TODO FIXME this code is racy since the file might have
// already been removed. But since the other code do a blocking
// dbus call, the probability are not high that it will happen.
// loadAccessTokenFromFile is also mostly legacy nowadays
accessToken = loadAccessTokenFromFile(account);
if (accessToken.isEmpty()) {
return;
}
return;
}
auto connection = new Connection(account.homeserver());
@@ -416,21 +400,6 @@ void Controller::invokeLogin()
}
}
QByteArray Controller::loadAccessTokenFromFile(const AccountSettings &account)
{
QFile accountTokenFile{accessTokenFileName(account)};
if (accountTokenFile.open(QFile::ReadOnly)) {
if (accountTokenFile.size() < 1024) {
return accountTokenFile.readAll();
}
qWarning() << "File" << accountTokenFile.fileName() << "is" << accountTokenFile.size() << "bytes long - too long for a token, ignoring it.";
}
qWarning() << "Could not open access token file" << accountTokenFile.fileName();
return {};
}
QKeychain::ReadPasswordJob *Controller::loadAccessTokenFromKeyChain(const AccountSettings &account)
{
qDebug() << "Reading access token from the keychain for" << account.userId();
@@ -442,24 +411,6 @@ QKeychain::ReadPasswordJob *Controller::loadAccessTokenFromKeyChain(const Accoun
if (job->error() == QKeychain::Error::NoError) {
return;
}
if (job->error() == QKeychain::Error::EntryNotFound) {
// no access token from the keychain, try token file
auto accessToken = loadAccessTokenFromFile(account);
if (!accessToken.isEmpty()) {
qDebug() << "Migrating the access token from file to the keychain for " << account.userId();
bool removed = false;
bool saved = saveAccessTokenToKeyChain(account, accessToken);
if (saved) {
QFile accountTokenFile{accessTokenFileName(account)};
removed = accountTokenFile.remove();
}
if (!(saved && removed)) {
qDebug() << "Migrating the access token from the file to the keychain "
"failed";
}
return;
}
}
switch (job->error()) {
case QKeychain::EntryNotFound:
@@ -484,22 +435,6 @@ QKeychain::ReadPasswordJob *Controller::loadAccessTokenFromKeyChain(const Accoun
return job;
}
bool Controller::saveAccessTokenToFile(const AccountSettings &account, const QByteArray &accessToken)
{
// (Re-)Make a dedicated file for access_token.
QFile accountTokenFile{accessTokenFileName(account)};
accountTokenFile.remove(); // Just in case
auto fileDir = QFileInfo(accountTokenFile).dir();
if (!((fileDir.exists() || fileDir.mkpath(".")) && accountTokenFile.open(QFile::WriteOnly))) {
Q_EMIT errorOccured("I/O Denied: Cannot save access token.");
} else {
accountTokenFile.write(accessToken);
return true;
}
return false;
}
bool Controller::saveAccessTokenToKeyChain(const AccountSettings &account, const QByteArray &accessToken)
{
qDebug() << "Save the access token to the keychain for " << account.userId();
@@ -514,7 +449,7 @@ bool Controller::saveAccessTokenToKeyChain(const AccountSettings &account, const
if (job.error()) {
qWarning() << "Could not save access token to the keychain: " << qPrintable(job.errorString());
return saveAccessTokenToFile(account, accessToken);
return false;
}
return true;
}

View File

@@ -68,7 +68,6 @@ public:
[[nodiscard]] bool supportSystemTray() const;
bool saveAccessTokenToFile(const Quotient::AccountSettings &account, const QByteArray &accessToken);
bool saveAccessTokenToKeyChain(const Quotient::AccountSettings &account, const QByteArray &accessToken);
int activeConnectionIndex() const;
@@ -111,7 +110,6 @@ private:
bool m_busy = false;
TrayIcon *m_trayIcon = nullptr;
static QByteArray loadAccessTokenFromFile(const Quotient::AccountSettings &account);
QKeychain::ReadPasswordJob *loadAccessTokenFromKeyChain(const Quotient::AccountSettings &account);
void loadSettings();

View File

@@ -158,8 +158,8 @@ void Login::login()
// Some servers do not have a .well_known file. So we login via the username part from the mxid,
// rather than with the full mxid, as that would lead to an invalid user.
QStringRef username(&m_matrixId, 1, m_matrixId.indexOf(":") - 1);
m_connection->loginWithPassword(username.toString(), m_password, m_deviceName, QString());
auto username = m_matrixId.mid(1, m_matrixId.indexOf(":") - 1);
m_connection->loginWithPassword(username, m_password, m_deviceName, QString());
}
bool Login::supportsPassword() const

View File

@@ -66,6 +66,7 @@ QHash<int, QByteArray> MessageEventModel::roleNames() const
roles[AuthorDisplayNameRole] = "authorDisplayName";
roles[IsNameChangeRole] = "isNameChange";
roles[IsAvatarChangeRole] = "isAvatarChange";
roles[IsRedactedRole] = "isRedacted";
return roles;
}
@@ -894,6 +895,9 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
}
return false;
}
if (role == IsRedactedRole) {
return evt.isRedacted();
}
return {};
}

View File

@@ -71,6 +71,7 @@ public:
AuthorDisplayNameRole,
IsNameChangeRole,
IsAvatarChangeRole,
IsRedactedRole,
LastRole, // Keep this last
};
Q_ENUM(EventRoles)

View File

@@ -25,6 +25,10 @@ MessageFilterModel::MessageFilterModel(QObject *parent)
beginResetModel();
endResetModel();
});
connect(NeoChatConfig::self(), &NeoChatConfig::ShowDeletedMessagesChanged, this, [this] {
beginResetModel();
endResetModel();
});
}
bool MessageFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
@@ -39,12 +43,15 @@ bool MessageFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sour
if (index.data(MessageEventModel::IsAvatarChangeRole).toBool() && !NeoChatConfig::self()->showAvatarUpdate()) {
return false;
}
if (index.data(MessageEventModel::IsRedactedRole).toBool() && !NeoChatConfig::self()->showDeletedMessages()) {
return false;
}
if (specialMarks == EventStatus::Hidden || specialMarks == EventStatus::Replaced) {
return false;
}
const QString eventType = index.data(MessageEventModel::EventTypeRole).toString();
const auto eventType = index.data(MessageEventModel::EventTypeRole).toInt();
if (eventType == MessageEventModel::Other) {
return false;

View File

@@ -62,6 +62,9 @@
<label>Enable developer tools</label>
<default>false</default>
</entry>
<entry name="LastSaveDirectory" type="String">
<label>Directory last used for saving a file</label>
</entry>
</group>
<group name="Timeline">
<entry name="ShowAvatarInTimeline" type="bool">
@@ -80,6 +83,10 @@
<label>Show avatar update events in the timeline</label>
<default>true</default>
</entry>
<entry name="ShowDeletedMessages" type="bool">
<label>Show deleted messages in the timeline</label>
<default>true</default>
</entry>
<entry name="ShowLinkPreview" type="bool">
<label>Show preview of the links in the chat messages</label>
</entry>

View File

@@ -17,6 +17,7 @@
#include <qcoro/task.h>
#include <connection.h>
#include <csapi/directory.h>
#include <csapi/pushrules.h>
#include <csapi/redaction.h>
#include <csapi/report_content.h>
@@ -473,13 +474,6 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
auto base = url.scheme() + QStringLiteral("://") + url.host() + (url.port() != -1 ? ':' + QString::number(url.port()) : QString());
htmlBody.replace(utils::mxcImageRegExp, QStringLiteral(R"(<img \1 src="%1/_matrix/media/r0/download/\2/\3" \4 > )").arg(base));
if (e.msgtype() == MessageEventType::Emote) {
auto author = static_cast<NeoChatUser *>(user(e.senderId()));
int firstPara = htmlBody.indexOf("<p>");
htmlBody.insert(firstPara == -1 ? 0 : firstPara + 3,
"* <a href='https://matrix.to/#/" + author->id() + "' style='color: " + author->color().name() + "'>"
+ author->displayname(this) + "</a> ");
}
return htmlBody;
}
@@ -501,18 +495,14 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
plainBody = e.plainBody();
}
if (removeReply) {
plainBody = plainBody.remove(utils::removeReplyRegex);
}
if (prettyPrint) {
plainBody = Quotient::prettyPrint(plainBody);
if (removeReply) {
plainBody.remove(utils::removeReplyRegex);
}
return Quotient::prettyPrint(plainBody);
}
if (e.msgtype() == MessageEventType::Emote) {
auto author = static_cast<NeoChatUser *>(user(e.senderId()));
plainBody.remove("/me");
plainBody.insert(0,
"* <a href='https://matrix.to/#/" + author->id() + "' style='color: " + author->color().name() + "'>"
+ author->displayname(this) + "</a> ");
if (removeReply) {
return plainBody.remove(utils::removeReplyRegex);
}
return plainBody;
},
@@ -1335,3 +1325,46 @@ void NeoChatRoom::download(const QString &eventId, const QUrl &localFilename)
job->start();
#endif
}
void NeoChatRoom::mapAlias(const QString &alias)
{
auto getLocalAliasesJob = connection()->callApi<GetLocalAliasesJob>(id());
connect(getLocalAliasesJob, &BaseJob::success, this, [this, getLocalAliasesJob, alias] {
if (getLocalAliasesJob->aliases().contains(alias)) {
return;
} else {
auto setRoomAliasJob = connection()->callApi<SetRoomAliasJob>(alias, id());
connect(setRoomAliasJob, &BaseJob::success, this, [this, alias] {
auto newAltAliases = altAliases();
newAltAliases.append(alias);
setLocalAliases(newAltAliases);
});
}
});
}
void NeoChatRoom::unmapAlias(const QString &alias)
{
connection()->callApi<DeleteRoomAliasJob>(alias);
}
void NeoChatRoom::setCanonicalAlias(const QString &newAlias)
{
QString oldCanonicalAlias = canonicalAlias();
Room::setCanonicalAlias(newAlias);
connect(this, &Room::namesChanged, this, [this, newAlias, oldCanonicalAlias] {
if (canonicalAlias() == newAlias) {
// If the new canonical alias is already a published alt alias remove it otherwise it will be in both lists.
// The server doesn't prevent this so we need to handle it.
auto newAltAliases = altAliases();
if (!oldCanonicalAlias.isEmpty()) {
newAltAliases.append(oldCanonicalAlias);
}
if (newAltAliases.contains(newAlias)) {
newAltAliases.removeAll(newAlias);
Room::setLocalAliases(newAltAliases);
}
}
});
}

View File

@@ -3,6 +3,7 @@
#pragma once
#include <qobjectdefs.h>
#include <room.h>
#include <QCache>
@@ -201,6 +202,16 @@ public:
Q_INVOKABLE bool downloadTempFile(const QString &eventId);
/*
* Map an alias to the room
*
* Note: this is different to setLocalAliases as that can only
* get the room to publish and alias that is already mapped.
*/
Q_INVOKABLE void mapAlias(const QString &alias);
Q_INVOKABLE void unmapAlias(const QString &alias);
Q_INVOKABLE void setCanonicalAlias(const QString &newAlias);
#ifdef QUOTIENT_07
Q_INVOKABLE PollHandler *poll(const QString &eventId);
#endif

View File

@@ -137,6 +137,9 @@ QQC2.ToolBar {
completionMenu.decrementIndex()
} else if (event.key === Qt.Key_Down && completionMenu.visible) {
completionMenu.incrementIndex()
} else if (event.key === Qt.Key_Backspace && inputField.text.length <= 1) {
currentRoom.sendTypingNotification(false)
repeatTimer.stop()
}
}
@@ -147,10 +150,10 @@ QQC2.ToolBar {
onTextChanged: {
if (!repeatTimer.running && Config.typingNotifications) {
currentRoom.sendTypingNotification(true)
var textExists = text.length > 0
currentRoom.sendTypingNotification(textExists)
textExists ? repeatTimer.start() : repeatTimer.stop()
}
repeatTimer.start()
currentRoom.chatBoxText = text
}
}
@@ -267,7 +270,7 @@ QQC2.ToolBar {
function postMessage() {
actionsHandler.handleMessage();
repeatTimer.stop()
currentRoom.markAllMessagesAsRead();
inputField.clear();
currentRoom.chatBoxReplyId = "";

View File

@@ -293,8 +293,10 @@ QQC2.Popup {
id: saveAsDialog
FileDialog {
fileMode: FileDialog.SaveFile
folder: StandardPaths.writableLocation(StandardPaths.DownloadLocation)
folder: Config.lastSaveDirectory.length > 0 ? Config.lastSaveDirectory : StandardPaths.writableLocation(StandardPaths.DownloadLocation)
onAccepted: {
Config.lastSaveDirectory = folder
Config.save()
if (!currentFile) {
return;
}

View File

@@ -5,23 +5,15 @@ import QtQuick 2.15
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.15 as Kirigami
import org.kde.kirigami 2.20 as Kirigami
import org.kde.neochat 1.0
Kirigami.PlaceholderMessage {
Kirigami.LoadingPlaceholder {
property var showContinueButton: false
property var showBackButton: false
property string title: i18n("Loading…")
anchors.centerIn: parent
QQC2.Label {
text: i18n("Please wait. This might take a little while.")
}
QQC2.BusyIndicator {
Layout.alignment: Qt.AlignHCenter
running: false
}
}

View File

@@ -159,11 +159,15 @@ TimelineContainer {
FileDialog {
fileMode: FileDialog.SaveFile
folder: StandardPaths.writableLocation(StandardPaths.DownloadLocation)
onAccepted: if (autoOpenFile) {
UrlHelper.copyTo(progressInfo.localPath, file)
} else {
currentRoom.download(eventId, file);
folder: Config.lastSaveDirectory.length > 0 ? Config.lastSaveDirectory : StandardPaths.writableLocation(StandardPaths.DownloadLocation)
onAccepted: {
Config.lastSaveDirectory = folder
Config.save()
if (autoOpenFile) {
UrlHelper.copyTo(progressInfo.localPath, file)
} else {
currentRoom.download(eventId, file);
}
}
}
}

View File

@@ -75,7 +75,7 @@ a{
background: " + Kirigami.Theme.textColor + ";
}
" : "") + "
</style>" + textMessage + (isEdited && !contentLabel.isReplyLabel ? (" <span style=\"color: " + Kirigami.Theme.disabledTextColor + "\">" + "<span style='font-size: " + Kirigami.Theme.defaultFont.pixelSize +"px'>" + i18n(" (edited)") + "</span>") : "")
</style>" + (isEmote ? "* <a href='https://matrix.to/#/" + author.id + "' style='color: " + author.color + "'>" + author.displayName + "</a> " : "") + textMessage + (isEdited && !contentLabel.isReplyLabel ? (" <span style=\"color: " + Kirigami.Theme.disabledTextColor + "\">" + "<span style='font-size: " + Kirigami.Theme.defaultFont.pixelSize +"px'>" + i18n(" (edited)") + "</span>") : "")
color: Kirigami.Theme.textColor
selectedTextColor: Kirigami.Theme.highlightedTextColor

View File

@@ -160,6 +160,15 @@ Kirigami.OverlaySheet {
}
}
}
Kirigami.BasicListItem {
action: Kirigami.Action {
text: i18n("Copy link")
icon.name: "username-copy"
onTriggered: {
Clipboard.saveText("https://matrix.to/#/" + user.id)
}
}
}
Component {
id: fullScreenImage

View File

@@ -113,11 +113,13 @@ MessageDelegateContextMenu {
id: saveAsDialog
FileDialog {
fileMode: FileDialog.SaveFile
folder: StandardPaths.writableLocation(StandardPaths.DownloadLocation)
folder: Config.lastSaveDirectory.length > 0 ? Config.lastSaveDirectory : StandardPaths.writableLocation(StandardPaths.DownloadLocation)
onAccepted: {
if (!currentFile) {
return;
}
Config.lastSaveDirectory = folder
Config.save()
currentRoom.downloadFile(eventId, currentFile)
}
}

View File

@@ -76,6 +76,13 @@ Loader {
width: Kirigami.Units.gridUnit * 25
});
}
},
Kirigami.Action {
text: i18n("Copy Link")
icon.name: "edit-copy"
onTriggered: {
Clipboard.saveText("https://matrix.to/#/" + currentRoom.id + "/" + loadRoot.eventId)
}
}
]
@@ -143,6 +150,7 @@ Loader {
QQC2.MenuItem {
text: i18n("Configure Web Shortcuts...")
icon.name: "configure"
visible: !Controller.isFlatpak
onTriggered: webshortcutmodel.configureWebShortcuts()
}
}

View File

@@ -348,6 +348,7 @@ Kirigami.ScrollablePage {
visible: currentRoom && currentRoom.hasUnreadMessages && currentRoom.readMarkerLoaded
action: Kirigami.Action {
onTriggered: {
chatBox.focusInputField();
messageListView.goToEvent(currentRoom.readMarkerEventId)
}
icon.name: "go-up"
@@ -360,7 +361,7 @@ Kirigami.ScrollablePage {
QQC2.RoundButton {
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: Kirigami.Units.largeSpacing + messageListView.headerItem.height
anchors.bottomMargin: Kirigami.Units.largeSpacing
anchors.rightMargin: Kirigami.Units.largeSpacing
implicitWidth: Kirigami.Units.gridUnit * 2
implicitHeight: Kirigami.Units.gridUnit * 2
@@ -371,6 +372,7 @@ Kirigami.ScrollablePage {
visible: !messageListView.atYEnd
action: Kirigami.Action {
onTriggered: {
chatBox.focusInputField();
goToLastMessage();
currentRoom.markAllMessagesAsRead();
}

View File

@@ -195,7 +195,7 @@ Kirigami.OverlayDrawer {
Layout.preferredWidth: Kirigami.Units.gridUnit * 3.5
Layout.preferredHeight: Kirigami.Units.gridUnit * 3.5
name: room ? room.name : i18n("No name")
name: room ? room.displayName : ""
source: room ? ("image://mxc/" + room.avatarMediaId) : ""
}

View File

@@ -5,7 +5,9 @@
import QtQuick 2.15
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.15 as Kirigami
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
import org.kde.neochat 1.0
@@ -14,108 +16,202 @@ Kirigami.ScrollablePage {
property var room
readonly property bool canChangeAvatar: room.canSendState("m.room.avatar")
readonly property bool canChangeName: room.canSendState("m.room.name")
readonly property bool canChangeTopic: room.canSendState("m.room.topic")
readonly property bool canChangeCanonicalAlias: room.canSendState("m.room.canonical_alias")
title: i18n("General")
leftPadding: 0
rightPadding: 0
ColumnLayout {
Kirigami.FormLayout {
MobileForm.FormCard {
Layout.fillWidth: true
Kirigami.Avatar {
Layout.bottomMargin: Kirigami.Units.largeSpacing
name: room.name
source: room.avatarMediaId ? ("image://mxc/" + room.avatarMediaId) : ""
QQC2.RoundButton {
anchors.right: parent.right
anchors.bottom: parent.bottom
height: Kirigami.Units.gridUnits
width: Kirigami.Units.gridUnits
icon.name: 'cloud-upload'
Accessible.name: i18n("Update avatar")
enabled: canChangeAvatar
onClicked: {
const fileDialog = openFileDialog.createObject(QQC2.ApplicationWindow.overlay)
fileDialog.chosen.connect(function(path) {
if (!path) return
room.changeAvatar(path)
})
fileDialog.open()
}
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
title: i18n("Room Information")
}
}
QQC2.TextField {
id: roomNameField
text: room.name
Kirigami.FormData.label: i18n("Room Name:")
enabled: canChangeName
}
QQC2.TextArea {
id: roomTopicField
Layout.fillWidth: true
text: room.topic
Kirigami.FormData.label: i18n("Room topic:")
enabled: canChangeTopic
}
Kirigami.Separator {
Layout.fillWidth: true
visible: canonicalAliasComboBox.visible || altAlias.visible
}
QQC2.ComboBox {
id: canonicalAliasComboBox
visible: room.aliases && room.aliases.length
Kirigami.FormData.label: i18n("Canonical Alias:")
popup.z: 999; // HACK This is an absolute hack, but combos inside OverlaySheets have their popups show up underneath, because of fun z ordering stuff
enabled: canChangeCanonicalAlias
model: room.aliases
currentIndex: room.aliases.indexOf(room.canonicalAlias)
onCurrentIndexChanged: {
if (room.canonicalAlias != room.aliases[currentIndex]) {
room.setCanonicalAlias(room.aliases[currentIndex])
}
}
}
RowLayout {
id: altAlias
Kirigami.FormData.label: i18n("Other Aliases:")
Layout.fillWidth: true
visible: room.altAliases && room.altAliases.length
ColumnLayout {
MobileForm.AbstractFormDelegate {
Layout.fillWidth: true
background: Item {}
contentItem: RowLayout {
Item {
Layout.fillWidth: true
}
Kirigami.Avatar {
id: avatar
Layout.alignment: Qt.AlignRight
name: room.name
source: room.avatarMediaId ? ("image://mxc/" + room.avatarMediaId) : ""
}
QQC2.Button {
Layout.alignment: Qt.AlignLeft
enabled: room.canSendState("m.room.avatar")
visible: enabled
icon.name: "cloud-upload"
text: i18n("Update avatar")
display: QQC2.AbstractButton.IconOnly
spacing: 0
onClicked: {
const fileDialog = openFileDialog.createObject(QQC2.ApplicationWindow.overlay)
Repeater {
model: room.altAliases
fileDialog.chosen.connect(function(path) {
if (!path) return
delegate: RowLayout {
Layout.maximumWidth: parent.width
room.changeAvatar(path)
})
QQC2.Label {
text: modelData
fileDialog.open()
}
QQC2.ToolTip.text: text
QQC2.ToolTip.visible: hovered
}
Item {
Layout.fillWidth: true
}
}
}
MobileForm.FormTextFieldDelegate {
id: roomNameField
label: i18n("Room name:")
text: room.name
enabled: room.canSendState("m.room.name")
}
MobileForm.AbstractFormDelegate {
id: roomTopicField
Layout.fillWidth: true
enabled: room.canSendState("m.room.topic")
background: Item {}
contentItem: ColumnLayout {
QQC2.Label {
id: roomTopicLabel
text: i18n("Room topic:")
Layout.fillWidth: true
}
QQC2.TextArea {
Accessible.description: roomTopicLabel.text
Layout.fillWidth: true
text: room.topic
onTextChanged: roomTopicField.text = text
}
}
}
MobileForm.AbstractFormDelegate {
Layout.fillWidth: true
background: Item {}
contentItem: RowLayout {
Item {
Layout.fillWidth: true
}
QQC2.Button {
Layout.bottomMargin: Kirigami.Units.smallSpacing
Layout.topMargin: Kirigami.Units.smallSpacing
enabled: room.name !== roomNameField.text || room.topic !== roomTopicField.text
text: i18n("Save")
onClicked: {
if (room.name != roomNameField.text) {
room.setName(roomNameField.text)
}
if (room.topic != roomTopicField.text) {
room.setTopic(roomTopicField.text)
}
}
}
}
}
}
}
MobileForm.FormCard {
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
title: i18n("Aliases")
}
MobileForm.FormTextDelegate {
visible: room.aliases.length <= 0
text: i18n("No canonical alias set")
}
Repeater {
id: altAliasRepeater
model: room.aliases.slice().reverse()
delegate: MobileForm.FormTextDelegate {
text: modelData
description: room.canonicalAlias.length > 0 && modelData === room.canonicalAlias ? "Canonical alias" : ""
contentItem.children: [
QQC2.ToolButton {
icon.name: ""
onClicked: room.removeLocalAlias(modelData)
id: setCanonicalAliasButton
visible: modelData !== room.canonicalAlias && room.canSendState("m.room.canonical_alias")
text: i18n("Make this alias the room's canonical alias")
icon.name: "checkmark"
display: QQC2.AbstractButton.IconOnly
onClicked: {
room.setCanonicalAlias(modelData)
}
QQC2.ToolTip {
text: setCanonicalAliasButton.text
delay: Kirigami.Units.toolTipDelay
}
},
QQC2.ToolButton {
id: deleteButton
visible: room.canSendState("m.room.canonical_alias")
text: i18n("Delete alias")
icon.name: "edit-delete-remove"
display: QQC2.AbstractButton.IconOnly
onClicked: {
room.unmapAlias(modelData)
}
QQC2.ToolTip {
text: deleteButton.text
delay: Kirigami.Units.toolTipDelay
}
}
]
}
}
MobileForm.AbstractFormDelegate {
Layout.fillWidth: true
contentItem : RowLayout {
Kirigami.ActionTextField {
id: aliasAddField
Layout.fillWidth: true
placeholderText: i18n("#new_alias:server.org")
rightActions: Kirigami.Action {
icon.name: "edit-clear"
visible: aliasAddField.text.length > 0
onTriggered: {
aliasAddField.text = ""
}
}
onAccepted: {
room.mapAlias(aliasAddField.text)
}
}
QQC2.Button {
id: addButton
text: i18n("Add keyword")
Accessible.name: text
icon.name: "list-add"
display: QQC2.AbstractButton.IconOnly
onClicked: {
room.mapAlias(aliasAddField.text)
}
QQC2.ToolTip {
text: addButton.text
delay: Kirigami.Units.toolTipDelay
}
}
}
@@ -123,47 +219,33 @@ Kirigami.ScrollablePage {
}
}
Kirigami.Separator {
Kirigami.InlineMessage {
Layout.fillWidth: true
visible: next.visible || prev.visible
}
QQC2.Control {
id: next
Layout.fillWidth: true
Layout.maximumWidth: Kirigami.Units.gridUnit * 30
Layout.alignment: Qt.AlignHCenter
text: i18n("This room continues another conversation.")
type: Kirigami.MessageType.Information
visible: room.predecessorId && room.connection.room(room.predecessorId)
padding: Kirigami.Units.largeSpacing
contentItem: Kirigami.InlineMessage {
text: i18n("This room continues another conversation.")
actions: Kirigami.Action {
text: i18n("See older messages...")
onTriggered: {
roomListForm.enteredRoom = Controller.activeConnection.room(room.predecessorId)
root.close()
}
actions: Kirigami.Action {
text: i18n("See older messages…")
onTriggered: {
RoomManager.enterRoom(Controller.activeConnection.room(room.predecessorId));
root.close();
}
}
}
QQC2.Control {
id: prev
Kirigami.InlineMessage {
Layout.fillWidth: true
Layout.maximumWidth: Kirigami.Units.gridUnit * 30
Layout.alignment: Qt.AlignHCenter
text: i18n("This room has been replaced.")
type: Kirigami.MessageType.Information
visible: room.successorId && room.connection.room(room.successorId)
padding: Kirigami.Units.largeSpacing
contentItem: Kirigami.InlineMessage {
text: i18n("This room has been replaced.")
actions: Kirigami.Action {
text: i18n("See new room...")
onTriggered: {
roomListForm.enteredRoom = Controller.activeConnection.room(room.successorId)
root.close()
}
actions: Kirigami.Action {
text: i18n("See new room…")
onTriggered: {
RoomManager.enterRoom(Controller.activeConnection.room(room.successorId));
root.close();
}
}
}
@@ -174,27 +256,5 @@ Kirigami.ScrollablePage {
OpenFileDialog {}
}
}
footer: QQC2.ToolBar {
contentItem: RowLayout {
Item {
Layout.fillWidth: true
}
QQC2.Button {
Layout.alignment: Qt.AlignRight
enabled: room.name !== roomNameField.text || room.topic !== roomTopicField.text
text: i18n("Apply")
onClicked: {
if (room.name != roomNameField.text) {
room.setName(roomNameField.text)
}
if (room.topic != roomTopicField.text) {
room.setTopic(roomTopicField.text)
}
}
}
}
}
}

View File

@@ -113,6 +113,19 @@ Kirigami.ScrollablePage {
Config.save()
}
}
MobileForm.FormDelegateSeparator { above: showAvatarChangeDelegate; below: showDeletedMessages }
MobileForm.FormCheckDelegate {
id: showDeletedMessages
text: i18n("Show deleted messages")
checked: Config.showDeletedMessages
enabled: !Config.isShowDeletedMessagesImmutable
onToggled: {
Config.showDeletedMessages = checked
Config.save()
}
}
}
}

View File

@@ -238,13 +238,13 @@ Kirigami.ApplicationWindow {
text: i18n("Explore rooms")
icon.name: "compass"
onTriggered: pushReplaceLayer("qrc:/JoinRoomPage.qml", {connection: Controller.activeConnection})
enabled: pageStack.layers.currentItem.title !== i18n("Explore Rooms") && Controller.accountCount > 0
enabled: pageStack.layers.depth === 1 && Controller.accountCount > 0
},
Kirigami.Action {
text: i18n("Start a Chat")
icon.name: "irc-join-channel"
onTriggered: pushReplaceLayer("qrc:/StartChatPage.qml", {connection: Controller.activeConnection})
enabled: pageStack.layers.currentItem.title !== i18n("Start a Chat") && Controller.accountCount > 0
enabled: pageStack.layers.depth === 1 && Controller.accountCount > 0
},
Kirigami.Action {
text: i18n("Create a Room")
@@ -262,7 +262,7 @@ Kirigami.ApplicationWindow {
onTriggered: pageStack.pushDialogLayer("qrc:/SettingsPage.qml", {}, {
title: i18n("Configure")
})
enabled: pageStack.layers.currentItem.title !== i18n("Configure NeoChat...")
enabled: pageStack.layers.depth === 1
shortcut: StandardKey.Preferences
},
Kirigami.Action {

View File

@@ -3,7 +3,6 @@
#include "sortfilterroomlistmodel.h"
#include "neochatconfig.h"
#include "roomlistmodel.h"
#include "spacehierarchycache.h"
@@ -15,15 +14,6 @@ SortFilterRoomListModel::SortFilterRoomListModel(QObject *parent)
connect(this, &SortFilterRoomListModel::filterTextChanged, this, [this]() {
invalidateFilter();
});
connect(NeoChatConfig::self(), &NeoChatConfig::ShowRenameChanged, this, [this] {
invalidate();
});
connect(NeoChatConfig::self(), &NeoChatConfig::ShowAvatarUpdateChanged, this, [this] {
invalidate();
});
connect(NeoChatConfig::self(), &NeoChatConfig::ShowLeaveJoinEventChanged, this, [this] {
invalidate();
});
}
void SortFilterRoomListModel::setRoomSortOrder(SortFilterRoomListModel::RoomSortOrder sortOrder)