Compare commits

..

1 Commits

Author SHA1 Message Date
Tobias Fella
739c96711c Invalidate room list sorting when changing event visibility settings
BUG: 455030
2022-11-27 19:16:51 +01:00
73 changed files with 9749 additions and 11599 deletions

View File

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

View File

@@ -7,6 +7,7 @@ include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
# TODO enable once we can have qt6 libQuotient on the CI # 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 # - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml # 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/freebsd.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 - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/flatpak.yml

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,15 +4,16 @@
#pragma once #pragma once
#include <QObject> #include <QObject>
#include <QQuickTextDocument>
#include <QTextCursor> #include <QTextCursor>
#include "completionmodel.h"
#include "userlistmodel.h" #include "userlistmodel.h"
class QTextDocument; class QTextDocument;
class QQuickTextDocument;
class NeoChatRoom; class NeoChatRoom;
class SyntaxHighlighter; class SyntaxHighlighter;
class CompletionModel;
class ChatDocumentHandler : public QObject class ChatDocumentHandler : public QObject
{ {
@@ -27,6 +28,15 @@ class ChatDocumentHandler : public QObject
Q_PROPERTY(NeoChatRoom *room READ room NOTIFY roomChanged) Q_PROPERTY(NeoChatRoom *room READ room NOTIFY roomChanged)
public: public:
enum AutoCompletionType {
User,
Room,
Emoji,
Command,
None,
};
Q_ENUM(AutoCompletionType)
explicit ChatDocumentHandler(QObject *parent = nullptr); explicit ChatDocumentHandler(QObject *parent = nullptr);
[[nodiscard]] QQuickTextDocument *document() const; [[nodiscard]] QQuickTextDocument *document() const;
@@ -70,7 +80,9 @@ private:
SyntaxHighlighter *m_highlighter = nullptr; SyntaxHighlighter *m_highlighter = nullptr;
CompletionModel::AutoCompletionType m_completionType = CompletionModel::None; AutoCompletionType m_completionType = None;
CompletionModel *m_completionModel = nullptr; 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 int CompletionModel::rowCount(const QModelIndex &parent) const
{ {
Q_UNUSED(parent); Q_UNUSED(parent);
if (m_autoCompletionType == None) { if (m_autoCompletionType == ChatDocumentHandler::None) {
return 0; return 0;
} }
return m_filterModel->rowCount(); return m_filterModel->rowCount();
@@ -54,7 +54,7 @@ QVariant CompletionModel::data(const QModelIndex &index, int role) const
return {}; return {};
} }
auto filterIndex = m_filterModel->index(index.row(), 0); auto filterIndex = m_filterModel->index(index.row(), 0);
if (m_autoCompletionType == User) { if (m_autoCompletionType == ChatDocumentHandler::User) {
if (role == Text) { if (role == Text) {
return m_filterModel->data(filterIndex, UserListModel::NameRole); return m_filterModel->data(filterIndex, UserListModel::NameRole);
} }
@@ -66,7 +66,7 @@ QVariant CompletionModel::data(const QModelIndex &index, int role) const
} }
} }
if (m_autoCompletionType == Command) { if (m_autoCompletionType == ChatDocumentHandler::Command) {
if (role == Text) { if (role == Text) {
return m_filterModel->data(filterIndex, ActionsModel::Prefix).toString() + QStringLiteral(" ") return m_filterModel->data(filterIndex, ActionsModel::Prefix).toString() + QStringLiteral(" ")
+ m_filterModel->data(filterIndex, ActionsModel::Parameters).toString(); + 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); return m_filterModel->data(filterIndex, ActionsModel::Prefix);
} }
} }
if (m_autoCompletionType == Room) { if (m_autoCompletionType == ChatDocumentHandler::Room) {
if (role == Text) { if (role == Text) {
return m_filterModel->data(filterIndex, RoomListModel::DisplayNameRole); 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); return m_filterModel->data(filterIndex, RoomListModel::AvatarRole);
} }
} }
if (m_autoCompletionType == Emoji) { if (m_autoCompletionType == ChatDocumentHandler::Emoji) {
if (role == Text) { if (role == Text) {
return m_filterModel->data(filterIndex, CustomEmojiModel::DisplayRole); return m_filterModel->data(filterIndex, CustomEmojiModel::DisplayRole);
} }
@@ -125,7 +125,7 @@ void CompletionModel::updateCompletion()
m_filterModel->setSecondaryFilterRole(UserListModel::NameRole); m_filterModel->setSecondaryFilterRole(UserListModel::NameRole);
m_filterModel->setFullText(m_fullText); m_filterModel->setFullText(m_fullText);
m_filterModel->setFilterText(m_text); m_filterModel->setFilterText(m_text);
m_autoCompletionType = User; m_autoCompletionType = ChatDocumentHandler::User;
m_filterModel->invalidate(); m_filterModel->invalidate();
} else if (text().startsWith(QLatin1Char('/'))) { } else if (text().startsWith(QLatin1Char('/'))) {
m_filterModel->setSourceModel(&ActionsModel::instance()); m_filterModel->setSourceModel(&ActionsModel::instance());
@@ -133,10 +133,10 @@ void CompletionModel::updateCompletion()
m_filterModel->setSecondaryFilterRole(-1); m_filterModel->setSecondaryFilterRole(-1);
m_filterModel->setFullText(m_fullText); m_filterModel->setFullText(m_fullText);
m_filterModel->setFilterText(m_text.mid(1)); m_filterModel->setFilterText(m_text.mid(1));
m_autoCompletionType = Command; m_autoCompletionType = ChatDocumentHandler::Command;
m_filterModel->invalidate(); m_filterModel->invalidate();
} else if (text().startsWith(QLatin1Char('#'))) { } else if (text().startsWith(QLatin1Char('#'))) {
m_autoCompletionType = Room; m_autoCompletionType = ChatDocumentHandler::Room;
m_filterModel->setSourceModel(m_roomListModel); m_filterModel->setSourceModel(m_roomListModel);
m_filterModel->setFilterRole(RoomListModel::CanonicalAliasRole); m_filterModel->setFilterRole(RoomListModel::CanonicalAliasRole);
m_filterModel->setSecondaryFilterRole(RoomListModel::DisplayNameRole); m_filterModel->setSecondaryFilterRole(RoomListModel::DisplayNameRole);
@@ -146,15 +146,15 @@ void CompletionModel::updateCompletion()
} else if (text().startsWith(QLatin1Char(':')) } else if (text().startsWith(QLatin1Char(':'))
&& (m_fullText.indexOf(QLatin1Char(':'), 1) == -1 && (m_fullText.indexOf(QLatin1Char(':'), 1) == -1
|| (m_fullText.indexOf(QLatin1Char(' ')) != -1 && m_fullText.indexOf(QLatin1Char(':'), 1) > m_fullText.indexOf(QLatin1Char(' '), 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_filterModel->setSourceModel(m_emojiModel);
m_autoCompletionType = Emoji;
m_filterModel->setFilterRole(CustomEmojiModel::Name); m_filterModel->setFilterRole(CustomEmojiModel::Name);
m_filterModel->setSecondaryFilterRole(-1); m_filterModel->setSecondaryFilterRole(-1);
m_filterModel->setFullText(m_fullText); m_filterModel->setFullText(m_fullText);
m_filterModel->setFilterText(m_text); m_filterModel->setFilterText(m_text);
m_filterModel->invalidate(); m_filterModel->invalidate();
} else { } else {
m_autoCompletionType = None; m_autoCompletionType = ChatDocumentHandler::None;
} }
beginResetModel(); beginResetModel();
endResetModel(); endResetModel();
@@ -171,12 +171,12 @@ void CompletionModel::setRoom(NeoChatRoom *room)
Q_EMIT roomChanged(); Q_EMIT roomChanged();
} }
CompletionModel::AutoCompletionType CompletionModel::autoCompletionType() const ChatDocumentHandler::AutoCompletionType CompletionModel::autoCompletionType() const
{ {
return m_autoCompletionType; return m_autoCompletionType;
} }
void CompletionModel::setAutoCompletionType(AutoCompletionType autoCompletionType) void CompletionModel::setAutoCompletionType(ChatDocumentHandler::AutoCompletionType autoCompletionType)
{ {
m_autoCompletionType = autoCompletionType; m_autoCompletionType = autoCompletionType;
Q_EMIT autoCompletionTypeChanged(); Q_EMIT autoCompletionTypeChanged();

View File

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

View File

@@ -18,11 +18,7 @@ bool CompletionProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &so
&& sourceModel() && sourceModel()
->data(sourceModel()->index(sourceRow, 0), secondaryFilterRole()) ->data(sourceModel()->index(sourceRow, 0), secondaryFilterRole())
.toString() .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)); .startsWith(m_filterText.midRef(1), Qt::CaseInsensitive));
#endif
} }
int CompletionProxyModel::secondaryFilterRole() const int CompletionProxyModel::secondaryFilterRole() const

View File

@@ -234,6 +234,13 @@ void Controller::showWindow()
WindowController::instance().showAndRaiseWindow(QString()); 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) void Controller::loginWithAccessToken(const QString &serverAddr, const QString &user, const QString &token, const QString &deviceName)
{ {
if (user.isEmpty() || token.isEmpty()) { if (user.isEmpty() || token.isEmpty()) {
@@ -274,6 +281,7 @@ void Controller::logout(Connection *conn, bool serverSideLogout)
} }
SettingsGroup("Accounts").remove(conn->userId()); SettingsGroup("Accounts").remove(conn->userId());
QFile(accessTokenFileName(AccountSettings(conn->userId()))).remove();
QKeychain::DeletePasswordJob job(qAppName()); QKeychain::DeletePasswordJob job(qAppName());
job.setAutoDelete(true); job.setAutoDelete(true);
@@ -366,7 +374,15 @@ void Controller::invokeLogin()
if (accessTokenLoadingJob->error() == QKeychain::Error::NoError) { if (accessTokenLoadingJob->error() == QKeychain::Error::NoError) {
accessToken = accessTokenLoadingJob->binaryData(); accessToken = accessTokenLoadingJob->binaryData();
} else { } else {
return; // 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;
}
} }
auto connection = new Connection(account.homeserver()); auto connection = new Connection(account.homeserver());
@@ -400,6 +416,21 @@ 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) QKeychain::ReadPasswordJob *Controller::loadAccessTokenFromKeyChain(const AccountSettings &account)
{ {
qDebug() << "Reading access token from the keychain for" << account.userId(); qDebug() << "Reading access token from the keychain for" << account.userId();
@@ -411,6 +442,24 @@ QKeychain::ReadPasswordJob *Controller::loadAccessTokenFromKeyChain(const Accoun
if (job->error() == QKeychain::Error::NoError) { if (job->error() == QKeychain::Error::NoError) {
return; 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()) { switch (job->error()) {
case QKeychain::EntryNotFound: case QKeychain::EntryNotFound:
@@ -435,6 +484,22 @@ QKeychain::ReadPasswordJob *Controller::loadAccessTokenFromKeyChain(const Accoun
return job; 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) bool Controller::saveAccessTokenToKeyChain(const AccountSettings &account, const QByteArray &accessToken)
{ {
qDebug() << "Save the access token to the keychain for " << account.userId(); qDebug() << "Save the access token to the keychain for " << account.userId();
@@ -449,7 +514,7 @@ bool Controller::saveAccessTokenToKeyChain(const AccountSettings &account, const
if (job.error()) { if (job.error()) {
qWarning() << "Could not save access token to the keychain: " << qPrintable(job.errorString()); qWarning() << "Could not save access token to the keychain: " << qPrintable(job.errorString());
return false; return saveAccessTokenToFile(account, accessToken);
} }
return true; return true;
} }

View File

@@ -68,6 +68,7 @@ public:
[[nodiscard]] bool supportSystemTray() const; [[nodiscard]] bool supportSystemTray() const;
bool saveAccessTokenToFile(const Quotient::AccountSettings &account, const QByteArray &accessToken);
bool saveAccessTokenToKeyChain(const Quotient::AccountSettings &account, const QByteArray &accessToken); bool saveAccessTokenToKeyChain(const Quotient::AccountSettings &account, const QByteArray &accessToken);
int activeConnectionIndex() const; int activeConnectionIndex() const;
@@ -110,6 +111,7 @@ private:
bool m_busy = false; bool m_busy = false;
TrayIcon *m_trayIcon = nullptr; TrayIcon *m_trayIcon = nullptr;
static QByteArray loadAccessTokenFromFile(const Quotient::AccountSettings &account);
QKeychain::ReadPasswordJob *loadAccessTokenFromKeyChain(const Quotient::AccountSettings &account); QKeychain::ReadPasswordJob *loadAccessTokenFromKeyChain(const Quotient::AccountSettings &account);
void loadSettings(); 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, // 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. // rather than with the full mxid, as that would lead to an invalid user.
auto username = m_matrixId.mid(1, m_matrixId.indexOf(":") - 1); QStringRef username(&m_matrixId, 1, m_matrixId.indexOf(":") - 1);
m_connection->loginWithPassword(username, m_password, m_deviceName, QString()); m_connection->loginWithPassword(username.toString(), m_password, m_deviceName, QString());
} }
bool Login::supportsPassword() const bool Login::supportsPassword() const

View File

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

View File

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

View File

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

View File

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

View File

@@ -17,7 +17,6 @@
#include <qcoro/task.h> #include <qcoro/task.h>
#include <connection.h> #include <connection.h>
#include <csapi/directory.h>
#include <csapi/pushrules.h> #include <csapi/pushrules.h>
#include <csapi/redaction.h> #include <csapi/redaction.h>
#include <csapi/report_content.h> #include <csapi/report_content.h>
@@ -474,6 +473,13 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
auto base = url.scheme() + QStringLiteral("://") + url.host() + (url.port() != -1 ? ':' + QString::number(url.port()) : QString()); 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)); 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; return htmlBody;
} }
@@ -495,14 +501,18 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
plainBody = e.plainBody(); plainBody = e.plainBody();
} }
if (prettyPrint) {
if (removeReply) {
plainBody.remove(utils::removeReplyRegex);
}
return Quotient::prettyPrint(plainBody);
}
if (removeReply) { if (removeReply) {
return plainBody.remove(utils::removeReplyRegex); plainBody = plainBody.remove(utils::removeReplyRegex);
}
if (prettyPrint) {
plainBody = 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> ");
} }
return plainBody; return plainBody;
}, },
@@ -1325,46 +1335,3 @@ void NeoChatRoom::download(const QString &eventId, const QUrl &localFilename)
job->start(); job->start();
#endif #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,7 +3,6 @@
#pragma once #pragma once
#include <qobjectdefs.h>
#include <room.h> #include <room.h>
#include <QCache> #include <QCache>
@@ -202,16 +201,6 @@ public:
Q_INVOKABLE bool downloadTempFile(const QString &eventId); 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 #ifdef QUOTIENT_07
Q_INVOKABLE PollHandler *poll(const QString &eventId); Q_INVOKABLE PollHandler *poll(const QString &eventId);
#endif #endif

View File

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

View File

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

View File

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

View File

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

View File

@@ -75,7 +75,7 @@ a{
background: " + Kirigami.Theme.textColor + "; background: " + Kirigami.Theme.textColor + ";
} }
" : "") + " " : "") + "
</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>") : "") </style>" + 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 color: Kirigami.Theme.textColor
selectedTextColor: Kirigami.Theme.highlightedTextColor selectedTextColor: Kirigami.Theme.highlightedTextColor

View File

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

View File

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

View File

@@ -76,13 +76,6 @@ Loader {
width: Kirigami.Units.gridUnit * 25 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)
}
} }
] ]
@@ -150,7 +143,6 @@ Loader {
QQC2.MenuItem { QQC2.MenuItem {
text: i18n("Configure Web Shortcuts...") text: i18n("Configure Web Shortcuts...")
icon.name: "configure" icon.name: "configure"
visible: !Controller.isFlatpak
onTriggered: webshortcutmodel.configureWebShortcuts() onTriggered: webshortcutmodel.configureWebShortcuts()
} }
} }

View File

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

View File

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

View File

@@ -5,9 +5,7 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.15 as QQC2 import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigami 2.15 as Kirigami
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
import org.kde.neochat 1.0 import org.kde.neochat 1.0
@@ -16,202 +14,108 @@ Kirigami.ScrollablePage {
property var room 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") title: i18n("General")
leftPadding: 0
rightPadding: 0
ColumnLayout { ColumnLayout {
MobileForm.FormCard { Kirigami.FormLayout {
Layout.fillWidth: true Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
title: i18n("Room Information")
}
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
onClicked: { Kirigami.Avatar {
const fileDialog = openFileDialog.createObject(QQC2.ApplicationWindow.overlay) Layout.bottomMargin: Kirigami.Units.largeSpacing
fileDialog.chosen.connect(function(path) { name: room.name
if (!path) return source: room.avatarMediaId ? ("image://mxc/" + room.avatarMediaId) : ""
room.changeAvatar(path) 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.open() fileDialog.chosen.connect(function(path) {
} if (!path) return
QQC2.ToolTip.text: text room.changeAvatar(path)
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) { fileDialog.open()
room.setTopic(roomTopicField.text)
}
}
}
} }
} }
} }
} QQC2.TextField {
MobileForm.FormCard { id: roomNameField
Layout.fillWidth: true text: room.name
contentItem: ColumnLayout { Kirigami.FormData.label: i18n("Room Name:")
spacing: 0 enabled: canChangeName
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 { QQC2.TextArea {
text: modelData id: roomTopicField
description: room.canonicalAlias.length > 0 && modelData === room.canonicalAlias ? "Canonical alias" : "" Layout.fillWidth: true
contentItem.children: [ text: room.topic
QQC2.ToolButton { Kirigami.FormData.label: i18n("Room topic:")
id: setCanonicalAliasButton enabled: canChangeTopic
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: { Kirigami.Separator {
room.unmapAlias(modelData) Layout.fillWidth: true
} visible: canonicalAliasComboBox.visible || altAlias.visible
QQC2.ToolTip { }
text: deleteButton.text
delay: Kirigami.Units.toolTipDelay
}
}
]
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])
} }
} }
MobileForm.AbstractFormDelegate { }
RowLayout {
id: altAlias
Kirigami.FormData.label: i18n("Other Aliases:")
Layout.fillWidth: true
visible: room.altAliases && room.altAliases.length
ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
contentItem : RowLayout { spacing: 0
Kirigami.ActionTextField {
id: aliasAddField
Layout.fillWidth: true Repeater {
model: room.altAliases
placeholderText: i18n("#new_alias:server.org") delegate: RowLayout {
Layout.maximumWidth: parent.width
rightActions: Kirigami.Action { QQC2.Label {
icon.name: "edit-clear" text: modelData
visible: aliasAddField.text.length > 0
onTriggered: {
aliasAddField.text = ""
}
} }
onAccepted: { QQC2.ToolButton {
room.mapAlias(aliasAddField.text) icon.name: ""
} onClicked: room.removeLocalAlias(modelData)
}
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
} }
} }
} }
@@ -219,33 +123,47 @@ Kirigami.ScrollablePage {
} }
} }
Kirigami.InlineMessage { Kirigami.Separator {
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: Kirigami.Units.gridUnit * 30 visible: next.visible || prev.visible
Layout.alignment: Qt.AlignHCenter }
text: i18n("This room continues another conversation.")
type: Kirigami.MessageType.Information QQC2.Control {
id: next
Layout.fillWidth: true
visible: room.predecessorId && room.connection.room(room.predecessorId) visible: room.predecessorId && room.connection.room(room.predecessorId)
actions: Kirigami.Action {
text: i18n("See older messages…") padding: Kirigami.Units.largeSpacing
onTriggered: {
RoomManager.enterRoom(Controller.activeConnection.room(room.predecessorId)); contentItem: Kirigami.InlineMessage {
root.close(); 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()
}
} }
} }
} }
Kirigami.InlineMessage {
QQC2.Control {
id: prev
Layout.fillWidth: true 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) visible: room.successorId && room.connection.room(room.successorId)
actions: Kirigami.Action {
text: i18n("See new room…") padding: Kirigami.Units.largeSpacing
onTriggered: {
RoomManager.enterRoom(Controller.activeConnection.room(room.successorId)); contentItem: Kirigami.InlineMessage {
root.close(); 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()
}
} }
} }
} }
@@ -256,5 +174,27 @@ Kirigami.ScrollablePage {
OpenFileDialog {} 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,19 +113,6 @@ Kirigami.ScrollablePage {
Config.save() 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") text: i18n("Explore rooms")
icon.name: "compass" icon.name: "compass"
onTriggered: pushReplaceLayer("qrc:/JoinRoomPage.qml", {connection: Controller.activeConnection}) onTriggered: pushReplaceLayer("qrc:/JoinRoomPage.qml", {connection: Controller.activeConnection})
enabled: pageStack.layers.depth === 1 && Controller.accountCount > 0 enabled: pageStack.layers.currentItem.title !== i18n("Explore Rooms") && Controller.accountCount > 0
}, },
Kirigami.Action { Kirigami.Action {
text: i18n("Start a Chat") text: i18n("Start a Chat")
icon.name: "irc-join-channel" icon.name: "irc-join-channel"
onTriggered: pushReplaceLayer("qrc:/StartChatPage.qml", {connection: Controller.activeConnection}) onTriggered: pushReplaceLayer("qrc:/StartChatPage.qml", {connection: Controller.activeConnection})
enabled: pageStack.layers.depth === 1 && Controller.accountCount > 0 enabled: pageStack.layers.currentItem.title !== i18n("Start a Chat") && Controller.accountCount > 0
}, },
Kirigami.Action { Kirigami.Action {
text: i18n("Create a Room") text: i18n("Create a Room")
@@ -262,7 +262,7 @@ Kirigami.ApplicationWindow {
onTriggered: pageStack.pushDialogLayer("qrc:/SettingsPage.qml", {}, { onTriggered: pageStack.pushDialogLayer("qrc:/SettingsPage.qml", {}, {
title: i18n("Configure") title: i18n("Configure")
}) })
enabled: pageStack.layers.depth === 1 enabled: pageStack.layers.currentItem.title !== i18n("Configure NeoChat...")
shortcut: StandardKey.Preferences shortcut: StandardKey.Preferences
}, },
Kirigami.Action { Kirigami.Action {

View File

@@ -3,6 +3,7 @@
#include "sortfilterroomlistmodel.h" #include "sortfilterroomlistmodel.h"
#include "neochatconfig.h"
#include "roomlistmodel.h" #include "roomlistmodel.h"
#include "spacehierarchycache.h" #include "spacehierarchycache.h"
@@ -14,6 +15,15 @@ SortFilterRoomListModel::SortFilterRoomListModel(QObject *parent)
connect(this, &SortFilterRoomListModel::filterTextChanged, this, [this]() { connect(this, &SortFilterRoomListModel::filterTextChanged, this, [this]() {
invalidateFilter(); 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) void SortFilterRoomListModel::setRoomSortOrder(SortFilterRoomListModel::RoomSortOrder sortOrder)