Compare commits
84 Commits
v23.08.0
...
work/tobia
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe3516b044 | ||
|
|
794683b5d2 | ||
|
|
9f7f5409bd | ||
|
|
7d7b9d7ae0 | ||
|
|
c7c892c51c | ||
|
|
97903a7cb0 | ||
|
|
0c8f488ac4 | ||
|
|
88368cefaa | ||
|
|
ab4bb41979 | ||
|
|
c2398b19dc | ||
|
|
4b3dac025f | ||
|
|
9eeff06328 | ||
|
|
657a8291d0 | ||
|
|
bc4431462a | ||
|
|
fdd8a62873 | ||
|
|
c164228894 | ||
|
|
7d418f0883 | ||
|
|
e90aecbead | ||
|
|
221c27fbbe | ||
|
|
1907404124 | ||
|
|
81e953dd8c | ||
|
|
9311052e39 | ||
|
|
648fff20f2 | ||
|
|
980211f36a | ||
|
|
25e0e3fa8e | ||
|
|
403c1ed391 | ||
|
|
c2f76612cf | ||
|
|
2a651b8946 | ||
|
|
00c0d1c276 | ||
|
|
0162d91b60 | ||
|
|
5f41b7b4c1 | ||
|
|
d9691bac7c | ||
|
|
719b916837 | ||
|
|
f9514fe925 | ||
|
|
399b9e6944 | ||
|
|
00cf5c8a5b | ||
|
|
02f26424e2 | ||
|
|
3bd639775a | ||
|
|
163c1ef407 | ||
|
|
9997b1074a | ||
|
|
f52a25717b | ||
|
|
5746c24b73 | ||
|
|
dca1b22521 | ||
|
|
b15f1461d8 | ||
|
|
24fd7a0f5b | ||
|
|
0ac3932303 | ||
|
|
807a9ee779 | ||
|
|
4f32a168cd | ||
|
|
45d2da56c7 | ||
|
|
d794e26d62 | ||
|
|
42cc42642d | ||
|
|
ffd6205bd1 | ||
|
|
9ba6b2f0a5 | ||
|
|
f8d3e25f8e | ||
|
|
75cd77facb | ||
|
|
8546d76a54 | ||
|
|
00b7f68a03 | ||
|
|
b486cb905c | ||
|
|
cdd5c9f484 | ||
|
|
3e6c426397 | ||
|
|
847f41e1ad | ||
|
|
ed5bb270ff | ||
|
|
c8b4da2b96 | ||
|
|
ba5445e135 | ||
|
|
1cca39e105 | ||
|
|
dbf67b984e | ||
|
|
c9126cf38e | ||
|
|
13988da4fc | ||
|
|
0847839abc | ||
|
|
6b55e502a0 | ||
|
|
8f81629ac1 | ||
|
|
7f459cb90f | ||
|
|
420e195313 | ||
|
|
3263a69880 | ||
|
|
b060881f06 | ||
|
|
701e786c1f | ||
|
|
646c8ba8fe | ||
|
|
9b31fdea10 | ||
|
|
ce5dfdee16 | ||
|
|
918e805718 | ||
|
|
7debf47833 | ||
|
|
2c142c36e6 | ||
|
|
3279142498 | ||
|
|
0e08a1aa7e |
@@ -58,5 +58,9 @@ Dependencies:
|
|||||||
'require':
|
'require':
|
||||||
'frameworks/kdbusaddons': '@latest-kf6'
|
'frameworks/kdbusaddons': '@latest-kf6'
|
||||||
|
|
||||||
|
- 'on': ['Linux/Qt6', 'Linux/Qt5']
|
||||||
|
'require':
|
||||||
|
'sdk/selenium-webdriver-at-spi': '@latest-kf6'
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
require-passing-tests-on: [ 'Linux/Qt5', 'FreeBSD' ]
|
require-passing-tests-on: [ 'Linux/Qt5', 'FreeBSD', 'Windows' ]
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ cmake_minimum_required(VERSION 3.16)
|
|||||||
|
|
||||||
# KDE Applications version, managed by release script.
|
# KDE Applications version, managed by release script.
|
||||||
set(RELEASE_SERVICE_VERSION_MAJOR "23")
|
set(RELEASE_SERVICE_VERSION_MAJOR "23")
|
||||||
set(RELEASE_SERVICE_VERSION_MINOR "08")
|
set(RELEASE_SERVICE_VERSION_MINOR "11")
|
||||||
set(RELEASE_SERVICE_VERSION_MICRO "0")
|
set(RELEASE_SERVICE_VERSION_MICRO "70")
|
||||||
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
||||||
|
|
||||||
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
|
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
|
||||||
@@ -93,12 +93,6 @@ set_package_properties(KF${QT_MAJOR_VERSION}Kirigami2 PROPERTIES
|
|||||||
)
|
)
|
||||||
find_package(KF${QT_MAJOR_VERSION}KirigamiAddons 0.7.2 REQUIRED)
|
find_package(KF${QT_MAJOR_VERSION}KirigamiAddons 0.7.2 REQUIRED)
|
||||||
|
|
||||||
find_package(Qt${QT_MAJOR_VERSION}Keychain)
|
|
||||||
set_package_properties(Qt${QT_MAJOR_VERSION}Keychain PROPERTIES
|
|
||||||
TYPE REQUIRED
|
|
||||||
PURPOSE "Secure storage of account secrets"
|
|
||||||
)
|
|
||||||
|
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
find_package(OpenSSL)
|
find_package(OpenSSL)
|
||||||
set_package_properties(OpenSSL PROPERTIES
|
set_package_properties(OpenSSL PROPERTIES
|
||||||
@@ -130,6 +124,11 @@ set_package_properties(Quotient${QUOTIENT_SUFFIX} PROPERTIES
|
|||||||
PURPOSE "Talk with matrix server"
|
PURPOSE "Talk with matrix server"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (NOT TARGET Olm::Olm)
|
||||||
|
message(FATAL_ERROR "NeoChat requires Quotient with the E2EE feature enabled")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
find_package(cmark)
|
find_package(cmark)
|
||||||
set_package_properties(cmark PROPERTIES
|
set_package_properties(cmark PROPERTIES
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
@@ -160,10 +159,6 @@ set_package_properties(KF${QT_MAJOR_VERSION}DocTools PROPERTIES DESCRIPTION
|
|||||||
TYPE OPTIONAL
|
TYPE OPTIONAL
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT Quotient${QUOTIENT_SUFFIX}_VERSION_MINOR GREATER 6)
|
|
||||||
cmake_policy(SET CMP0063 OLD)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
find_package(Sqlite3)
|
find_package(Sqlite3)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/android/version.gradle.in ${CMAKE_BINARY_DIR}/version.gradle)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/android/version.gradle.in ${CMAKE_BINARY_DIR}/version.gradle)
|
||||||
@@ -179,9 +174,11 @@ install(FILES org.kde.neochat.tray.svg DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/h
|
|||||||
add_definitions(-DQT_NO_FOREACH)
|
add_definitions(-DQT_NO_FOREACH)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
if (BUILD_TESTING AND Quotient${QUOTIENT_SUFFIX}_VERSION_MINOR GREATER 6)
|
|
||||||
|
if (BUILD_TESTING)
|
||||||
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} NO_MODULE COMPONENTS Test)
|
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} NO_MODULE COMPONENTS Test)
|
||||||
add_subdirectory(autotests)
|
add_subdirectory(autotests)
|
||||||
|
add_subdirectory(appiumtests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(KF${QT_MAJOR_VERSION}DocTools_FOUND)
|
if(KF${QT_MAJOR_VERSION}DocTools_FOUND)
|
||||||
|
|||||||
23
appiumtests/CMakeLists.txt
Normal file
23
appiumtests/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
# SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org>
|
||||||
|
|
||||||
|
|
||||||
|
if(NOT BUILD_TESTING OR NOT CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(SeleniumWebDriverATSPI)
|
||||||
|
set_package_properties(SeleniumWebDriverATSPI PROPERTIES
|
||||||
|
DESCRIPTION "Server component for selenium tests using Linux accessibility infrastructure"
|
||||||
|
PURPOSE "Needed for GUI tests"
|
||||||
|
URL "https://invent.kde.org/sdk/selenium-webdriver-at-spi"
|
||||||
|
TYPE OPTIONAL
|
||||||
|
)
|
||||||
|
if(NOT SeleniumWebDriverATSPI_FOUND)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_test(
|
||||||
|
NAME logintest
|
||||||
|
COMMAND selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/logintest.py
|
||||||
|
)
|
||||||
42
appiumtests/login-server.py
Normal file
42
appiumtests/login-server.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
# SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||||
|
|
||||||
|
|
||||||
|
from flask import Flask, request, abort
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route("/_matrix/client/v3/login", methods=["GET"])
|
||||||
|
def login_get():
|
||||||
|
result = dict()
|
||||||
|
result["flows"] = [dict()]
|
||||||
|
result["flows"][0]["type"] = "m.login.password"
|
||||||
|
return result
|
||||||
|
|
||||||
|
@app.route("/_matrix/client/v3/login", methods=["POST"])
|
||||||
|
def login_post():
|
||||||
|
data = request.get_json()
|
||||||
|
if data["identifier"]["user"] != "user" or data["password"] != "1234":
|
||||||
|
abort(403)
|
||||||
|
print(data)
|
||||||
|
result = dict()
|
||||||
|
result["access_token"] = "token_1234"
|
||||||
|
result["device_id"] = "device_1234"
|
||||||
|
result["user_id"] = "@user:localhost:1234"
|
||||||
|
return result
|
||||||
|
|
||||||
|
@app.route("/_matrix/client/r0/sync")
|
||||||
|
def sync():
|
||||||
|
result = dict()
|
||||||
|
result["next_batch"] = "batch1234"
|
||||||
|
return result
|
||||||
|
|
||||||
|
@app.route("/.well-known/matrix/client")
|
||||||
|
def well_known():
|
||||||
|
reply = dict()
|
||||||
|
reply["m.homeserver"] = dict()
|
||||||
|
reply["m.homeserver"]["base_url"] = "https://localhost:1234"
|
||||||
|
return reply
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(ssl_context='adhoc', port=1234)
|
||||||
44
appiumtests/logintest.py
Executable file
44
appiumtests/logintest.py
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
# SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sitter@kde.org>
|
||||||
|
# SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from appium import webdriver
|
||||||
|
from appium.webdriver.common.appiumby import AppiumBy
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
import time
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
class LoginTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(self):
|
||||||
|
desired_caps = {}
|
||||||
|
desired_caps["app"] = "neochat --ignore-ssl-errors"
|
||||||
|
desired_caps["timeouts"] = {'implicit': 10000}
|
||||||
|
self.driver = webdriver.Remote(
|
||||||
|
command_executor='http://127.0.0.1:4723',
|
||||||
|
desired_capabilities=desired_caps)
|
||||||
|
subprocess.Popen(["python","login-server.py"])
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
if not self._outcome.result.wasSuccessful():
|
||||||
|
self.driver.get_screenshot_as_file("failed_test_shot_{}.png".format(self.id()))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(self):
|
||||||
|
self.driver.quit()
|
||||||
|
|
||||||
|
def test_login(self):
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Matrix ID").send_keys("@user:localhost:1234")
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Continue").click()
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Password").send_keys("1234")
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Login").click()
|
||||||
|
self.driver.find_element(by=AppiumBy.NAME, value="Join some rooms to get started").click()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <Quotient/syncdata.h>
|
#include <Quotient/syncdata.h>
|
||||||
#include <qnamespace.h>
|
#include <qnamespace.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
class TestRoom : public NeoChatRoom
|
class TestRoom : public NeoChatRoom
|
||||||
@@ -555,10 +557,10 @@ void TextHandlerTest::receiveRichPlainUrl()
|
|||||||
void TextHandlerTest::receiveRichEmote()
|
void TextHandlerTest::receiveRichEmote()
|
||||||
{
|
{
|
||||||
auto event = room->messageEvents().at(1).get();
|
auto event = room->messageEvents().at(1).get();
|
||||||
auto author = static_cast<NeoChatUser *>(room->user(event->senderId()));
|
auto author = room->user(event->senderId());
|
||||||
const QString testInputString = QStringLiteral("This is an emote.");
|
const QString testInputString = QStringLiteral("This is an emote.");
|
||||||
const QString testOutputString = QStringLiteral("* <a href=\"https://matrix.to/#/@example:example.org\" style=\"color:") + author->color().name()
|
const QString testOutputString = QStringLiteral("* <a href=\"https://matrix.to/#/@example:example.org\" style=\"color:")
|
||||||
+ QStringLiteral("\">@example:example.org</a> This is an emote.");
|
+ Utils::getUserColor(author->hueF()).name() + QStringLiteral("\">@example:example.org</a> This is an emote.");
|
||||||
|
|
||||||
TextHandler testTextHandler;
|
TextHandler testTextHandler;
|
||||||
testTextHandler.setData(testInputString);
|
testTextHandler.setData(testInputString);
|
||||||
@@ -644,5 +646,5 @@ void TextHandlerTest::linkPreviewsReject()
|
|||||||
QCOMPARE(testTextHandler.getLinkPreviews(), testOutputLinks);
|
QCOMPARE(testTextHandler.getLinkPreviews(), testOutputLinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(TextHandlerTest)
|
QTEST_MAIN(TextHandlerTest)
|
||||||
#include "texthandlertest.moc"
|
#include "texthandlertest.moc"
|
||||||
|
|||||||
@@ -46,43 +46,21 @@
|
|||||||
<name xml:lang="uk">NeoChat</name>
|
<name xml:lang="uk">NeoChat</name>
|
||||||
<name xml:lang="x-test">xxNeoChatxx</name>
|
<name xml:lang="x-test">xxNeoChatxx</name>
|
||||||
<name xml:lang="zh-CN">NeoChat</name>
|
<name xml:lang="zh-CN">NeoChat</name>
|
||||||
<summary>A client for matrix, the decentralized communication protocol</summary>
|
<summary>Chat with your friends on matrix</summary>
|
||||||
<summary xml:lang="ar">عميل لماتركس، ميفاق الاتصال اللامركزي</summary>
|
<summary xml:lang="ca">Xategeu amb els vostres amics a Matrix</summary>
|
||||||
<summary xml:lang="az">Matrix üçün müştəri, mərkəzləşməmiş kommunikasiya protokolu</summary>
|
<summary xml:lang="ca-valencia">Xategeu amb els vostres amics a Matrix</summary>
|
||||||
<summary xml:lang="ca">Un client de Matrix, el protocol de comunicacions descentralitzat</summary>
|
<summary xml:lang="eo">Babilu kun viaj amikoj sur matrix</summary>
|
||||||
<summary xml:lang="ca-valencia">Un client de Matrix, el protocol de comunicacions descentralitzat</summary>
|
<summary xml:lang="eu">Berriketan jardun zure lagunekin «Matrix»en</summary>
|
||||||
<summary xml:lang="cs">Klient pro decentralizovaný komunikační protokol matrix</summary>
|
<summary xml:lang="gl">Charle coas súas amizades en Matrix.</summary>
|
||||||
<summary xml:lang="de">Ein Programm für Matrix, das dezentrale Kommunikationsprotokoll</summary>
|
<summary xml:lang="ka">ესაუბრეთ მეგობრებს Matrix-ზე</summary>
|
||||||
<summary xml:lang="el">Ένας πελάτης για το Matrix, το αποκεντρωμένο πρωτόκολλο επικοινωνίας</summary>
|
<summary xml:lang="nl">Met uw vrienden chatten op matrix</summary>
|
||||||
<summary xml:lang="en-GB">A client for matrix, the decentralised communication protocol</summary>
|
<summary xml:lang="nn">Prat med vennar på Matrix</summary>
|
||||||
<summary xml:lang="eo">Kliento por matrix, la malcentra komunikprotokolo</summary>
|
<summary xml:lang="sl">Klepet z vašimi prijatelji na matrixu</summary>
|
||||||
<summary xml:lang="es">Un cliente para Matrix, el protocolo de comunicaciones descentralizado</summary>
|
<summary xml:lang="sv">Chatta med dina vänner på Matrix</summary>
|
||||||
<summary xml:lang="eu">Matrix, deszentralizatutako komunikazio protokolorako bezero bat</summary>
|
<summary xml:lang="ta">மேட்ரிக்ஸு மூலம் உங்கள் நண்பர்களிடம் பேசலாம்</summary>
|
||||||
<summary xml:lang="fi">Asiakas Matrixille, hajautetulle viestintäyhteyskäytännölle</summary>
|
<summary xml:lang="tr">Matrix'te arkadaşlarınızla sohbet edin</summary>
|
||||||
<summary xml:lang="fr">Un client pour « Matrix », le protocole décentralisé de communications.</summary>
|
<summary xml:lang="uk">Спілкуйтеся з вашими друзями у matrix</summary>
|
||||||
<summary xml:lang="gl">Un cliente para Matrix, o protocolo de comunicación descentralizada.</summary>
|
<summary xml:lang="x-test">xxChat with your friends on matrixxx</summary>
|
||||||
<summary xml:lang="hu">Kliens a matrixhoz, a decentralizált kommunikációs protokollhoz</summary>
|
|
||||||
<summary xml:lang="ia">Un cliente per Matrix, le protocollo de communication decentralisate</summary>
|
|
||||||
<summary xml:lang="id">Klien untuk matrix, protokol komunikasi terdesentralisasi</summary>
|
|
||||||
<summary xml:lang="ie">Un cliente de Matrix, li protocol de communication decentralisat</summary>
|
|
||||||
<summary xml:lang="it">Un client per matrix, il protocollo di comunicazione decentralizzato</summary>
|
|
||||||
<summary xml:lang="ka">კლიენტი Matrix-სთვის, დეცენტრალიზებული კომუნიკაციის პროტოკოლისთვის</summary>
|
|
||||||
<summary xml:lang="ko">Matrix, 분산 대화 프로토콜 클라이언트</summary>
|
|
||||||
<summary xml:lang="nl">Een client voor matrix, het gedecentraliseerde communicatieprotocol</summary>
|
|
||||||
<summary xml:lang="nn">Ein klient for Matrix – protokollen for desentralisert kommunikasjon</summary>
|
|
||||||
<summary xml:lang="pa">ਮੈਟਰਿਕਸ, ਸਰਬ-ਸਾਂਝੇ ਸੰਚਾਰ ਪਰੋਟੋਕਾਲ, ਲਈ ਕਲਾਈਂਟ ਹੈ</summary>
|
|
||||||
<summary xml:lang="pl">Program do obsługi matriksa, rozproszonego protokołu porozumiewania się</summary>
|
|
||||||
<summary xml:lang="pt">Um cliente para o Matrix, o protocolo de comunicação descentralizado</summary>
|
|
||||||
<summary xml:lang="pt-BR">Um cliente do Matrix, o protocolo de comunicação descentralizado</summary>
|
|
||||||
<summary xml:lang="ru">Клиент для Matrix — децентрализованного коммуникационного протокола</summary>
|
|
||||||
<summary xml:lang="sk">Klient pre matrix, decentralizovaný komunikačný protokol</summary>
|
|
||||||
<summary xml:lang="sl">Odjemalec za matrix, decentralizirani komunikacijski protokol</summary>
|
|
||||||
<summary xml:lang="sv">En klient för Matrix, det decentraliserade kommunikationsprotokollet</summary>
|
|
||||||
<summary xml:lang="ta">மையமில்லா தகவல் பரிமாற்ற நெறிமுறையான மேட்ரிக்ஸுக்கான செயலி</summary>
|
|
||||||
<summary xml:lang="tr">Merkezi olmayan iletişim protokolü Matrix için bir istemci</summary>
|
|
||||||
<summary xml:lang="uk">Клієнт matrix, децентралізованого протоколу обміну даними</summary>
|
|
||||||
<summary xml:lang="x-test">xxA client for matrix, the decentralized communication protocolxx</summary>
|
|
||||||
<summary xml:lang="zh-CN">分布式通讯协议 Matrix 的客户端</summary>
|
|
||||||
<description>
|
<description>
|
||||||
<p>NeoChat is a client for Matrix, the decentralized communication protocol for instant messaging. It allows you to send text messages, videos and audio files to your family, colleagues and friends. It uses KDE frameworks and most notably Kirigami
|
<p>NeoChat is a client for Matrix, the decentralized communication protocol for instant messaging. It allows you to send text messages, videos and audio files to your family, colleagues and friends. It uses KDE frameworks and most notably Kirigami
|
||||||
to provide a convergent experience across multiple platforms.</p>
|
to provide a convergent experience across multiple platforms.</p>
|
||||||
@@ -114,6 +92,7 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<p xml:lang="ca">NeoChat pretén ser una aplicació amb totes les característiques per a l'especificació de Matrix. Com a tal, s'ha implementat tota l'especificació actual estable amb les notables excepcions de la VoIP, fils i alguns aspectes de l'encriptatge d'extrem a extrem. Hi ha algunes altres omissions més petites a causa del fet que l'especificació de Matrix està evolucionant constantment, però l'objectiu segueix sent proporcionar suport eventual per a tota l'especificació.</p>
|
<p xml:lang="ca">NeoChat pretén ser una aplicació amb totes les característiques per a l'especificació de Matrix. Com a tal, s'ha implementat tota l'especificació actual estable amb les notables excepcions de la VoIP, fils i alguns aspectes de l'encriptatge d'extrem a extrem. Hi ha algunes altres omissions més petites a causa del fet que l'especificació de Matrix està evolucionant constantment, però l'objectiu segueix sent proporcionar suport eventual per a tota l'especificació.</p>
|
||||||
<p xml:lang="ca-valencia">NeoChat pretén ser una aplicació amb totes les característiques per a l'especificació de Matrix. Com a tal, s'ha implementat tota l'especificació actual estable amb les notables excepcions de VoIP, fils i alguns aspectes de l'encriptació d'extrem a extrem. Hi ha algunes altres omissions més xicotetes a causa del fet que l'especificació de Matrix està evolucionant constantment, però l'objectiu seguix sent proporcionar suport eventual per a tota l'especificació.</p>
|
<p xml:lang="ca-valencia">NeoChat pretén ser una aplicació amb totes les característiques per a l'especificació de Matrix. Com a tal, s'ha implementat tota l'especificació actual estable amb les notables excepcions de VoIP, fils i alguns aspectes de l'encriptació d'extrem a extrem. Hi ha algunes altres omissions més xicotetes a causa del fet que l'especificació de Matrix està evolucionant constantment, però l'objectiu seguix sent proporcionar suport eventual per a tota l'especificació.</p>
|
||||||
<p xml:lang="en-GB">NeoChat aims to be a fully featured application for the Matrix specification. As such everything in the current stable specification with the notable exceptions of VoIP, threads and some aspects of End-to-End Encryption are supported. There are a few other smaller omissions due to the fact that the Matrix spec is constantly evolving but the aim remains to provide eventual support for the entire spec.</p>
|
<p xml:lang="en-GB">NeoChat aims to be a fully featured application for the Matrix specification. As such everything in the current stable specification with the notable exceptions of VoIP, threads and some aspects of End-to-End Encryption are supported. There are a few other smaller omissions due to the fact that the Matrix spec is constantly evolving but the aim remains to provide eventual support for the entire spec.</p>
|
||||||
|
<p xml:lang="eo">NeoChat celas esti plene kapabla aplikaĵo por la Matrix-specifo. Kiel tia, ĉio en la nuna stabila specifo kun la rimarkindaj esceptoj de VoIP, fadenoj kaj kelkaj aspektoj de Fin-al-Fina Ĉifrado estas subtenataj. Estas kelkaj aliaj pli malgrandaj preterlasoj pro la fakto, ke la Matrix-speco konstante evoluas, sed la celo restas provizi finfine subtenon por la tuta specifaĵo.</p>
|
||||||
<p xml:lang="es">NeoChat pretende ser una aplicación con todas las funciones para la especificación de Matrix. Como tal, admite todo en la especificación estable actual, con las notables excepciones de VoIP, subprocesos y algunas funciones de cifrado de extremo a extremo. Existen algunas omisiones menos importantes debido al hecho de que la especificación de Matrix está en constante evolución, pero el objetivo sigue siendo brindar compatibilidad final con toda la especificación.</p>
|
<p xml:lang="es">NeoChat pretende ser una aplicación con todas las funciones para la especificación de Matrix. Como tal, admite todo en la especificación estable actual, con las notables excepciones de VoIP, subprocesos y algunas funciones de cifrado de extremo a extremo. Existen algunas omisiones menos importantes debido al hecho de que la especificación de Matrix está en constante evolución, pero el objetivo sigue siendo brindar compatibilidad final con toda la especificación.</p>
|
||||||
<p xml:lang="eu">«NeoChat»ek «Matrix» zehaztapenaren ezaugarri guztiak eskaintzen dituen aplikazio bat izan nahi du. Beraz, egungo zehaztapen egonkorrean dagoen guztiaren euskarria du, VoIP, hariak eta muturren artean zifratzeko salbuespen nabarmenekin. Badira beste ez-betetze txikiago batzuk, «Matrix»en zehaztapena etengabe eboluzioan dagoelako, baina azken helburua zehaztapen osoaren euskarria ematea izaten jarraitzen du.</p>
|
<p xml:lang="eu">«NeoChat»ek «Matrix» zehaztapenaren ezaugarri guztiak eskaintzen dituen aplikazio bat izan nahi du. Beraz, egungo zehaztapen egonkorrean dagoen guztiaren euskarria du, VoIP, hariak eta muturren artean zifratzeko salbuespen nabarmenekin. Badira beste ez-betetze txikiago batzuk, «Matrix»en zehaztapena etengabe eboluzioan dagoelako, baina azken helburua zehaztapen osoaren euskarria ematea izaten jarraitzen du.</p>
|
||||||
<p xml:lang="fi">NeoChat pyrkii olemaan Matrix-määritelmän täysominaisuuksinen sovellus, joten se tukee kaikkea nykyisessä vakaassa määritelmässä muutamaa huomattavaa poikkeusta lukuun ottamatta (VoIP, säikeet ja jotkin piirteet päästä päähän -salauksessa). Joitakin pienempiäkin puutteita on Matrix-määritelmän jatkuvan kehityksen vuoksi, mutta lopputavoitteena on tarjota määritelmän täysi tuki.</p>
|
<p xml:lang="fi">NeoChat pyrkii olemaan Matrix-määritelmän täysominaisuuksinen sovellus, joten se tukee kaikkea nykyisessä vakaassa määritelmässä muutamaa huomattavaa poikkeusta lukuun ottamatta (VoIP, säikeet ja jotkin piirteet päästä päähän -salauksessa). Joitakin pienempiäkin puutteita on Matrix-määritelmän jatkuvan kehityksen vuoksi, mutta lopputavoitteena on tarjota määritelmän täysi tuki.</p>
|
||||||
@@ -137,6 +116,7 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<p xml:lang="ca">A causa de la naturalesa del desenvolupament de l'especificació de Matrix, el NeoChat també implementa nombroses característiques inestables. Actualment són:</p>
|
<p xml:lang="ca">A causa de la naturalesa del desenvolupament de l'especificació de Matrix, el NeoChat també implementa nombroses característiques inestables. Actualment són:</p>
|
||||||
<p xml:lang="ca-valencia">A causa de la naturalea del desenvolupament de l'especificació de Matrix, NeoChat també implementa nombroses característiques inestables. Actualment són:</p>
|
<p xml:lang="ca-valencia">A causa de la naturalea del desenvolupament de l'especificació de Matrix, NeoChat també implementa nombroses característiques inestables. Actualment són:</p>
|
||||||
<p xml:lang="en-GB">Due to the nature of the Matrix specification development NeoChat also supports numerous unstable features. Currently these are:</p>
|
<p xml:lang="en-GB">Due to the nature of the Matrix specification development NeoChat also supports numerous unstable features. Currently these are:</p>
|
||||||
|
<p xml:lang="eo">Pro la naturo de la Matrix-specifevoluo NeoChat ankaŭ subtenas multajn malstabilajn funkciojn. Nuntempe ĉi tiuj estas:</p>
|
||||||
<p xml:lang="es">Debido a la naturaleza del desarrollo de la especificación de Matrix, NeoChat también permite numerosas funciones no estables, como:</p>
|
<p xml:lang="es">Debido a la naturaleza del desarrollo de la especificación de Matrix, NeoChat también permite numerosas funciones no estables, como:</p>
|
||||||
<p xml:lang="eu">«Matrix» zehaztapenaren garapenaren izaeragatik, «Neo¢hat»ek ezaugarri ezegonkor ugari ere onartzen ditu. Gaur egun hauek:</p>
|
<p xml:lang="eu">«Matrix» zehaztapenaren garapenaren izaeragatik, «Neo¢hat»ek ezaugarri ezegonkor ugari ere onartzen ditu. Gaur egun hauek:</p>
|
||||||
<p xml:lang="fi">Matrix-määritelmän kehittyessä NeoChat tukee myös monia epävakaita ominaisuuksia. Tällä hetkellä näitä ovat:</p>
|
<p xml:lang="fi">Matrix-määritelmän kehittyessä NeoChat tukee myös monia epävakaita ominaisuuksia. Tällä hetkellä näitä ovat:</p>
|
||||||
@@ -162,6 +142,7 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<li xml:lang="ca">Enquestes - MSC3381</li>
|
<li xml:lang="ca">Enquestes - MSC3381</li>
|
||||||
<li xml:lang="ca-valencia">Enquestes - MSC3381</li>
|
<li xml:lang="ca-valencia">Enquestes - MSC3381</li>
|
||||||
<li xml:lang="en-GB">Polls - MSC3381</li>
|
<li xml:lang="en-GB">Polls - MSC3381</li>
|
||||||
|
<li xml:lang="eo">Enketoj - MSC3381</li>
|
||||||
<li xml:lang="es">Encuestas - MSC3381</li>
|
<li xml:lang="es">Encuestas - MSC3381</li>
|
||||||
<li xml:lang="eu">Polls - MSC3381</li>
|
<li xml:lang="eu">Polls - MSC3381</li>
|
||||||
<li xml:lang="fi">Kyselyt – MSC3381</li>
|
<li xml:lang="fi">Kyselyt – MSC3381</li>
|
||||||
@@ -185,6 +166,7 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<li xml:lang="ca">Paquets d'adhesius - MSC2545</li>
|
<li xml:lang="ca">Paquets d'adhesius - MSC2545</li>
|
||||||
<li xml:lang="ca-valencia">Paquets d'adhesius - MSC2545</li>
|
<li xml:lang="ca-valencia">Paquets d'adhesius - MSC2545</li>
|
||||||
<li xml:lang="en-GB">Sticker Packs - MSC2545</li>
|
<li xml:lang="en-GB">Sticker Packs - MSC2545</li>
|
||||||
|
<li xml:lang="eo">Glumark-Pakoj - MSC2545</li>
|
||||||
<li xml:lang="es">Paquetes de pegatinas - MSC2545</li>
|
<li xml:lang="es">Paquetes de pegatinas - MSC2545</li>
|
||||||
<li xml:lang="eu">Eranskailu paketeak - MSC2545</li>
|
<li xml:lang="eu">Eranskailu paketeak - MSC2545</li>
|
||||||
<li xml:lang="fi">Tarrapakkaukset – MSC2545</li>
|
<li xml:lang="fi">Tarrapakkaukset – MSC2545</li>
|
||||||
@@ -208,6 +190,7 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<li xml:lang="ca">Esdeveniments d'ubicació - MSC3488</li>
|
<li xml:lang="ca">Esdeveniments d'ubicació - MSC3488</li>
|
||||||
<li xml:lang="ca-valencia">Esdeveniments d'ubicació - MSC3488</li>
|
<li xml:lang="ca-valencia">Esdeveniments d'ubicació - MSC3488</li>
|
||||||
<li xml:lang="en-GB">Location Events - MSC3488</li>
|
<li xml:lang="en-GB">Location Events - MSC3488</li>
|
||||||
|
<li xml:lang="eo">Lokaj Eventoj - MSC3488</li>
|
||||||
<li xml:lang="es">Eventos de ubicación - MSC3488</li>
|
<li xml:lang="es">Eventos de ubicación - MSC3488</li>
|
||||||
<li xml:lang="eu">Kokaleku-gertaerak - MSC3488</li>
|
<li xml:lang="eu">Kokaleku-gertaerak - MSC3488</li>
|
||||||
<li xml:lang="fi">Sijaintitapahtumat – MSC3488</li>
|
<li xml:lang="fi">Sijaintitapahtumat – MSC3488</li>
|
||||||
@@ -284,12 +267,11 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<value key="KDE::windows_store::screenshots::1::caption">Main view with room list, chat, and room information</value>
|
<value key="KDE::windows_store::screenshots::1::caption">Main view with room list, chat, and room information</value>
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ca">Vista principal amb la llista de sales, xats i informació de les sales</value>
|
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ca">Vista principal amb la llista de sales, xats i informació de les sales</value>
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ca-valencia">Vista principal amb la llista de sales, xats i informació de les sales</value>
|
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ca-valencia">Vista principal amb la llista de sales, xats i informació de les sales</value>
|
||||||
|
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="eo">Ĉefa vido kun ĉambra listo, babilejo kaj ĉambra informo</value>
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="es">Vista principal con la lista de salas, chat e información de la sala</value>
|
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="es">Vista principal con la lista de salas, chat e información de la sala</value>
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="eu">Ikuspegi nagusia gela-zerrenda, berriketa, eta gelako informazioarekin</value>
|
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="eu">Ikuspegi nagusia gela-zerrenda, berriketa, eta gelako informazioarekin</value>
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="fi">Päänäkymä, jossa huoneluettelo, keskustelu ja huoneen tiedot</value>
|
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="fr">Vue principale avec la liste des salons ainsi que des informations sur les salons et forums de discussions</value>
|
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="fr">Vue principale avec la liste des salons ainsi que des informations sur les salons et forums de discussions</value>
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="gl">Vista principal coa lista de salas, a charla, e información da sala.</value>
|
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="gl">Vista principal coa lista de salas, a charla, e información da sala.</value>
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ia">Vista principal con lista de sala, chat e information de sala</value>
|
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="it">Vista principale con elenco delle stanze, chat e informazioni sulla stanza</value>
|
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="it">Vista principale con elenco delle stanze, chat e informazioni sulla stanza</value>
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ka">მთავარი ხედი სურათების სიით, ჩატით და ოთახის ინფორმაციით</value>
|
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ka">მთავარი ხედი სურათების სიით, ჩატით და ოთახის ინფორმაციით</value>
|
||||||
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ko">대화방 목록, 채팅, 대화방 정보가 표시된 주 보기</value>
|
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ko">대화방 목록, 채팅, 대화방 정보가 표시된 주 보기</value>
|
||||||
@@ -306,12 +288,11 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<value key="KDE::windows_store::screenshots::2::caption">Login screen</value>
|
<value key="KDE::windows_store::screenshots::2::caption">Login screen</value>
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ca">Pantalla d'inici de sessió</value>
|
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ca">Pantalla d'inici de sessió</value>
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ca-valencia">Pantalla d'inici de sessió</value>
|
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ca-valencia">Pantalla d'inici de sessió</value>
|
||||||
|
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="eo">Ensaluta ekrano</value>
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="es">Pantalla de inicio de sesión</value>
|
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="es">Pantalla de inicio de sesión</value>
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="eu">Saio-hasteko pantaila</value>
|
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="eu">Saio-hasteko pantaila</value>
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="fi">Kirjautumisnäkymä</value>
|
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="fr">Écran de connexion</value>
|
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="fr">Écran de connexion</value>
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="gl">Pantalla de identificación.</value>
|
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="gl">Pantalla de identificación.</value>
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ia">Schermo de accesso</value>
|
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="it">Schermata di accesso</value>
|
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="it">Schermata di accesso</value>
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ka">შესვლის ეკრანი</value>
|
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ka">შესვლის ეკრანი</value>
|
||||||
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ko">로그인 화면</value>
|
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ko">로그인 화면</value>
|
||||||
@@ -338,7 +319,6 @@ to provide a convergent experience across multiple platforms.</p>
|
|||||||
<content_attribute id="social-chat">intense</content_attribute>
|
<content_attribute id="social-chat">intense</content_attribute>
|
||||||
</content_rating>
|
</content_rating>
|
||||||
<releases>
|
<releases>
|
||||||
<release version="23.08.0" date="2023-08-24"/>
|
|
||||||
<release version="23.04.3" date="2023-07-06"/>
|
<release version="23.04.3" date="2023-07-06"/>
|
||||||
<release version="23.04.2" date="2023-06-08"/>
|
<release version="23.04.2" date="2023-06-08"/>
|
||||||
<release version="23.04.1" date="2023-05-11"/>
|
<release version="23.04.1" date="2023-05-11"/>
|
||||||
|
|||||||
349
po/ar/neochat.po
349
po/ar/neochat.po
File diff suppressed because it is too large
Load Diff
353
po/az/neochat.po
353
po/az/neochat.po
File diff suppressed because it is too large
Load Diff
345
po/ca/neochat.po
345
po/ca/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
348
po/cs/neochat.po
348
po/cs/neochat.po
File diff suppressed because it is too large
Load Diff
346
po/da/neochat.po
346
po/da/neochat.po
File diff suppressed because it is too large
Load Diff
349
po/de/neochat.po
349
po/de/neochat.po
File diff suppressed because it is too large
Load Diff
349
po/el/neochat.po
349
po/el/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
350
po/es/neochat.po
350
po/es/neochat.po
File diff suppressed because it is too large
Load Diff
345
po/eu/neochat.po
345
po/eu/neochat.po
File diff suppressed because it is too large
Load Diff
378
po/fi/neochat.po
378
po/fi/neochat.po
File diff suppressed because it is too large
Load Diff
349
po/fr/neochat.po
349
po/fr/neochat.po
File diff suppressed because it is too large
Load Diff
349
po/hu/neochat.po
349
po/hu/neochat.po
File diff suppressed because it is too large
Load Diff
354
po/ia/neochat.po
354
po/ia/neochat.po
File diff suppressed because it is too large
Load Diff
349
po/id/neochat.po
349
po/id/neochat.po
File diff suppressed because it is too large
Load Diff
350
po/ie/neochat.po
350
po/ie/neochat.po
File diff suppressed because it is too large
Load Diff
352
po/it/neochat.po
352
po/it/neochat.po
File diff suppressed because it is too large
Load Diff
343
po/ja/neochat.po
343
po/ja/neochat.po
File diff suppressed because it is too large
Load Diff
349
po/ka/neochat.po
349
po/ka/neochat.po
File diff suppressed because it is too large
Load Diff
348
po/ko/neochat.po
348
po/ko/neochat.po
File diff suppressed because it is too large
Load Diff
343
po/lt/neochat.po
343
po/lt/neochat.po
File diff suppressed because it is too large
Load Diff
349
po/nl/neochat.po
349
po/nl/neochat.po
File diff suppressed because it is too large
Load Diff
329
po/nn/neochat.po
329
po/nn/neochat.po
@@ -6,8 +6,8 @@ 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: 2023-08-15 02:26+0000\n"
|
"POT-Creation-Date: 2023-08-04 00:46+0000\n"
|
||||||
"PO-Revision-Date: 2023-08-10 18:43+0200\n"
|
"PO-Revision-Date: 2023-08-03 19:40+0200\n"
|
||||||
"Last-Translator: Karl Ove Hufthammer <karl@huftis.org>\n"
|
"Last-Translator: Karl Ove Hufthammer <karl@huftis.org>\n"
|
||||||
"Language-Team: Norwegian Nynorsk <l10n-no@lister.huftis.org>\n"
|
"Language-Team: Norwegian Nynorsk <l10n-no@lister.huftis.org>\n"
|
||||||
"Language: nn\n"
|
"Language: nn\n"
|
||||||
@@ -20,77 +20,77 @@ msgstr ""
|
|||||||
"X-Accelerator-Marker: &\n"
|
"X-Accelerator-Marker: &\n"
|
||||||
"X-Text-Markup: kde4\n"
|
"X-Text-Markup: kde4\n"
|
||||||
|
|
||||||
#: src/controller.cpp:234
|
#: src/controller.cpp:233
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Login Failed: Access Token invalid or revoked"
|
msgid "Login Failed: Access Token invalid or revoked"
|
||||||
msgstr "Feil ved innlogging: Ugyldig eller tilbaketrekt tilgangspollett"
|
msgstr "Feil ved innlogging: Ugyldig eller tilbaketrekt tilgangspollett"
|
||||||
|
|
||||||
#: src/controller.cpp:237 src/controller.cpp:242 src/login.cpp:90
|
#: src/controller.cpp:236 src/controller.cpp:241 src/login.cpp:90
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Login Failed: %1"
|
msgid "Login Failed: %1"
|
||||||
msgstr "Feil ved innlogging: %1"
|
msgstr "Feil ved innlogging: %1"
|
||||||
|
|
||||||
#: src/controller.cpp:248
|
#: src/controller.cpp:247
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Network Error: %1"
|
msgid "Network Error: %1"
|
||||||
msgstr "Nettverksfeil: %1"
|
msgstr "Nettverksfeil: %1"
|
||||||
|
|
||||||
#: src/controller.cpp:273
|
#: src/controller.cpp:272
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Access token wasn't found"
|
msgid "Access token wasn't found"
|
||||||
msgstr "Fann ikkje tilgangspollett"
|
msgstr "Fann ikkje tilgangspollett"
|
||||||
|
|
||||||
#: src/controller.cpp:273
|
#: src/controller.cpp:272
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Maybe it was deleted?"
|
msgid "Maybe it was deleted?"
|
||||||
msgstr "Kanskje han er sletta?"
|
msgstr "Kanskje han er sletta?"
|
||||||
|
|
||||||
#: src/controller.cpp:277
|
#: src/controller.cpp:276
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Access to keychain was denied."
|
msgid "Access to keychain was denied."
|
||||||
msgstr "Vart nekta tilgang til nøkkelring."
|
msgstr "Vart nekta tilgang til nøkkelring."
|
||||||
|
|
||||||
#: src/controller.cpp:277
|
#: src/controller.cpp:276
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Please allow NeoChat to read the access token"
|
msgid "Please allow NeoChat to read the access token"
|
||||||
msgstr "Gje NeoChat løyve til å lesa tilgangspolletten"
|
msgstr "Gje NeoChat løyve til å lesa tilgangspolletten"
|
||||||
|
|
||||||
#: src/controller.cpp:280
|
#: src/controller.cpp:279
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "No keychain available."
|
msgid "No keychain available."
|
||||||
msgstr "Ingen nøkkelring er tilgjengeleg."
|
msgstr "Ingen nøkkelring er tilgjengeleg."
|
||||||
|
|
||||||
#: src/controller.cpp:280
|
#: src/controller.cpp:279
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Please install a keychain, e.g. KWallet or GNOME keyring on Linux"
|
msgid "Please install a keychain, e.g. KWallet or GNOME keyring on Linux"
|
||||||
msgstr "Installer ein nøkkelring, for eksempel KWallet eller GNOME Keyring"
|
msgstr "Installer ein nøkkelring, for eksempel KWallet eller GNOME Keyring"
|
||||||
|
|
||||||
#: src/controller.cpp:283
|
#: src/controller.cpp:282
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Unable to read access token"
|
msgid "Unable to read access token"
|
||||||
msgstr "Klarte ikkje lesa tilgangspollett"
|
msgstr "Klarte ikkje lesa tilgangspollett"
|
||||||
|
|
||||||
#: src/controller.cpp:453
|
#: src/controller.cpp:452
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "File too large to download."
|
msgid "File too large to download."
|
||||||
msgstr "Fila er for stor til å kunna lastast ned."
|
msgstr "Fila er for stor til å kunna lastast ned."
|
||||||
|
|
||||||
#: src/controller.cpp:453
|
#: src/controller.cpp:452
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Contact your matrix server administrator for support."
|
msgid "Contact your matrix server administrator for support."
|
||||||
msgstr "Ta kontakt med administratoren av Matrix-tenaren for brukarstøtte."
|
msgstr "Ta kontakt med administratoren av Matrix-tenaren for brukarstøtte."
|
||||||
|
|
||||||
#: src/controller.cpp:492
|
#: src/controller.cpp:491
|
||||||
#, 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:513
|
#: src/controller.cpp:512
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Space creation failed: %1"
|
msgid "Space creation failed: %1"
|
||||||
msgstr "Feil ved registrering av område: %1"
|
msgstr "Feil ved registrering av område: %1"
|
||||||
|
|
||||||
#: src/controller.cpp:527
|
#: src/controller.cpp:526
|
||||||
#, 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"
|
||||||
@@ -202,16 +202,21 @@ msgctxt "<version number> (built against <possibly different version number>)"
|
|||||||
msgid "%1 (built against %2)"
|
msgid "%1 (built against %2)"
|
||||||
msgstr "%1 (bygd mot %2)"
|
msgstr "%1 (bygd mot %2)"
|
||||||
|
|
||||||
#: src/main.cpp:326
|
#: src/main.cpp:324
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Client for the matrix communication protocol"
|
msgid "Client for the matrix communication protocol"
|
||||||
msgstr "Lynmeldingsklient for Matrix-protokollen"
|
msgstr "Lynmeldingsklient for Matrix-protokollen"
|
||||||
|
|
||||||
#: src/main.cpp:327
|
#: src/main.cpp:325
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Supports matrix: url scheme"
|
msgid "Supports matrix: url scheme"
|
||||||
msgstr "Støttar «matrix:»-adresser"
|
msgstr "Støttar «matrix:»-adresser"
|
||||||
|
|
||||||
|
#: src/main.cpp:326
|
||||||
|
#, kde-format
|
||||||
|
msgid "Ignore all SSL Errors, e.g., unsigned certificates."
|
||||||
|
msgstr "Ignorer alle SSL-feil, for eksempel usignerte sertifikat."
|
||||||
|
|
||||||
#: src/matriximageprovider.cpp:38
|
#: src/matriximageprovider.cpp:38
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Media id '%1' doesn't follow server/mediaId pattern"
|
msgid "Media id '%1' doesn't follow server/mediaId pattern"
|
||||||
@@ -643,35 +648,35 @@ msgctxt "As in 'The user's own emojis"
|
|||||||
msgid "Own Emojis"
|
msgid "Own Emojis"
|
||||||
msgstr "Eigne emojiar"
|
msgstr "Eigne emojiar"
|
||||||
|
|
||||||
#: src/models/messageeventmodel.cpp:464 src/models/messageeventmodel.cpp:473
|
#: src/models/messageeventmodel.cpp:463 src/models/messageeventmodel.cpp:472
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "<i>[This message was deleted]</i>"
|
msgid "<i>[This message was deleted]</i>"
|
||||||
msgstr "<i>[Denne meldinga er sletta]</i>"
|
msgstr "<i>[Denne meldinga er sletta]</i>"
|
||||||
|
|
||||||
#: src/models/messageeventmodel.cpp:465
|
#: src/models/messageeventmodel.cpp:464
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "<i>[This message was deleted: %1]</i>"
|
msgid "<i>[This message was deleted: %1]</i>"
|
||||||
msgstr "<i>[Denne meldinga er sletta: %1]</i>"
|
msgstr "<i>[Denne meldinga er sletta: %1]</i>"
|
||||||
|
|
||||||
# Eller «SENSURERT»?
|
# Eller «SENSURERT»?
|
||||||
#: src/models/messageeventmodel.cpp:541
|
#: src/models/messageeventmodel.cpp:540
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "[REDACTED]"
|
msgid "[REDACTED]"
|
||||||
msgstr "[TREKT TILBAKE]"
|
msgstr "[TREKT TILBAKE]"
|
||||||
|
|
||||||
#: src/models/messageeventmodel.cpp:541
|
#: src/models/messageeventmodel.cpp:540
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "[REDACTED: %1]"
|
msgid "[REDACTED: %1]"
|
||||||
msgstr "[TREKT TILBAKE: %1]"
|
msgstr "[TREKT TILBAKE: %1]"
|
||||||
|
|
||||||
#: src/models/messageeventmodel.cpp:837
|
#: src/models/messageeventmodel.cpp:836
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "1 user: "
|
msgid "1 user: "
|
||||||
msgid_plural "%1 users: "
|
msgid_plural "%1 users: "
|
||||||
msgstr[0] "1 brukar: "
|
msgstr[0] "1 brukar: "
|
||||||
msgstr[1] "%1 brukarar: "
|
msgstr[1] "%1 brukarar: "
|
||||||
|
|
||||||
#: src/models/messageeventmodel.cpp:840
|
#: src/models/messageeventmodel.cpp:839
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "list separator"
|
msgctxt "list separator"
|
||||||
msgid ", "
|
msgid ", "
|
||||||
@@ -732,354 +737,354 @@ msgstr "Lågt prioriterte"
|
|||||||
msgid "Spaces"
|
msgid "Spaces"
|
||||||
msgstr "Område"
|
msgstr "Område"
|
||||||
|
|
||||||
#: src/models/searchmodel.cpp:251
|
#: src/models/searchmodel.cpp:255
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "I dag"
|
msgstr "I dag"
|
||||||
|
|
||||||
#: src/models/searchmodel.cpp:254
|
#: src/models/searchmodel.cpp:258
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Yesterday"
|
msgid "Yesterday"
|
||||||
msgstr "I går"
|
msgstr "I går"
|
||||||
|
|
||||||
#: src/models/searchmodel.cpp:257
|
#: src/models/searchmodel.cpp:261
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "The day before yesterday"
|
msgid "The day before yesterday"
|
||||||
msgstr "I forgårs"
|
msgstr "I forgårs"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:503
|
#: src/neochatroom.cpp:506
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "a file"
|
msgid "a file"
|
||||||
msgstr "ei fil"
|
msgstr "ei fil"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:549
|
#: src/neochatroom.cpp:552
|
||||||
#, 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:551
|
#: src/neochatroom.cpp:554
|
||||||
#, 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:560 src/neochatroom.cpp:698
|
#: src/neochatroom.cpp:563 src/neochatroom.cpp:701
|
||||||
#, 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:562
|
#: src/neochatroom.cpp:565
|
||||||
#, 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:562 src/neochatroom.cpp:700
|
#: src/neochatroom.cpp:565 src/neochatroom.cpp:703
|
||||||
#, 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:566
|
#: src/neochatroom.cpp:569
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid ": %1"
|
msgid ": %1"
|
||||||
msgstr ": %1"
|
msgstr ": %1"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:573 src/neochatroom.cpp:708
|
#: src/neochatroom.cpp:576 src/neochatroom.cpp:711
|
||||||
#, 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:575
|
#: src/neochatroom.cpp:578
|
||||||
#, 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 visingsnamnet sitt til %1"
|
msgstr "endra visingsnamnet sitt til %1"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:580 src/neochatroom.cpp:715
|
#: src/neochatroom.cpp:583 src/neochatroom.cpp:718
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid " and "
|
msgid " and "
|
||||||
msgstr " og "
|
msgstr " og "
|
||||||
|
|
||||||
#: src/neochatroom.cpp:583 src/neochatroom.cpp:718
|
#: src/neochatroom.cpp:586 src/neochatroom.cpp:721
|
||||||
#, 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 sin"
|
msgstr "fjerna avataren sin"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:585 src/neochatroom.cpp:720
|
#: src/neochatroom.cpp:588 src/neochatroom.cpp:723
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "set an avatar"
|
msgid "set an avatar"
|
||||||
msgstr "valde ein avatar"
|
msgstr "valde ein avatar"
|
||||||
|
|
||||||
# Kan gjelda meir enn éin person, så «oppdaterte avataren sin» vert feil.
|
# Kan gjelda meir enn éin person, så «oppdaterte avataren sin» vert feil.
|
||||||
#: src/neochatroom.cpp:587 src/neochatroom.cpp:722
|
#: src/neochatroom.cpp:590 src/neochatroom.cpp:725
|
||||||
#, 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 "valde ein ny avatar"
|
msgstr "valde ein ny avatar"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:591 src/neochatroom.cpp:726
|
#: src/neochatroom.cpp:594 src/neochatroom.cpp:729
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "<user> changed nothing"
|
msgctxt "<user> changed nothing"
|
||||||
msgid "changed nothing"
|
msgid "changed nothing"
|
||||||
msgstr "endra ingenting"
|
msgstr "endra ingenting"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:597
|
#: src/neochatroom.cpp:600
|
||||||
#, 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:597 src/neochatroom.cpp:732
|
#: src/neochatroom.cpp:600 src/neochatroom.cpp:735
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "rejected the invitation"
|
msgid "rejected the invitation"
|
||||||
msgstr "avviste invitasjonen"
|
msgstr "avviste invitasjonen"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:601
|
#: src/neochatroom.cpp:604
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "unbanned %1"
|
msgid "unbanned %1"
|
||||||
msgstr "oppheva utestenging av %1"
|
msgstr "oppheva utestenging av %1"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:601 src/neochatroom.cpp:736
|
#: src/neochatroom.cpp:604 src/neochatroom.cpp:739
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "self-unbanned"
|
msgid "self-unbanned"
|
||||||
msgstr "utestengde seg sjølv"
|
msgstr "utestengde seg sjølv"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:604
|
#: src/neochatroom.cpp:607
|
||||||
#, 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:605 src/neochatroom.cpp:738
|
#: src/neochatroom.cpp:608 src/neochatroom.cpp:741
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "left the room"
|
msgid "left the room"
|
||||||
msgstr "forlét rommet"
|
msgstr "forlét rommet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:609
|
#: src/neochatroom.cpp:612
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "banned %1 from the room"
|
msgid "banned %1 from the room"
|
||||||
msgstr "utestengde %1 frå rommet"
|
msgstr "utestengde %1 frå rommet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:611
|
#: src/neochatroom.cpp:614
|
||||||
#, 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:614 src/neochatroom.cpp:743
|
#: src/neochatroom.cpp:617 src/neochatroom.cpp:746
|
||||||
#, 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:618 src/neochatroom.cpp:746
|
#: src/neochatroom.cpp:621 src/neochatroom.cpp:749
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "requested an invite"
|
msgid "requested an invite"
|
||||||
msgstr "ba om ein invitasjon"
|
msgstr "ba om ein invitasjon"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:618
|
#: src/neochatroom.cpp:621
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "requested an invite with reason: %1"
|
msgid "requested an invite with reason: %1"
|
||||||
msgstr "ba om ein invitasjon med denne grunngjevinga: %1"
|
msgstr "ba om ein invitasjon med denne grunngjevinga: %1"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:622 src/neochatroom.cpp:750
|
#: src/neochatroom.cpp:625 src/neochatroom.cpp:753
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "made something unknown"
|
msgid "made something unknown"
|
||||||
msgstr "gjorde noko ukjent"
|
msgstr "gjorde noko ukjent"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:625 src/neochatroom.cpp:753
|
#: src/neochatroom.cpp:628 src/neochatroom.cpp:756
|
||||||
#, 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:625
|
#: src/neochatroom.cpp:628
|
||||||
#, 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:628 src/neochatroom.cpp:756
|
#: src/neochatroom.cpp:631 src/neochatroom.cpp:759
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "cleared the room name"
|
msgid "cleared the room name"
|
||||||
msgstr "fjerna romnamnet"
|
msgstr "fjerna romnamnet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:628
|
#: src/neochatroom.cpp:631
|
||||||
#, 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:631 src/neochatroom.cpp:759
|
#: src/neochatroom.cpp:634 src/neochatroom.cpp:762
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "cleared the topic"
|
msgid "cleared the topic"
|
||||||
msgstr "fjerna emnet"
|
msgstr "fjerna emnet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:632
|
#: src/neochatroom.cpp:635
|
||||||
#, 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:638 src/neochatroom.cpp:762
|
#: src/neochatroom.cpp:641 src/neochatroom.cpp:765
|
||||||
#, 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:641 src/neochatroom.cpp:765
|
#: src/neochatroom.cpp:644 src/neochatroom.cpp:768
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "activated End-to-End Encryption"
|
msgid "activated End-to-End Encryption"
|
||||||
msgstr "slo på ende-til-ende-kryptering"
|
msgstr "slo på ende-til-ende-kryptering"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:644
|
#: src/neochatroom.cpp:647
|
||||||
#, 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:645
|
#: src/neochatroom.cpp:648
|
||||||
#, 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:648 src/neochatroom.cpp:771
|
#: src/neochatroom.cpp:651 src/neochatroom.cpp:774
|
||||||
#, 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 "endra maktnivået for rommet"
|
msgstr "endra maktnivået for rommet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:652 src/neochatroom.cpp:775
|
#: src/neochatroom.cpp:655 src/neochatroom.cpp:778
|
||||||
#, 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 "endra tenartilgangskontroll-lista for rommet"
|
msgstr "endra tenartilgangskontroll-lista for rommet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:656
|
#: src/neochatroom.cpp:659
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "[User] added <name> widget"
|
msgctxt "[User] added <name> widget"
|
||||||
msgid "added %1 widget"
|
msgid "added %1 widget"
|
||||||
msgstr "la til eit %1-element"
|
msgstr "la til eit %1-element"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:659
|
#: src/neochatroom.cpp:662
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "[User] removed <name> widget"
|
msgctxt "[User] removed <name> widget"
|
||||||
msgid "removed %1 widget"
|
msgid "removed %1 widget"
|
||||||
msgstr "fjerna eit %1-element"
|
msgstr "fjerna eit %1-element"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:661
|
#: src/neochatroom.cpp:664
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "[User] configured <name> widget"
|
msgctxt "[User] configured <name> widget"
|
||||||
msgid "configured %1 widget"
|
msgid "configured %1 widget"
|
||||||
msgstr "endra innstillingar for eit %1-element"
|
msgstr "endra innstillingar for eit %1-element"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:666
|
#: src/neochatroom.cpp:669
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "updated %1 state"
|
msgid "updated %1 state"
|
||||||
msgstr "oppdaterte %1-tilstand"
|
msgstr "oppdaterte %1-tilstand"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:667
|
#: src/neochatroom.cpp:670
|
||||||
#, 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:672 src/neochatroom.cpp:792
|
#: src/neochatroom.cpp:675 src/neochatroom.cpp:795
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Unknown event"
|
msgid "Unknown event"
|
||||||
msgstr "Ukjend hending"
|
msgstr "Ukjend hending"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:681
|
#: src/neochatroom.cpp:684
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "sent a message"
|
msgid "sent a message"
|
||||||
msgstr "sende ei melding"
|
msgstr "sende ei melding"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:685
|
#: src/neochatroom.cpp:688
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "sent a sticker"
|
msgid "sent a sticker"
|
||||||
msgstr "sende eit klistremerke"
|
msgstr "sende eit klistremerke"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:691
|
#: src/neochatroom.cpp:694
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "reinvited someone to the room"
|
msgid "reinvited someone to the room"
|
||||||
msgstr "inviterte nokon på nytt til rommet"
|
msgstr "inviterte nokon på nytt til rommet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:700
|
#: src/neochatroom.cpp:703
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "invited someone to the room"
|
msgid "invited someone to the room"
|
||||||
msgstr "inviterte nokon til rommet"
|
msgstr "inviterte nokon til rommet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:710
|
#: src/neochatroom.cpp:713
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "their refers to a singular user"
|
msgctxt "their refers to a singular user"
|
||||||
msgid "changed their display name"
|
msgid "changed their display name"
|
||||||
msgstr "endra visingsnamnet sitt"
|
msgstr "endra visingsnamnet sitt"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:732
|
#: src/neochatroom.cpp:735
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "withdrew a user's invitation"
|
msgid "withdrew a user's invitation"
|
||||||
msgstr "trekte tilbake ein invitasjonen"
|
msgstr "trekte tilbake ein invitasjonen"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:736
|
#: src/neochatroom.cpp:739
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "unbanned a user"
|
msgid "unbanned a user"
|
||||||
msgstr "oppheva utestenging av ein brukar"
|
msgstr "oppheva utestenging av ein brukar"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:738
|
#: src/neochatroom.cpp:741
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "put a user out of the room"
|
msgid "put a user out of the room"
|
||||||
msgstr "fjerna ein brukar frå rommet"
|
msgstr "fjerna ein brukar frå rommet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:741
|
#: src/neochatroom.cpp:744
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "banned a user from the room"
|
msgid "banned a user from the room"
|
||||||
msgstr "utestengde ein brukar frå rommet"
|
msgstr "utestengde ein brukar frå rommet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:753
|
#: src/neochatroom.cpp:756
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "set the room main alias"
|
msgid "set the room main alias"
|
||||||
msgstr "bytte hovudalias for rommet"
|
msgstr "bytte hovudalias for rommet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:756
|
#: src/neochatroom.cpp:759
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "set the room name"
|
msgid "set the room name"
|
||||||
msgstr "bytte romnamnet"
|
msgstr "bytte romnamnet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:759
|
#: src/neochatroom.cpp:762
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "set the topic"
|
msgid "set the topic"
|
||||||
msgstr "bytte emnet"
|
msgstr "bytte emnet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:768
|
#: src/neochatroom.cpp:771
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "upgraded the room version"
|
msgid "upgraded the room version"
|
||||||
msgstr "oppgraderte rommet til ny versjon"
|
msgstr "oppgraderte rommet til ny versjon"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:768
|
#: src/neochatroom.cpp:771
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "created the room"
|
msgid "created the room"
|
||||||
msgstr "oppretta rommet"
|
msgstr "oppretta rommet"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:779
|
#: src/neochatroom.cpp:782
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "added a widget"
|
msgid "added a widget"
|
||||||
msgstr "la til eit element"
|
msgstr "la til eit element"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:782
|
#: src/neochatroom.cpp:785
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "removed a widget"
|
msgid "removed a widget"
|
||||||
msgstr "fjerna eit element"
|
msgstr "fjerna eit element"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:784
|
#: src/neochatroom.cpp:787
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "configured a widget"
|
msgid "configured a widget"
|
||||||
msgstr "endra innstillingar for eit element"
|
msgstr "endra innstillingar for eit element"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:786
|
#: src/neochatroom.cpp:789
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "updated the state"
|
msgid "updated the state"
|
||||||
msgstr "oppdaterte tilstanden"
|
msgstr "oppdaterte tilstanden"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:790
|
#: src/neochatroom.cpp:793
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "started a poll"
|
msgid "started a poll"
|
||||||
msgstr "starta ei avstemming"
|
msgstr "starta ei avstemming"
|
||||||
|
|
||||||
#: src/neochatroom.cpp:1624 src/neochatroom.cpp:1625
|
#: src/neochatroom.cpp:1627 src/neochatroom.cpp:1628
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Report sent successfully."
|
msgid "Report sent successfully."
|
||||||
msgstr "Rapporten er no send."
|
msgstr "Rapporten er no send."
|
||||||
|
|
||||||
#: src/neochatroom.cpp:1923 src/neochatroom.cpp:1931
|
#: src/neochatroom.cpp:1927 src/neochatroom.cpp:1935
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "'Lat' and 'Lon' as in Latitude and Longitude"
|
msgctxt "'Lat' and 'Lon' as in Latitude and Longitude"
|
||||||
msgid "Lat: %1, Lon: %2"
|
msgid "Lat: %1, Lon: %2"
|
||||||
@@ -1090,7 +1095,7 @@ msgstr "Breiddegr.: %1 – lengdegr.: %2"
|
|||||||
msgid "Encrypted Message"
|
msgid "Encrypted Message"
|
||||||
msgstr "Kryptert melding"
|
msgstr "Kryptert melding"
|
||||||
|
|
||||||
#: src/notificationsmanager.cpp:203 src/qml/main.qml:257
|
#: src/notificationsmanager.cpp:203 src/qml/main.qml:258
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "%1: %2"
|
msgid "%1: %2"
|
||||||
msgstr "%1: %2"
|
msgstr "%1: %2"
|
||||||
@@ -1160,18 +1165,18 @@ msgstr "Legg ved bilete eller fil"
|
|||||||
msgid "Emojis & Stickers"
|
msgid "Emojis & Stickers"
|
||||||
msgstr "Emojiar og klistremerke"
|
msgstr "Emojiar og klistremerke"
|
||||||
|
|
||||||
#: src/qml/Component/ChatBox/ChatBar.qml:106
|
#: src/qml/Component/ChatBox/ChatBar.qml:105
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Send a Location"
|
msgid "Send a Location"
|
||||||
msgstr "Send geografisk posisjon"
|
msgstr "Send geografisk posisjon"
|
||||||
|
|
||||||
# Namn på «send»-knappen i skrivefeltet.
|
# Namn på «send»-knappen i skrivefeltet.
|
||||||
#: src/qml/Component/ChatBox/ChatBar.qml:120
|
#: src/qml/Component/ChatBox/ChatBar.qml:118
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Send message"
|
msgid "Send message"
|
||||||
msgstr "Send meldinga"
|
msgstr "Send meldinga"
|
||||||
|
|
||||||
#: src/qml/Component/ChatBox/ChatBar.qml:167
|
#: src/qml/Component/ChatBox/ChatBar.qml:165
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"This room is encrypted. Build libQuotient with encryption enabled to send "
|
"This room is encrypted. Build libQuotient with encryption enabled to send "
|
||||||
@@ -1180,17 +1185,17 @@ msgstr ""
|
|||||||
"Dette rommet er kryptert. Bygg libQuotient med kryptering slått på for å "
|
"Dette rommet er kryptert. Bygg libQuotient med kryptering slått på for å "
|
||||||
"senda krypterte meldingar."
|
"senda krypterte meldingar."
|
||||||
|
|
||||||
#: src/qml/Component/ChatBox/ChatBar.qml:167
|
#: src/qml/Component/ChatBox/ChatBar.qml:165
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Send an encrypted message…"
|
msgid "Send an encrypted message…"
|
||||||
msgstr "Send ei kryptert melding …"
|
msgstr "Send ei kryptert melding …"
|
||||||
|
|
||||||
#: src/qml/Component/ChatBox/ChatBar.qml:167
|
#: src/qml/Component/ChatBox/ChatBar.qml:165
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Set an attachment caption..."
|
msgid "Set an attachment caption..."
|
||||||
msgstr "Vel vedleggstekst …"
|
msgstr "Vel vedleggstekst …"
|
||||||
|
|
||||||
#: src/qml/Component/ChatBox/ChatBar.qml:167
|
#: src/qml/Component/ChatBox/ChatBar.qml:165
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Send a message…"
|
msgid "Send a message…"
|
||||||
msgstr "Send ei melding …"
|
msgstr "Send ei melding …"
|
||||||
@@ -1325,7 +1330,7 @@ msgstr "Klistremerke"
|
|||||||
msgid "View Location"
|
msgid "View Location"
|
||||||
msgstr "Vis posisjon"
|
msgstr "Vis posisjon"
|
||||||
|
|
||||||
#: src/qml/Component/FullScreenMap.qml:64
|
#: src/qml/Component/FullScreenMap.qml:65
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr "Lukk"
|
msgstr "Lukk"
|
||||||
@@ -1356,13 +1361,13 @@ msgstr "Avvis"
|
|||||||
msgid "Accept"
|
msgid "Accept"
|
||||||
msgstr "Godta"
|
msgstr "Godta"
|
||||||
|
|
||||||
#: src/qml/Component/LocationPage.qml:17 src/qml/Panel/RoomDrawer.qml:201
|
#: src/qml/Component/LocationPage.qml:17 src/qml/Panel/RoomDrawer.qml:200
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "Locations on a map"
|
msgctxt "Locations on a map"
|
||||||
msgid "Locations"
|
msgid "Locations"
|
||||||
msgstr "Posisjonar"
|
msgstr "Posisjonar"
|
||||||
|
|
||||||
#: src/qml/Component/LocationPage.qml:51
|
#: src/qml/Component/LocationPage.qml:52
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "There are no locations shared in this room."
|
msgid "There are no locations shared in this room."
|
||||||
msgstr "Ingen posisjonar er delte i rommet."
|
msgstr "Ingen posisjonar er delte i rommet."
|
||||||
@@ -1389,7 +1394,7 @@ msgid "Url:"
|
|||||||
msgstr "Adresse:"
|
msgstr "Adresse:"
|
||||||
|
|
||||||
#: src/qml/Component/Login/Homeserver.qml:57
|
#: src/qml/Component/Login/Homeserver.qml:57
|
||||||
#: src/qml/Component/Login/Login.qml:46
|
#: src/qml/Component/Login/Login.qml:47
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "@action:button"
|
msgctxt "@action:button"
|
||||||
msgid "Continue"
|
msgid "Continue"
|
||||||
@@ -1416,13 +1421,18 @@ msgstr "Skriv inn Matrix-ID"
|
|||||||
msgid "Matrix ID:"
|
msgid "Matrix ID:"
|
||||||
msgstr "Matrix-ID:"
|
msgstr "Matrix-ID:"
|
||||||
|
|
||||||
#: src/qml/Component/Login/Login.qml:46 src/qml/Component/Login/Sso.qml:45
|
#: src/qml/Component/Login/Login.qml:31
|
||||||
|
#, kde-format
|
||||||
|
msgid "Matrix ID"
|
||||||
|
msgstr "Matrix-ID"
|
||||||
|
|
||||||
|
#: src/qml/Component/Login/Login.qml:47 src/qml/Component/Login/Sso.qml:45
|
||||||
#: src/qml/Page/LoadingPage.qml:9
|
#: src/qml/Page/LoadingPage.qml:9
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Loading…"
|
msgid "Loading…"
|
||||||
msgstr "Lastar …"
|
msgstr "Lastar …"
|
||||||
|
|
||||||
#: src/qml/Component/Login/Login.qml:46
|
#: src/qml/Component/Login/Login.qml:47
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Already logged in"
|
msgid "Already logged in"
|
||||||
msgstr "Allereie innlogga"
|
msgstr "Allereie innlogga"
|
||||||
@@ -1477,6 +1487,13 @@ msgctxt "@action:button"
|
|||||||
msgid "Login"
|
msgid "Login"
|
||||||
msgstr "Logg inn"
|
msgstr "Logg inn"
|
||||||
|
|
||||||
|
#: src/qml/Component/Login/Password.qml:41
|
||||||
|
#: src/qml/Settings/AccountEditorPage.qml:151
|
||||||
|
#: src/qml/Settings/NetworkProxyPage.qml:99
|
||||||
|
#, kde-format
|
||||||
|
msgid "Password"
|
||||||
|
msgstr "Passord"
|
||||||
|
|
||||||
#: src/qml/Component/Login/Sso.qml:23
|
#: src/qml/Component/Login/Sso.qml:23
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Complete the authentication steps in your browser"
|
msgid "Complete the authentication steps in your browser"
|
||||||
@@ -1944,86 +1961,86 @@ msgstr "Administrator (100)"
|
|||||||
msgid "Confirm"
|
msgid "Confirm"
|
||||||
msgstr "Stadfest"
|
msgstr "Stadfest"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:29
|
#: src/qml/Dialog/UserDetailDialog.qml:32
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "@title:menu Account detail dialog"
|
msgctxt "@title:menu Account detail dialog"
|
||||||
msgid "Account detail"
|
msgid "Account detail"
|
||||||
msgstr "Kontodetaljar"
|
msgstr "Kontodetaljar"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:77
|
#: src/qml/Dialog/UserDetailDialog.qml:80
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Unignore this user"
|
msgid "Unignore this user"
|
||||||
msgstr "Avignorer brukaren"
|
msgstr "Avignorer brukaren"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:77
|
#: src/qml/Dialog/UserDetailDialog.qml:80
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Ignore this user"
|
msgid "Ignore this user"
|
||||||
msgstr "Ignorer brukaren"
|
msgstr "Ignorer brukaren"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:89
|
#: src/qml/Dialog/UserDetailDialog.qml:92
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Kick this user"
|
msgid "Kick this user"
|
||||||
msgstr "Kast ut brukaren"
|
msgstr "Kast ut brukaren"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:102
|
#: src/qml/Dialog/UserDetailDialog.qml:105
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Invite this user"
|
msgid "Invite this user"
|
||||||
msgstr "Inviter brukaren"
|
msgstr "Inviter brukaren"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:114
|
#: src/qml/Dialog/UserDetailDialog.qml:117
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Ban this user"
|
msgid "Ban this user"
|
||||||
msgstr "Utesteng brukaren"
|
msgstr "Utesteng brukaren"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:119
|
#: src/qml/Dialog/UserDetailDialog.qml:122
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "@title"
|
msgctxt "@title"
|
||||||
msgid "Ban User"
|
msgid "Ban User"
|
||||||
msgstr "Utesteng brukar"
|
msgstr "Utesteng brukar"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:130
|
#: src/qml/Dialog/UserDetailDialog.qml:133
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Unban this user"
|
msgid "Unban this user"
|
||||||
msgstr "Opphev utestenging av brukaren"
|
msgstr "Opphev utestenging av brukaren"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:142
|
#: src/qml/Dialog/UserDetailDialog.qml:145
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Set user power level"
|
msgid "Set user power level"
|
||||||
msgstr "Vel maktnivå for brukar"
|
msgstr "Vel maktnivå for brukar"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:166
|
#: src/qml/Dialog/UserDetailDialog.qml:169
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Remove recent messages by this user"
|
msgid "Remove recent messages by this user"
|
||||||
msgstr "Fjern nylege meldingar frå brukaren"
|
msgstr "Fjern nylege meldingar frå brukaren"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:171
|
#: src/qml/Dialog/UserDetailDialog.qml:174
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "@title"
|
msgctxt "@title"
|
||||||
msgid "Remove Messages"
|
msgid "Remove Messages"
|
||||||
msgstr "Fjern meldingar"
|
msgstr "Fjern meldingar"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:181
|
#: src/qml/Dialog/UserDetailDialog.qml:184
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Open a private chat"
|
msgid "Open a private chat"
|
||||||
msgstr "Start privat prat"
|
msgstr "Start privat prat"
|
||||||
|
|
||||||
#: src/qml/Dialog/UserDetailDialog.qml:191
|
#: src/qml/Dialog/UserDetailDialog.qml:194
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Copy link"
|
msgid "Copy link"
|
||||||
msgstr "Kopier lenkje"
|
msgstr "Kopier lenkje"
|
||||||
|
|
||||||
#: src/qml/main.qml:299
|
#: src/qml/main.qml:300
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "@title:window"
|
msgctxt "@title:window"
|
||||||
msgid "Session Verification"
|
msgid "Session Verification"
|
||||||
msgstr "Øktstadfesting"
|
msgstr "Øktstadfesting"
|
||||||
|
|
||||||
#: src/qml/main.qml:311
|
#: src/qml/main.qml:312
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "User consent"
|
msgid "User consent"
|
||||||
msgstr "Brukarsamtykke"
|
msgstr "Brukarsamtykke"
|
||||||
|
|
||||||
#: src/qml/main.qml:316
|
#: src/qml/main.qml:317
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your homeserver requires you to agree to its terms and conditions before "
|
"Your homeserver requires you to agree to its terms and conditions before "
|
||||||
@@ -2032,17 +2049,17 @@ msgstr ""
|
|||||||
"Heimetenaren krev at du godtek brukarvilkåra før du kan ta han i bruk. Trykk "
|
"Heimetenaren krev at du godtek brukarvilkåra før du kan ta han i bruk. Trykk "
|
||||||
"på knappen nedanfor for å lesa vilkåra."
|
"på knappen nedanfor for å lesa vilkåra."
|
||||||
|
|
||||||
#: src/qml/main.qml:321
|
#: src/qml/main.qml:322
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Open"
|
msgid "Open"
|
||||||
msgstr "Opna"
|
msgstr "Opna"
|
||||||
|
|
||||||
#: src/qml/main.qml:356
|
#: src/qml/main.qml:357
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Start a chat"
|
msgid "Start a chat"
|
||||||
msgstr "Start prat"
|
msgstr "Start prat"
|
||||||
|
|
||||||
#: src/qml/main.qml:358
|
#: src/qml/main.qml:359
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Do you want to start a chat with %1?"
|
msgid "Do you want to start a chat with %1?"
|
||||||
msgstr "Vil du starta ein prat med %1?"
|
msgstr "Vil du starta ein prat med %1?"
|
||||||
@@ -2659,12 +2676,24 @@ msgstr "Start ved å verta med i nokre rom"
|
|||||||
msgid "Search in room directory"
|
msgid "Search in room directory"
|
||||||
msgstr "Søk i romkatalogen"
|
msgstr "Søk i romkatalogen"
|
||||||
|
|
||||||
#: src/qml/Page/RoomList/RoomDelegate.qml:95
|
#: src/qml/Page/RoomList/Page.qml:196
|
||||||
|
#, kde-format
|
||||||
|
msgctxt "Collapse <section name>"
|
||||||
|
msgid "Collapse %1"
|
||||||
|
msgstr "Fald saman %1"
|
||||||
|
|
||||||
|
#: src/qml/Page/RoomList/Page.qml:196
|
||||||
|
#, kde-format
|
||||||
|
msgctxt "Expand <section name"
|
||||||
|
msgid "Expand %1"
|
||||||
|
msgstr "Utvid %1"
|
||||||
|
|
||||||
|
#: src/qml/Page/RoomList/RoomDelegate.qml:96
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Muted room"
|
msgid "Muted room"
|
||||||
msgstr "Dempa rom"
|
msgstr "Dempa rom"
|
||||||
|
|
||||||
#: src/qml/Page/RoomList/RoomDelegate.qml:127
|
#: src/qml/Page/RoomList/RoomDelegate.qml:128
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Configure room"
|
msgid "Configure room"
|
||||||
msgstr "Set opp rommet"
|
msgstr "Set opp rommet"
|
||||||
@@ -2771,12 +2800,12 @@ msgstr "Velkommen til Matrix"
|
|||||||
msgid "No name"
|
msgid "No name"
|
||||||
msgstr "Namnlaus"
|
msgstr "Namnlaus"
|
||||||
|
|
||||||
#: src/qml/Panel/GroupChatDrawerHeader.qml:71
|
#: src/qml/Panel/GroupChatDrawerHeader.qml:70
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "No Canonical Alias"
|
msgid "No Canonical Alias"
|
||||||
msgstr "Manglar kanonisk alias"
|
msgstr "Manglar kanonisk alias"
|
||||||
|
|
||||||
#: src/qml/Panel/GroupChatDrawerHeader.qml:81
|
#: src/qml/Panel/GroupChatDrawerHeader.qml:80
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "No Topic"
|
msgid "No Topic"
|
||||||
msgstr "Manglar emne"
|
msgstr "Manglar emne"
|
||||||
@@ -2802,55 +2831,61 @@ msgstr "Handlingar"
|
|||||||
msgid "Open developer tools"
|
msgid "Open developer tools"
|
||||||
msgstr "Opna utviklarverktøy"
|
msgstr "Opna utviklarverktøy"
|
||||||
|
|
||||||
#: src/qml/Panel/RoomDrawer.qml:168
|
#: src/qml/Panel/RoomDrawer.qml:167
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Search in this room"
|
msgid "Search in this room"
|
||||||
msgstr "Søk i rommet"
|
msgstr "Søk i rommet"
|
||||||
|
|
||||||
#: src/qml/Panel/RoomDrawer.qml:176
|
#: src/qml/Panel/RoomDrawer.qml:175
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgctxt "@action:title"
|
msgctxt "@action:title"
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Søk"
|
msgstr "Søk"
|
||||||
|
|
||||||
#: src/qml/Panel/RoomDrawer.qml:185
|
#: src/qml/Panel/RoomDrawer.qml:184
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Remove room from favorites"
|
msgid "Remove room from favorites"
|
||||||
msgstr "Fjern rommet frå favorittar"
|
msgstr "Fjern rommet frå favorittar"
|
||||||
|
|
||||||
#: src/qml/Panel/RoomDrawer.qml:185
|
#: src/qml/Panel/RoomDrawer.qml:184
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Make room favorite"
|
msgid "Make room favorite"
|
||||||
msgstr "Gjer rommet til favoritt"
|
msgstr "Gjer rommet til favoritt"
|
||||||
|
|
||||||
#: src/qml/Panel/RoomDrawer.qml:196
|
#: src/qml/Panel/RoomDrawer.qml:195
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Show locations for this room"
|
msgid "Show locations for this room"
|
||||||
msgstr "Vis posisjonar i rommet"
|
msgstr "Vis posisjonar i rommet"
|
||||||
|
|
||||||
#: src/qml/Panel/RoomDrawer.qml:208
|
#: src/qml/Panel/RoomDrawer.qml:207
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Members"
|
msgid "Members"
|
||||||
msgstr "Medlemmar"
|
msgstr "Medlemmar"
|
||||||
|
|
||||||
#: src/qml/Panel/RoomDrawer.qml:219
|
#: src/qml/Panel/RoomDrawer.qml:218
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Search user in room"
|
msgid "Search user in room"
|
||||||
msgstr "Søk etter brukarar i rommet"
|
msgstr "Søk etter brukarar i rommet"
|
||||||
|
|
||||||
#: src/qml/Panel/RoomDrawer.qml:236
|
#: src/qml/Panel/RoomDrawer.qml:231
|
||||||
|
#, kde-format
|
||||||
|
msgctxt "@title"
|
||||||
|
msgid "Invite a User"
|
||||||
|
msgstr "Inviter ein brukar"
|
||||||
|
|
||||||
|
#: src/qml/Panel/RoomDrawer.qml:234
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Invite user to room"
|
msgid "Invite user to room"
|
||||||
msgstr "Inviter brukar til rommet"
|
msgstr "Inviter brukar til rommet"
|
||||||
|
|
||||||
#: src/qml/Panel/RoomDrawer.qml:243
|
#: src/qml/Panel/RoomDrawer.qml:241
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "%1 member"
|
msgid "%1 member"
|
||||||
msgid_plural "%1 members"
|
msgid_plural "%1 members"
|
||||||
msgstr[0] "%1 medlem"
|
msgstr[0] "%1 medlem"
|
||||||
msgstr[1] "%1 medlemmar"
|
msgstr[1] "%1 medlemmar"
|
||||||
|
|
||||||
#: src/qml/Panel/RoomDrawer.qml:243
|
#: src/qml/Panel/RoomDrawer.qml:241
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "No member count"
|
msgid "No member count"
|
||||||
msgstr "Manglar medlemstal"
|
msgstr "Manglar medlemstal"
|
||||||
@@ -3356,12 +3391,6 @@ msgstr "Namn:"
|
|||||||
msgid "Label:"
|
msgid "Label:"
|
||||||
msgstr "Merkelapp:"
|
msgstr "Merkelapp:"
|
||||||
|
|
||||||
#: src/qml/Settings/AccountEditorPage.qml:151
|
|
||||||
#: src/qml/Settings/NetworkProxyPage.qml:99
|
|
||||||
#, kde-format
|
|
||||||
msgid "Password"
|
|
||||||
msgstr "Passord"
|
|
||||||
|
|
||||||
#: src/qml/Settings/AccountEditorPage.qml:159
|
#: src/qml/Settings/AccountEditorPage.qml:159
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Your server doesn't support changing your password"
|
msgid "Your server doesn't support changing your password"
|
||||||
@@ -3499,12 +3528,6 @@ msgstr "I sidestolpen"
|
|||||||
msgid "Color theme"
|
msgid "Color theme"
|
||||||
msgstr "Fargetema"
|
msgstr "Fargetema"
|
||||||
|
|
||||||
#: src/qml/Settings/DeviceDelegate.qml:52
|
|
||||||
#, kde-format
|
|
||||||
msgctxt "@label"
|
|
||||||
msgid "%1, Last activity: %2"
|
|
||||||
msgstr "%1 – siste aktivitet: %2"
|
|
||||||
|
|
||||||
#: src/qml/Settings/DeviceDelegate.qml:61
|
#: src/qml/Settings/DeviceDelegate.qml:61
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "New device name"
|
msgid "New device name"
|
||||||
@@ -3658,8 +3681,8 @@ msgstr "Generelle innstillingar"
|
|||||||
|
|
||||||
#: src/qml/Settings/GeneralSettingsPage.qml:33
|
#: src/qml/Settings/GeneralSettingsPage.qml:33
|
||||||
#, kde-format
|
#, kde-format
|
||||||
msgid "Close to system tray"
|
msgid "Show in System Tray"
|
||||||
msgstr "Minimer til systemtrauet"
|
msgstr "Vis i systemtrauet"
|
||||||
|
|
||||||
#: src/qml/Settings/GeneralSettingsPage.qml:47
|
#: src/qml/Settings/GeneralSettingsPage.qml:47
|
||||||
#, kde-format
|
#, kde-format
|
||||||
|
|||||||
353
po/pa/neochat.po
353
po/pa/neochat.po
File diff suppressed because it is too large
Load Diff
349
po/pl/neochat.po
349
po/pl/neochat.po
File diff suppressed because it is too large
Load Diff
349
po/pt/neochat.po
349
po/pt/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
349
po/ru/neochat.po
349
po/ru/neochat.po
File diff suppressed because it is too large
Load Diff
353
po/sk/neochat.po
353
po/sk/neochat.po
File diff suppressed because it is too large
Load Diff
355
po/sl/neochat.po
355
po/sl/neochat.po
File diff suppressed because it is too large
Load Diff
@@ -1,122 +0,0 @@
|
|||||||
<?xml version="1.0" ?>
|
|
||||||
<!DOCTYPE refentry PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN" "dtd/kdedbx45.dtd" [
|
|
||||||
<!ENTITY % Swedish "INCLUDE">
|
|
||||||
]>
|
|
||||||
<!--
|
|
||||||
SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
|
|
||||||
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
||||||
-->
|
|
||||||
|
|
||||||
<refentry lang="&language;">
|
|
||||||
<refentryinfo>
|
|
||||||
<title
|
|
||||||
>NeoChat användarmanual</title>
|
|
||||||
<author
|
|
||||||
><firstname
|
|
||||||
>Carl</firstname
|
|
||||||
><surname
|
|
||||||
>Schwan</surname
|
|
||||||
> <contrib
|
|
||||||
>NeoChat manualsida.</contrib
|
|
||||||
> <email
|
|
||||||
>carl@carlschwan.eu</email
|
|
||||||
></author>
|
|
||||||
<date
|
|
||||||
>2022-11-01</date>
|
|
||||||
<releaseinfo
|
|
||||||
>22.09</releaseinfo>
|
|
||||||
<productname
|
|
||||||
>NeoChat</productname>
|
|
||||||
</refentryinfo>
|
|
||||||
|
|
||||||
<refmeta>
|
|
||||||
<refentrytitle>
|
|
||||||
<command
|
|
||||||
>neochat</command>
|
|
||||||
</refentrytitle>
|
|
||||||
<manvolnum
|
|
||||||
>1</manvolnum>
|
|
||||||
</refmeta>
|
|
||||||
|
|
||||||
<refnamediv>
|
|
||||||
<refname
|
|
||||||
>neochat</refname>
|
|
||||||
<refpurpose
|
|
||||||
>Klient för att interagera med meddelandeprotokollet matrix</refpurpose>
|
|
||||||
</refnamediv>
|
|
||||||
<!-- body begins here -->
|
|
||||||
<refsynopsisdiv id='synopsis'>
|
|
||||||
<cmdsynopsis
|
|
||||||
><command
|
|
||||||
>neochat</command
|
|
||||||
> <arg choice="opt"
|
|
||||||
><replaceable
|
|
||||||
>URI</replaceable
|
|
||||||
></arg
|
|
||||||
> </cmdsynopsis>
|
|
||||||
</refsynopsisdiv>
|
|
||||||
|
|
||||||
|
|
||||||
<refsect1 id="description">
|
|
||||||
<title
|
|
||||||
>Beskrivning</title>
|
|
||||||
<para
|
|
||||||
><command
|
|
||||||
>neochat</command
|
|
||||||
> är ett chattprogram för protokollet matrix som fungerar både på skrivbord och mobil. </para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1 id="options"
|
|
||||||
><title
|
|
||||||
>Väljare</title>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term
|
|
||||||
><option
|
|
||||||
>URI</option
|
|
||||||
></term>
|
|
||||||
<listitem>
|
|
||||||
<para
|
|
||||||
>Matrix webbadress för en användare eller ett rum, t.ex. matrix:u/användare:exempel.org. Det gör att NeoChat försöker öppna det angivna rummet eller konversationen. </para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1 id="bug">
|
|
||||||
<title
|
|
||||||
>Rapportera fel</title>
|
|
||||||
<para
|
|
||||||
>Rapportera fel och funktionsönskemål på <ulink url="https://bugs.kde.org/enter_bug.cgi?product=NeoChat&component=General"
|
|
||||||
>https://bugs.kde.org/enter_bug.cgi?product=NeoChat&component=General</ulink
|
|
||||||
></para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title
|
|
||||||
>Se också</title>
|
|
||||||
<simplelist>
|
|
||||||
<member
|
|
||||||
>En lista över vanliga frågor om Matrix <ulink url="https://matrix.org/faq/"
|
|
||||||
>https://matrix.org/faq/</ulink
|
|
||||||
> </member>
|
|
||||||
<member
|
|
||||||
>kf5options(7)</member>
|
|
||||||
<member
|
|
||||||
>qt5options(7)</member>
|
|
||||||
</simplelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1 id="copyright"
|
|
||||||
><title
|
|
||||||
>Copyright</title>
|
|
||||||
<para
|
|
||||||
>Copyright © 2020-2022 Tobias Fella </para>
|
|
||||||
<para
|
|
||||||
>Copyright © 2020-2022 Carl Schwan </para>
|
|
||||||
<para
|
|
||||||
>Licens: GNU General Public Version 3 eller senare <<ulink url="https://wwwgnuorg/licenses/gpl-html"
|
|
||||||
>http://www.gnu.org/licenses/gpl-3.0.html</ulink
|
|
||||||
>></para>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
|
||||||
366
po/sv/neochat.po
366
po/sv/neochat.po
File diff suppressed because it is too large
Load Diff
345
po/ta/neochat.po
345
po/ta/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
359
po/tr/neochat.po
359
po/tr/neochat.po
File diff suppressed because it is too large
Load Diff
345
po/uk/neochat.po
345
po/uk/neochat.po
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
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
configure_file(qml/Page/RoomList/RoomDelegate.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Page/RoomList/RoomDelegate.qml)
|
configure_file(qml/Page/RoomList/RoomDelegate.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Page/RoomList/RoomDelegate.qml)
|
||||||
configure_file(qml/Component/QuickSwitcher.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/QuickSwitcher.qml)
|
configure_file(qml/Component/QuickSwitcher.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/QuickSwitcher.qml)
|
||||||
configure_file(qml/Dialog/UserDetailDialog.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Dialog/UserDetailDialog.qml)
|
|
||||||
configure_file(qml/Dialog/PowerLevelDialog.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Dialog/PowerLevelDialog.qml)
|
configure_file(qml/Dialog/PowerLevelDialog.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Dialog/PowerLevelDialog.qml)
|
||||||
configure_file(qml/Component/Timeline/AudioDelegate.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/Timeline/AudioDelegate.qml)
|
configure_file(qml/Component/Timeline/AudioDelegate.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/Timeline/AudioDelegate.qml)
|
||||||
configure_file(qml/Component/Timeline/VideoDelegate.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/Timeline/VideoDelegate.qml)
|
configure_file(qml/Component/Timeline/VideoDelegate.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/Timeline/VideoDelegate.qml)
|
||||||
@@ -44,8 +43,6 @@ add_library(neochat STATIC
|
|||||||
roommanager.h
|
roommanager.h
|
||||||
neochatroom.cpp
|
neochatroom.cpp
|
||||||
neochatroom.h
|
neochatroom.h
|
||||||
neochatuser.cpp
|
|
||||||
neochatuser.h
|
|
||||||
models/userlistmodel.cpp
|
models/userlistmodel.cpp
|
||||||
models/userlistmodel.h
|
models/userlistmodel.h
|
||||||
models/userfiltermodel.cpp
|
models/userfiltermodel.cpp
|
||||||
@@ -127,6 +124,7 @@ add_library(neochat STATIC
|
|||||||
locationhelper.h
|
locationhelper.h
|
||||||
events/pollevent.cpp
|
events/pollevent.cpp
|
||||||
pollhandler.cpp
|
pollhandler.cpp
|
||||||
|
utils.h
|
||||||
)
|
)
|
||||||
|
|
||||||
ecm_qt_declare_logging_category(neochat
|
ecm_qt_declare_logging_category(neochat
|
||||||
@@ -175,7 +173,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR})
|
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR})
|
||||||
target_link_libraries(neochat PUBLIC Qt::Core Qt::Quick Qt::Qml Qt::Gui Qt::Multimedia Qt::Network Qt::QuickControls2 KF${QT_MAJOR_VERSION}::I18n KF${QT_MAJOR_VERSION}::Kirigami2 KF${QT_MAJOR_VERSION}::Notifications KF${QT_MAJOR_VERSION}::ConfigCore KF${QT_MAJOR_VERSION}::ConfigGui KF${QT_MAJOR_VERSION}::CoreAddons KF${QT_MAJOR_VERSION}::SonnetCore KF${QT_MAJOR_VERSION}::ItemModels Quotient${QUOTIENT_SUFFIX} cmark::cmark ${QTKEYCHAIN_LIBRARIES} QCoro::Core)
|
target_link_libraries(neochat PUBLIC Qt::Core Qt::Quick Qt::Qml Qt::Gui Qt::Multimedia Qt::Network Qt::QuickControls2 KF${QT_MAJOR_VERSION}::I18n KF${QT_MAJOR_VERSION}::Kirigami2 KF${QT_MAJOR_VERSION}::Notifications KF${QT_MAJOR_VERSION}::ConfigCore KF${QT_MAJOR_VERSION}::ConfigGui KF${QT_MAJOR_VERSION}::CoreAddons KF${QT_MAJOR_VERSION}::SonnetCore KF${QT_MAJOR_VERSION}::ItemModels Quotient${QUOTIENT_SUFFIX} cmark::cmark QCoro::Core)
|
||||||
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)
|
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)
|
||||||
|
|
||||||
if(NEOCHAT_FLATPAK)
|
if(NEOCHAT_FLATPAK)
|
||||||
|
|||||||
@@ -35,15 +35,15 @@
|
|||||||
#include <Quotient/connection.h>
|
#include <Quotient/connection.h>
|
||||||
#include <Quotient/csapi/content-repo.h>
|
#include <Quotient/csapi/content-repo.h>
|
||||||
#include <Quotient/csapi/logout.h>
|
#include <Quotient/csapi/logout.h>
|
||||||
|
#include <Quotient/csapi/notifications.h>
|
||||||
#include <Quotient/csapi/profile.h>
|
#include <Quotient/csapi/profile.h>
|
||||||
|
#include <Quotient/eventstats.h>
|
||||||
#include <Quotient/jobs/downloadfilejob.h>
|
#include <Quotient/jobs/downloadfilejob.h>
|
||||||
#include <Quotient/qt_connection_util.h>
|
#include <Quotient/qt_connection_util.h>
|
||||||
#include <Quotient/csapi/notifications.h>
|
#include <Quotient/user.h>
|
||||||
#include <Quotient/eventstats.h>
|
|
||||||
|
|
||||||
#include "neochatconfig.h"
|
#include "neochatconfig.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
#include "neochatuser.h"
|
|
||||||
#include "notificationsmanager.h"
|
#include "notificationsmanager.h"
|
||||||
#include "roommanager.h"
|
#include "roommanager.h"
|
||||||
#include "windowcontroller.h"
|
#include "windowcontroller.h"
|
||||||
@@ -60,7 +60,6 @@ Controller::Controller(QObject *parent)
|
|||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
Connection::setRoomType<NeoChatRoom>();
|
Connection::setRoomType<NeoChatRoom>();
|
||||||
Connection::setUserType<NeoChatUser>();
|
|
||||||
|
|
||||||
setApplicationProxy();
|
setApplicationProxy();
|
||||||
|
|
||||||
@@ -532,7 +531,7 @@ void Controller::joinRoom(const QString &alias)
|
|||||||
RoomManager::instance().joinRoom(m_connection, alias, QStringList{knownServer});
|
RoomManager::instance().joinRoom(m_connection, alias, QStringList{knownServer});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::openOrCreateDirectChat(NeoChatUser *user)
|
void Controller::openOrCreateDirectChat(User *user)
|
||||||
{
|
{
|
||||||
const auto existing = activeConnection()->directChats();
|
const auto existing = activeConnection()->directChats();
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
#include <Quotient/settings.h>
|
#include <Quotient/settings.h>
|
||||||
|
|
||||||
class NeoChatRoom;
|
class NeoChatRoom;
|
||||||
class NeoChatUser;
|
|
||||||
class TrayIcon;
|
class TrayIcon;
|
||||||
class QWindow;
|
class QWindow;
|
||||||
class QQuickTextDocument;
|
class QQuickTextDocument;
|
||||||
@@ -23,6 +22,7 @@ namespace Quotient
|
|||||||
{
|
{
|
||||||
class Connection;
|
class Connection;
|
||||||
class Room;
|
class Room;
|
||||||
|
class User;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace QKeychain
|
namespace QKeychain
|
||||||
@@ -183,7 +183,7 @@ public:
|
|||||||
*
|
*
|
||||||
* If a direct chat with the user doesn't exist one is created and then joined.
|
* If a direct chat with the user doesn't exist one is created and then joined.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void openOrCreateDirectChat(NeoChatUser *user);
|
Q_INVOKABLE void openOrCreateDirectChat(Quotient::User *user);
|
||||||
|
|
||||||
[[nodiscard]] bool supportSystemTray() const;
|
[[nodiscard]] bool supportSystemTray() const;
|
||||||
|
|
||||||
|
|||||||
19
src/main.cpp
19
src/main.cpp
@@ -4,6 +4,7 @@
|
|||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QNetworkProxyFactory>
|
#include <QNetworkProxyFactory>
|
||||||
|
#include <QObject>
|
||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
#include <QQmlNetworkAccessManagerFactory>
|
#include <QQmlNetworkAccessManagerFactory>
|
||||||
@@ -28,10 +29,11 @@
|
|||||||
|
|
||||||
#include "neochat-version.h"
|
#include "neochat-version.h"
|
||||||
|
|
||||||
#include <Quotient/keyverificationsession.h>
|
|
||||||
#include <Quotient/accountregistry.h>
|
#include <Quotient/accountregistry.h>
|
||||||
|
#include <Quotient/keyverificationsession.h>
|
||||||
#include <Quotient/networkaccessmanager.h>
|
#include <Quotient/networkaccessmanager.h>
|
||||||
#include <Quotient/room.h>
|
#include <Quotient/room.h>
|
||||||
|
#include <Quotient/user.h>
|
||||||
#include <Quotient/util.h>
|
#include <Quotient/util.h>
|
||||||
|
|
||||||
#include "actionshandler.h"
|
#include "actionshandler.h"
|
||||||
@@ -75,7 +77,6 @@
|
|||||||
#include "models/webshortcutmodel.h"
|
#include "models/webshortcutmodel.h"
|
||||||
#include "neochatconfig.h"
|
#include "neochatconfig.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
#include "neochatuser.h"
|
|
||||||
#include "notificationsmanager.h"
|
#include "notificationsmanager.h"
|
||||||
#include "pollhandler.h"
|
#include "pollhandler.h"
|
||||||
#include "roommanager.h"
|
#include "roommanager.h"
|
||||||
@@ -88,7 +89,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "models/completionmodel.h"
|
#include "models/completionmodel.h"
|
||||||
#include "models/statemodel.h"
|
#include "models/statemodel.h"
|
||||||
#include "neochatuser.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_RUNNER
|
#ifdef HAVE_RUNNER
|
||||||
#include "runner.h"
|
#include "runner.h"
|
||||||
@@ -185,10 +185,8 @@ int main(int argc, char *argv[])
|
|||||||
initLogging();
|
initLogging();
|
||||||
|
|
||||||
#if Quotient_VERSION_MINOR == 8
|
#if Quotient_VERSION_MINOR == 8
|
||||||
#ifdef Quotient_E2EE_ENABLED
|
|
||||||
Connection::setEncryptionDefault(true);
|
Connection::setEncryptionDefault(true);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NEOCHAT_FLATPAK
|
#ifdef NEOCHAT_FLATPAK
|
||||||
// Copy over the included FontConfig configuration to the
|
// Copy over the included FontConfig configuration to the
|
||||||
@@ -261,7 +259,7 @@ int main(int argc, char *argv[])
|
|||||||
qmlRegisterUncreatableType<PushNotificationState>("org.kde.neochat", 1, 0, "PushNotificationState", "ENUM");
|
qmlRegisterUncreatableType<PushNotificationState>("org.kde.neochat", 1, 0, "PushNotificationState", "ENUM");
|
||||||
qmlRegisterUncreatableType<PushNotificationAction>("org.kde.neochat", 1, 0, "PushNotificationAction", "ENUM");
|
qmlRegisterUncreatableType<PushNotificationAction>("org.kde.neochat", 1, 0, "PushNotificationAction", "ENUM");
|
||||||
qmlRegisterUncreatableType<NeoChatRoomType>("org.kde.neochat", 1, 0, "NeoChatRoomType", "ENUM");
|
qmlRegisterUncreatableType<NeoChatRoomType>("org.kde.neochat", 1, 0, "NeoChatRoomType", "ENUM");
|
||||||
qmlRegisterUncreatableType<NeoChatUser>("org.kde.neochat", 1, 0, "NeoChatUser", {});
|
qmlRegisterUncreatableType<User>("org.kde.neochat", 1, 0, "User", {});
|
||||||
qmlRegisterUncreatableType<NeoChatRoom>("org.kde.neochat", 1, 0, "NeoChatRoom", {});
|
qmlRegisterUncreatableType<NeoChatRoom>("org.kde.neochat", 1, 0, "NeoChatRoom", {});
|
||||||
|
|
||||||
qRegisterMetaType<User *>("User*");
|
qRegisterMetaType<User *>("User*");
|
||||||
@@ -271,7 +269,7 @@ int main(int argc, char *argv[])
|
|||||||
qRegisterMetaType<Connection *>("Connection*");
|
qRegisterMetaType<Connection *>("Connection*");
|
||||||
qRegisterMetaType<MessageEventType>("MessageEventType");
|
qRegisterMetaType<MessageEventType>("MessageEventType");
|
||||||
qRegisterMetaType<NeoChatRoom *>("NeoChatRoom*");
|
qRegisterMetaType<NeoChatRoom *>("NeoChatRoom*");
|
||||||
qRegisterMetaType<NeoChatUser *>("NeoChatUser*");
|
qRegisterMetaType<User *>("User*");
|
||||||
qRegisterMetaType<GetRoomEventsJob *>("GetRoomEventsJob*");
|
qRegisterMetaType<GetRoomEventsJob *>("GetRoomEventsJob*");
|
||||||
qRegisterMetaType<QMimeType>("QMimeType");
|
qRegisterMetaType<QMimeType>("QMimeType");
|
||||||
#ifdef Quotient_E2EE_ENABLED
|
#ifdef Quotient_E2EE_ENABLED
|
||||||
@@ -325,11 +323,18 @@ int main(int argc, char *argv[])
|
|||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.setApplicationDescription(i18n("Client for the matrix communication protocol"));
|
parser.setApplicationDescription(i18n("Client for the matrix communication protocol"));
|
||||||
parser.addPositionalArgument(QStringLiteral("urls"), i18n("Supports matrix: url scheme"));
|
parser.addPositionalArgument(QStringLiteral("urls"), i18n("Supports matrix: url scheme"));
|
||||||
|
parser.addOption(QCommandLineOption("ignore-ssl-errors", i18n("Ignore all SSL Errors, e.g., unsigned certificates.")));
|
||||||
|
|
||||||
about.setupCommandLine(&parser);
|
about.setupCommandLine(&parser);
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
about.processCommandLine(&parser);
|
about.processCommandLine(&parser);
|
||||||
|
|
||||||
|
if (parser.isSet("ignore-ssl-errors")) {
|
||||||
|
QObject::connect(NetworkAccessManager::instance(), &QNetworkAccessManager::sslErrors, NetworkAccessManager::instance(), [](QNetworkReply *reply) {
|
||||||
|
reply->ignoreSslErrors();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
engine.addImageProvider(QLatin1String("mxc"), new MatrixImageProvider);
|
engine.addImageProvider(QLatin1String("mxc"), new MatrixImageProvider);
|
||||||
engine.addImageProvider(QLatin1String("blurhash"), new BlurhashImageProvider);
|
engine.addImageProvider(QLatin1String("blurhash"), new BlurhashImageProvider);
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ QVariant DevicesModel::data(const QModelIndex &index, int role) const
|
|||||||
if (device.deviceId == m_connection->deviceId()) {
|
if (device.deviceId == m_connection->deviceId()) {
|
||||||
return This;
|
return This;
|
||||||
}
|
}
|
||||||
#ifdef Quotient_E2EE_ENABLED
|
|
||||||
if (!m_connection->isKnownE2eeCapableDevice(m_connection->userId(), device.deviceId)) {
|
if (!m_connection->isKnownE2eeCapableDevice(m_connection->userId(), device.deviceId)) {
|
||||||
return Unencrypted;
|
return Unencrypted;
|
||||||
}
|
}
|
||||||
@@ -74,9 +73,6 @@ QVariant DevicesModel::data(const QModelIndex &index, int role) const
|
|||||||
} else {
|
} else {
|
||||||
return Unverified;
|
return Unverified;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
return Unverified;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -161,7 +157,6 @@ void DevicesModel::setConnection(Connection *connection)
|
|||||||
Q_EMIT connectionChanged();
|
Q_EMIT connectionChanged();
|
||||||
fetchDevices();
|
fetchDevices();
|
||||||
|
|
||||||
#ifdef Quotient_E2EE_ENABLED
|
|
||||||
connect(m_connection, &Connection::sessionVerified, this, [this](const QString &userId, const QString &deviceId) {
|
connect(m_connection, &Connection::sessionVerified, this, [this](const QString &userId, const QString &deviceId) {
|
||||||
Q_UNUSED(deviceId);
|
Q_UNUSED(deviceId);
|
||||||
if (userId == Controller::instance().activeConnection()->userId()) {
|
if (userId == Controller::instance().activeConnection()->userId()) {
|
||||||
@@ -171,7 +166,6 @@ void DevicesModel::setConnection(Connection *connection)
|
|||||||
connect(m_connection, &Connection::finishedQueryingKeys, this, [this]() {
|
connect(m_connection, &Connection::finishedQueryingKeys, this, [this]() {
|
||||||
fetchDevices();
|
fetchDevices();
|
||||||
});
|
});
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_devicesmodel.cpp"
|
#include "moc_devicesmodel.cpp"
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
bool operator<(const LiveLocationData &lhs, const LiveLocationData &rhs)
|
bool operator<(const LiveLocationData &lhs, const LiveLocationData &rhs)
|
||||||
@@ -88,6 +90,11 @@ QVariant LiveLocationsModel::data(const QModelIndex &index, int roleName) const
|
|||||||
const auto timeout = data.beaconInfo.value("timeout"_ls).toDouble(600000);
|
const auto timeout = data.beaconInfo.value("timeout"_ls).toDouble(600000);
|
||||||
return lastTs + timeout >= QDateTime::currentDateTime().toMSecsSinceEpoch();
|
return lastTs + timeout >= QDateTime::currentDateTime().toMSecsSinceEpoch();
|
||||||
}
|
}
|
||||||
|
case HeadingRole: {
|
||||||
|
bool success = false;
|
||||||
|
const auto heading = data.beacon["org.matrix.msc3488.location"_ls].toObject()["org.kde.itinerary.heading"_ls].toString().toDouble(&success);
|
||||||
|
return success ? heading : NAN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
@@ -101,6 +108,7 @@ QHash<int, QByteArray> LiveLocationsModel::roleNames() const
|
|||||||
r.insert(AssetRole, "asset");
|
r.insert(AssetRole, "asset");
|
||||||
r.insert(AuthorRole, "author");
|
r.insert(AuthorRole, "author");
|
||||||
r.insert(IsLiveRole, "isLive");
|
r.insert(IsLiveRole, "isLive");
|
||||||
|
r.insert(HeadingRole, "heading");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public:
|
|||||||
AssetRole, /**< Type of location event, e.g. self pin of the user location. */
|
AssetRole, /**< Type of location event, e.g. self pin of the user location. */
|
||||||
AuthorRole, /**< The author of the event. */
|
AuthorRole, /**< The author of the event. */
|
||||||
IsLiveRole, /**< Boolean that indicates whether a live location beacon is still live. */
|
IsLiveRole, /**< Boolean that indicates whether a live location beacon is still live. */
|
||||||
|
HeadingRole, /**< Heading in degree (not part of any MSC yet, using an Itinerary extension). */
|
||||||
};
|
};
|
||||||
Q_ENUM(Roles)
|
Q_ENUM(Roles)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "locationsmodel.h"
|
#include "locationsmodel.h"
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
LocationsModel::LocationsModel(QObject *parent)
|
LocationsModel::LocationsModel(QObject *parent)
|
||||||
@@ -43,6 +45,10 @@ LocationsModel::LocationsModel(QObject *parent)
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(this, &LocationsModel::rowsInserted, this, &LocationsModel::boundingBoxChanged);
|
connect(this, &LocationsModel::rowsInserted, this, &LocationsModel::boundingBoxChanged);
|
||||||
|
|
||||||
|
connect(static_cast<QGuiApplication *>(QGuiApplication::instance()), &QGuiApplication::paletteChanged, this, [this] {
|
||||||
|
Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0), {AuthorRole});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocationsModel::addLocation(const RoomMessageEvent *event)
|
void LocationsModel::addLocation(const RoomMessageEvent *event)
|
||||||
@@ -61,7 +67,7 @@ void LocationsModel::addLocation(const RoomMessageEvent *event)
|
|||||||
.latitude = latitude,
|
.latitude = latitude,
|
||||||
.longitude = longitude,
|
.longitude = longitude,
|
||||||
.content = event->contentJson(),
|
.content = event->contentJson(),
|
||||||
.author = dynamic_cast<NeoChatUser *>(m_room->user(event->senderId())),
|
.author = m_room->user(event->senderId()),
|
||||||
};
|
};
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
|
|
||||||
#include <Quotient/events/roommessageevent.h>
|
#include <Quotient/events/roommessageevent.h>
|
||||||
|
#include <Quotient/user.h>
|
||||||
|
|
||||||
class LocationsModel : public QAbstractListModel
|
class LocationsModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
@@ -51,7 +52,7 @@ private:
|
|||||||
float latitude;
|
float latitude;
|
||||||
float longitude;
|
float longitude;
|
||||||
QJsonObject content;
|
QJsonObject content;
|
||||||
NeoChatUser *author;
|
Quotient::User *author;
|
||||||
};
|
};
|
||||||
QList<LocationData> m_locations;
|
QList<LocationData> m_locations;
|
||||||
void addLocation(const Quotient::RoomMessageEvent *event);
|
void addLocation(const Quotient::RoomMessageEvent *event);
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
#include "models/reactionmodel.h"
|
#include "models/reactionmodel.h"
|
||||||
#include "neochatuser.h"
|
|
||||||
#include "texthandler.h"
|
#include "texthandler.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
@@ -78,7 +77,7 @@ MessageEventModel::MessageEventModel(QObject *parent)
|
|||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
connect(static_cast<QGuiApplication *>(QGuiApplication::instance()), &QGuiApplication::paletteChanged, this, [this] {
|
connect(static_cast<QGuiApplication *>(QGuiApplication::instance()), &QGuiApplication::paletteChanged, this, [this] {
|
||||||
Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0), {AuthorRole, ReplyRole});
|
Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0), {AuthorRole, ReplyAuthor, ReadMarkersRole});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,7 +530,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (role == AuthorRole) {
|
if (role == AuthorRole) {
|
||||||
auto author = static_cast<NeoChatUser *>(isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId()));
|
auto author = isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId());
|
||||||
return m_currentRoom->getUser(author);
|
return m_currentRoom->getUser(author);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,7 +678,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
auto replyPtr = m_currentRoom->getReplyForEvent(evt);
|
auto replyPtr = m_currentRoom->getReplyForEvent(evt);
|
||||||
|
|
||||||
if (replyPtr) {
|
if (replyPtr) {
|
||||||
auto replyUser = static_cast<NeoChatUser *>(m_currentRoom->user(replyPtr->senderId()));
|
auto replyUser = m_currentRoom->user(replyPtr->senderId());
|
||||||
return m_currentRoom->getUser(replyUser);
|
return m_currentRoom->getUser(replyUser);
|
||||||
} else {
|
} else {
|
||||||
return m_currentRoom->getUser(nullptr);
|
return m_currentRoom->getUser(nullptr);
|
||||||
@@ -808,7 +807,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
QVariantList users;
|
QVariantList users;
|
||||||
users.reserve(userIds.size());
|
users.reserve(userIds.size());
|
||||||
for (const auto &userId : userIds) {
|
for (const auto &userId : userIds) {
|
||||||
auto user = static_cast<NeoChatUser *>(m_currentRoom->user(userId));
|
auto user = m_currentRoom->user(userId);
|
||||||
users += m_currentRoom->getUser(user);
|
users += m_currentRoom->getUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,7 +835,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
*/
|
*/
|
||||||
QString readMarkersString = i18np("1 user: ", "%1 users: ", userIds.size());
|
QString readMarkersString = i18np("1 user: ", "%1 users: ", userIds.size());
|
||||||
for (const auto &userId : userIds) {
|
for (const auto &userId : userIds) {
|
||||||
auto user = static_cast<NeoChatUser *>(m_currentRoom->user(userId));
|
auto user = m_currentRoom->user(userId);
|
||||||
readMarkersString += user->displayname(m_currentRoom) + i18nc("list separator", ", ");
|
readMarkersString += user->displayname(m_currentRoom) + i18nc("list separator", ", ");
|
||||||
}
|
}
|
||||||
readMarkersString.chop(2);
|
readMarkersString.chop(2);
|
||||||
@@ -877,7 +876,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (role == DisplayNameForInitialsRole) {
|
if (role == DisplayNameForInitialsRole) {
|
||||||
auto user = static_cast<NeoChatUser *>(isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId()));
|
auto user = isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId());
|
||||||
return user->displayname(m_currentRoom).remove(QStringLiteral(" (%1)").arg(user->id()));
|
return user->displayname(m_currentRoom).remove(QStringLiteral(" (%1)").arg(user->id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -889,7 +888,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
}
|
}
|
||||||
return previousDisplayName;
|
return previousDisplayName;
|
||||||
} else {
|
} else {
|
||||||
auto author = static_cast<NeoChatUser *>(isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId()));
|
auto author = isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId());
|
||||||
return m_currentRoom->htmlSafeMemberName(author->id());
|
return m_currentRoom->htmlSafeMemberName(author->id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1062,13 +1061,13 @@ void MessageEventModel::createReactionModelForEvent(const Quotient::RoomMessageE
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
QMap<QString, QList<NeoChatUser *>> reactions = {};
|
QMap<QString, QList<Quotient::User *>> reactions = {};
|
||||||
for (const auto &a : annotations) {
|
for (const auto &a : annotations) {
|
||||||
if (a->isRedacted()) { // Just in case?
|
if (a->isRedacted()) { // Just in case?
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (const auto &e = eventCast<const ReactionEvent>(a)) {
|
if (const auto &e = eventCast<const ReactionEvent>(a)) {
|
||||||
reactions[e->key()].append(static_cast<NeoChatUser *>(m_currentRoom->user(e->senderId())));
|
reactions[e->key()].append(m_currentRoom->user(e->senderId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1095,7 +1094,7 @@ void MessageEventModel::createReactionModelForEvent(const Quotient::RoomMessageE
|
|||||||
if (m_reactionModels.contains(eventId)) {
|
if (m_reactionModels.contains(eventId)) {
|
||||||
m_reactionModels[eventId]->setReactions(res);
|
m_reactionModels[eventId]->setReactions(res);
|
||||||
} else if (res.size() > 0) {
|
} else if (res.size() > 0) {
|
||||||
m_reactionModels[eventId] = new ReactionModel(this, res, static_cast<NeoChatUser *>(m_currentRoom->localUser()));
|
m_reactionModels[eventId] = new ReactionModel(this, res, m_currentRoom->localUser());
|
||||||
} else {
|
} else {
|
||||||
if (m_reactionModels.contains(eventId)) {
|
if (m_reactionModels.contains(eventId)) {
|
||||||
delete m_reactionModels[eventId];
|
delete m_reactionModels[eventId];
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
#include "neochatuser.h"
|
#include <Quotient/user.h>
|
||||||
|
|
||||||
ReactionModel::ReactionModel(QObject *parent, QList<Reaction> reactions, NeoChatUser *localUser)
|
ReactionModel::ReactionModel(QObject *parent, QList<Reaction> reactions, Quotient::User *localUser)
|
||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
, m_localUser(localUser)
|
, m_localUser(localUser)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,10 @@
|
|||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
class NeoChatUser;
|
namespace Quotient
|
||||||
|
{
|
||||||
|
class User;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class ReactionModel
|
* @class ReactionModel
|
||||||
@@ -36,7 +39,7 @@ public:
|
|||||||
HasLocalUser, /**< Whether the local user is in the list of authors. */
|
HasLocalUser, /**< Whether the local user is in the list of authors. */
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit ReactionModel(QObject *parent = nullptr, QList<Reaction> reactions = {}, NeoChatUser *localUser = nullptr);
|
explicit ReactionModel(QObject *parent = nullptr, QList<Reaction> reactions = {}, Quotient::User *localUser = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the given role value at the given index.
|
* @brief Get the given role value at the given index.
|
||||||
@@ -67,6 +70,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
QList<Reaction> m_reactions;
|
QList<Reaction> m_reactions;
|
||||||
|
|
||||||
NeoChatUser *m_localUser;
|
Quotient::User *m_localUser;
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(ReactionModel *)
|
Q_DECLARE_METATYPE(ReactionModel *)
|
||||||
|
|||||||
@@ -5,13 +5,14 @@
|
|||||||
|
|
||||||
#include "messageeventmodel.h"
|
#include "messageeventmodel.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
#include "neochatuser.h"
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
|
||||||
|
#include <Quotient/connection.h>
|
||||||
#include <Quotient/events/stickerevent.h>
|
#include <Quotient/events/stickerevent.h>
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
// TODO search only in the current room
|
// TODO search only in the current room
|
||||||
@@ -19,6 +20,9 @@ using namespace Quotient;
|
|||||||
SearchModel::SearchModel(QObject *parent)
|
SearchModel::SearchModel(QObject *parent)
|
||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
|
connect(static_cast<QGuiApplication *>(QGuiApplication::instance()), &QGuiApplication::paletteChanged, this, [this] {
|
||||||
|
Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0), {AuthorRole, ReadMarkersRole});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SearchModel::searchText() const
|
QString SearchModel::searchText() const
|
||||||
@@ -109,7 +113,7 @@ QVariant SearchModel::data(const QModelIndex &index, int role) const
|
|||||||
return false;
|
return false;
|
||||||
case ReplyAuthorRole:
|
case ReplyAuthorRole:
|
||||||
if (const auto &replyPtr = m_room->getReplyForEvent(event)) {
|
if (const auto &replyPtr = m_room->getReplyForEvent(event)) {
|
||||||
return m_room->getUser(static_cast<NeoChatUser *>(m_room->user(replyPtr->senderId())));
|
return m_room->getUser(m_room->user(replyPtr->senderId()));
|
||||||
} else {
|
} else {
|
||||||
return m_room->getUser(nullptr);
|
return m_room->getUser(nullptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "userlistmodel.h"
|
#include "userlistmodel.h"
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
#include <Quotient/connection.h>
|
||||||
#include <Quotient/events/roompowerlevelsevent.h>
|
#include <Quotient/events/roompowerlevelsevent.h>
|
||||||
|
|
||||||
@@ -14,6 +16,9 @@ UserListModel::UserListModel(QObject *parent)
|
|||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
, m_currentRoom(nullptr)
|
, m_currentRoom(nullptr)
|
||||||
{
|
{
|
||||||
|
connect(static_cast<QGuiApplication *>(QGuiApplication::instance()), &QGuiApplication::paletteChanged, this, [this]() {
|
||||||
|
refreshAllUsers();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserListModel::setRoom(NeoChatRoom *room)
|
void UserListModel::setRoom(NeoChatRoom *room)
|
||||||
@@ -71,8 +76,7 @@ QVariant UserListModel::data(const QModelIndex &index, int role) const
|
|||||||
return user->id();
|
return user->id();
|
||||||
}
|
}
|
||||||
if (role == AvatarRole) {
|
if (role == AvatarRole) {
|
||||||
auto neoChatUser = static_cast<NeoChatUser *>(user);
|
return m_currentRoom->avatarForMember(user);
|
||||||
return m_currentRoom->avatarForMember(neoChatUser);
|
|
||||||
}
|
}
|
||||||
if (role == ObjectRole) {
|
if (role == ObjectRole) {
|
||||||
return QVariant::fromValue(user);
|
return QVariant::fromValue(user);
|
||||||
|
|||||||
@@ -4,8 +4,10 @@
|
|||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QGuiApplication>
|
||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
#include <QMimeDatabase>
|
#include <QMimeDatabase>
|
||||||
|
#include <QPalette>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
|
|
||||||
@@ -13,6 +15,7 @@
|
|||||||
#include <QMediaPlayer>
|
#include <QMediaPlayer>
|
||||||
|
|
||||||
#include <Quotient/jobs/basejob.h>
|
#include <Quotient/jobs/basejob.h>
|
||||||
|
#include <Quotient/user.h>
|
||||||
#include <qcoro/qcorosignal.h>
|
#include <qcoro/qcorosignal.h>
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
#include <Quotient/connection.h>
|
||||||
@@ -43,6 +46,7 @@
|
|||||||
#include "neochatconfig.h"
|
#include "neochatconfig.h"
|
||||||
#include "notificationsmanager.h"
|
#include "notificationsmanager.h"
|
||||||
#include "texthandler.h"
|
#include "texthandler.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include <KConfig>
|
#include <KConfig>
|
||||||
#include <KConfigGroup>
|
#include <KConfigGroup>
|
||||||
@@ -412,11 +416,11 @@ QVariantList NeoChatRoom::getUsers(const QString &keyword, int limit) const
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
for (const auto u : userList) {
|
for (const auto u : userList) {
|
||||||
if (u->displayname(this).contains(keyword, Qt::CaseInsensitive)) {
|
if (u->displayname(this).contains(keyword, Qt::CaseInsensitive)) {
|
||||||
NeoChatUser user(u->id(), u->connection());
|
Quotient::User user(u->id(), u->connection());
|
||||||
QVariantMap userVariant{{QStringLiteral("id"), user.id()},
|
QVariantMap userVariant{{QStringLiteral("id"), user.id()},
|
||||||
{QStringLiteral("displayName"), user.displayname(this)},
|
{QStringLiteral("displayName"), user.displayname(this)},
|
||||||
{QStringLiteral("avatarMediaId"), user.avatarMediaId(this)},
|
{QStringLiteral("avatarMediaId"), user.avatarMediaId(this)},
|
||||||
{QStringLiteral("color"), user.color()}};
|
{QStringLiteral("color"), Utils::getUserColor(user.hueF())}};
|
||||||
|
|
||||||
matchedList.append(QVariant::fromValue(userVariant));
|
matchedList.append(QVariant::fromValue(userVariant));
|
||||||
count++;
|
count++;
|
||||||
@@ -442,11 +446,10 @@ static const QVariantMap emptyUser = {
|
|||||||
|
|
||||||
QVariantMap NeoChatRoom::getUser(const QString &userID) const
|
QVariantMap NeoChatRoom::getUser(const QString &userID) const
|
||||||
{
|
{
|
||||||
NeoChatUser *userObject = static_cast<NeoChatUser *>(user(userID));
|
return getUser(user(userID));
|
||||||
return getUser(userObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap NeoChatRoom::getUser(NeoChatUser *user) const
|
QVariantMap NeoChatRoom::getUser(User *user) const
|
||||||
{
|
{
|
||||||
if (user == nullptr) {
|
if (user == nullptr) {
|
||||||
return emptyUser;
|
return emptyUser;
|
||||||
@@ -458,7 +461,7 @@ QVariantMap NeoChatRoom::getUser(NeoChatUser *user) const
|
|||||||
{QStringLiteral("displayName"), user->displayname(this)},
|
{QStringLiteral("displayName"), user->displayname(this)},
|
||||||
{QStringLiteral("avatarSource"), avatarForMember(user)},
|
{QStringLiteral("avatarSource"), avatarForMember(user)},
|
||||||
{QStringLiteral("avatarMediaId"), user->avatarMediaId(this)},
|
{QStringLiteral("avatarMediaId"), user->avatarMediaId(this)},
|
||||||
{QStringLiteral("color"), user->color()},
|
{QStringLiteral("color"), Utils::getUserColor(user->hueF())},
|
||||||
{QStringLiteral("object"), QVariant::fromValue(user)},
|
{QStringLiteral("object"), QVariant::fromValue(user)},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -539,7 +542,7 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
|
|||||||
|
|
||||||
if (prettyPrint) {
|
if (prettyPrint) {
|
||||||
subjectName = QStringLiteral("<a href=\"https://matrix.to/#/%1\" style=\"color: %2\">%3</a>")
|
subjectName = QStringLiteral("<a href=\"https://matrix.to/#/%1\" style=\"color: %2\">%3</a>")
|
||||||
.arg(e.userId(), static_cast<NeoChatUser *>(user(e.userId()))->color().name(), subjectName);
|
.arg(e.userId(), Utils::getUserColor(user(e.userId())->hueF()).name(), subjectName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The below code assumes senderName output in AuthorRole
|
// The below code assumes senderName output in AuthorRole
|
||||||
@@ -1682,7 +1685,7 @@ QVariantMap NeoChatRoom::chatBoxReplyUser() const
|
|||||||
if (m_chatBoxReplyId.isEmpty()) {
|
if (m_chatBoxReplyId.isEmpty()) {
|
||||||
return emptyUser;
|
return emptyUser;
|
||||||
}
|
}
|
||||||
return getUser(static_cast<NeoChatUser *>(user((*findInTimeline(m_chatBoxReplyId))->senderId())));
|
return getUser(user((*findInTimeline(m_chatBoxReplyId))->senderId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString NeoChatRoom::chatBoxReplyMessage() const
|
QString NeoChatRoom::chatBoxReplyMessage() const
|
||||||
@@ -1698,7 +1701,7 @@ QVariantMap NeoChatRoom::chatBoxEditUser() const
|
|||||||
if (m_chatBoxEditId.isEmpty()) {
|
if (m_chatBoxEditId.isEmpty()) {
|
||||||
return emptyUser;
|
return emptyUser;
|
||||||
}
|
}
|
||||||
return getUser(static_cast<NeoChatUser *>(user((*findInTimeline(m_chatBoxEditId))->senderId())));
|
return getUser(user((*findInTimeline(m_chatBoxEditId))->senderId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString NeoChatRoom::chatBoxEditMessage() const
|
QString NeoChatRoom::chatBoxEditMessage() const
|
||||||
@@ -1904,9 +1907,10 @@ int NeoChatRoom::maxRoomVersion() const
|
|||||||
}
|
}
|
||||||
return maxVersion;
|
return maxVersion;
|
||||||
}
|
}
|
||||||
NeoChatUser *NeoChatRoom::directChatRemoteUser() const
|
|
||||||
|
Quotient::User *NeoChatRoom::directChatRemoteUser() const
|
||||||
{
|
{
|
||||||
return dynamic_cast<NeoChatUser *>(connection()->directChatUsers(this)[0]);
|
return connection()->directChatUsers(this)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void NeoChatRoom::sendLocation(float lat, float lon, const QString &description)
|
void NeoChatRoom::sendLocation(float lat, float lon, const QString &description)
|
||||||
@@ -1938,7 +1942,7 @@ QByteArray NeoChatRoom::roomAcountDataJson(const QString &eventType)
|
|||||||
return QJsonDocument(accountData(eventType)->fullJson()).toJson();
|
return QJsonDocument(accountData(eventType)->fullJson()).toJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl NeoChatRoom::avatarForMember(NeoChatUser *user) const
|
QUrl NeoChatRoom::avatarForMember(Quotient::User *user) const
|
||||||
{
|
{
|
||||||
const auto &url = memberAvatarUrl(user->id());
|
const auto &url = memberAvatarUrl(user->id());
|
||||||
if (url.isEmpty() || url.scheme() != "mxc"_ls) {
|
if (url.isEmpty() || url.scheme() != "mxc"_ls) {
|
||||||
|
|||||||
@@ -10,10 +10,15 @@
|
|||||||
#include <QTextCursor>
|
#include <QTextCursor>
|
||||||
|
|
||||||
#include <QCoroTask>
|
#include <QCoroTask>
|
||||||
|
#include <Quotient/user.h>
|
||||||
|
|
||||||
#include "neochatuser.h"
|
|
||||||
#include "pollhandler.h"
|
#include "pollhandler.h"
|
||||||
|
|
||||||
|
namespace Quotient
|
||||||
|
{
|
||||||
|
class User;
|
||||||
|
}
|
||||||
|
|
||||||
class PushNotificationState : public QObject
|
class PushNotificationState : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -64,7 +69,7 @@ class NeoChatRoom : public Quotient::Room
|
|||||||
*
|
*
|
||||||
* The list does not include the local user.
|
* The list does not include the local user.
|
||||||
*
|
*
|
||||||
* This is different to getting a list of NeoChatUser objects or Quotient::User objects
|
* This is different to getting a list of Quotient::User objects
|
||||||
* as neither of those can provide details like the displayName or avatarMediaId
|
* as neither of those can provide details like the displayName or avatarMediaId
|
||||||
* without the room context as these can vary from room to room. This function
|
* without the room context as these can vary from room to room. This function
|
||||||
* provides the room context and puts the result as a list of QVariantMap objects.
|
* provides the room context and puts the result as a list of QVariantMap objects.
|
||||||
@@ -76,7 +81,7 @@ class NeoChatRoom : public Quotient::Room
|
|||||||
* - displayName - Display name in the context of this room.
|
* - displayName - Display name in the context of this room.
|
||||||
* - display - Name in the context of this room.
|
* - display - Name in the context of this room.
|
||||||
*
|
*
|
||||||
* @sa Quotient::User, NeoChatUser
|
* @sa Quotient::User
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(QVariantList usersTyping READ getUsersTyping NOTIFY typingChanged)
|
Q_PROPERTY(QVariantList usersTyping READ getUsersTyping NOTIFY typingChanged)
|
||||||
|
|
||||||
@@ -119,7 +124,7 @@ class NeoChatRoom : public Quotient::Room
|
|||||||
/**
|
/**
|
||||||
* @brief Get a user object for the other person in a direct chat.
|
* @brief Get a user object for the other person in a direct chat.
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(NeoChatUser *directChatRemoteUser READ directChatRemoteUser CONSTANT)
|
Q_PROPERTY(Quotient::User *directChatRemoteUser READ directChatRemoteUser CONSTANT)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief If the room is a space.
|
* @brief If the room is a space.
|
||||||
@@ -316,7 +321,7 @@ class NeoChatRoom : public Quotient::Room
|
|||||||
/**
|
/**
|
||||||
* @brief Get the user for the message being replied to.
|
* @brief Get the user for the message being replied to.
|
||||||
*
|
*
|
||||||
* This is different to getting a NeoChatUser object or Quotient::User object
|
* This is different to getting a Quotient::User object
|
||||||
* as neither of those can provide details like the displayName or avatarMediaId
|
* as neither of those can provide details like the displayName or avatarMediaId
|
||||||
* without the room context as these can vary from room to room.
|
* without the room context as these can vary from room to room.
|
||||||
*
|
*
|
||||||
@@ -329,9 +334,9 @@ class NeoChatRoom : public Quotient::Room
|
|||||||
* - avatarSource - The mxc URL for the user's avatar in the current room.
|
* - avatarSource - The mxc URL for the user's avatar in the current room.
|
||||||
* - avatarMediaId - Avatar id in the context of this room.
|
* - avatarMediaId - Avatar id in the context of this room.
|
||||||
* - color - Color for the user.
|
* - color - Color for the user.
|
||||||
* - object - The NeoChatUser object for the user.
|
* - object - The Quotient::User object for the user.
|
||||||
*
|
*
|
||||||
* @sa getUser, Quotient::User, NeoChatUser
|
* @sa getUser, Quotient::User
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(QVariantMap chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged)
|
Q_PROPERTY(QVariantMap chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged)
|
||||||
|
|
||||||
@@ -345,7 +350,7 @@ class NeoChatRoom : public Quotient::Room
|
|||||||
/**
|
/**
|
||||||
* @brief Get the user for the message being edited.
|
* @brief Get the user for the message being edited.
|
||||||
*
|
*
|
||||||
* This is different to getting a NeoChatUser object or Quotient::User object
|
* This is different to getting a Quotient::User object
|
||||||
* as neither of those can provide details like the displayName or avatarMediaId
|
* as neither of those can provide details like the displayName or avatarMediaId
|
||||||
* without the room context as these can vary from room to room.
|
* without the room context as these can vary from room to room.
|
||||||
*
|
*
|
||||||
@@ -358,9 +363,9 @@ class NeoChatRoom : public Quotient::Room
|
|||||||
* - avatarSource - The mxc URL for the user's avatar in the current room.
|
* - avatarSource - The mxc URL for the user's avatar in the current room.
|
||||||
* - avatarMediaId - Avatar id in the context of this room.
|
* - avatarMediaId - Avatar id in the context of this room.
|
||||||
* - color - Color for the user.
|
* - color - Color for the user.
|
||||||
* - object - The NeoChatUser object for the user.
|
* - object - The Quotient::User object for the user.
|
||||||
*
|
*
|
||||||
* @sa getUser, Quotient::User, NeoChatUser
|
* @sa getUser, Quotient::User
|
||||||
*/
|
*/
|
||||||
Q_PROPERTY(QVariantMap chatBoxEditUser READ chatBoxEditUser NOTIFY chatBoxEditIdChanged)
|
Q_PROPERTY(QVariantMap chatBoxEditUser READ chatBoxEditUser NOTIFY chatBoxEditIdChanged)
|
||||||
|
|
||||||
@@ -392,7 +397,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Get a list of users in the context of this room.
|
* @brief Get a list of users in the context of this room.
|
||||||
*
|
*
|
||||||
* This is different to getting a list of NeoChatUser objects or Quotient::User objects
|
* This is different to getting a list of Quotient::User objects
|
||||||
* as neither of those can provide details like the displayName or avatarMediaId
|
* as neither of those can provide details like the displayName or avatarMediaId
|
||||||
* without the room context as these can vary from room to room. This function
|
* without the room context as these can vary from room to room. This function
|
||||||
* provides the room context and returns the result as a list of QVariantMap objects.
|
* provides the room context and returns the result as a list of QVariantMap objects.
|
||||||
@@ -407,14 +412,14 @@ public:
|
|||||||
* - avatarMediaId - Avatar id in the context of this room.
|
* - avatarMediaId - Avatar id in the context of this room.
|
||||||
* - color - Color for the user.
|
* - color - Color for the user.
|
||||||
*
|
*
|
||||||
* @sa Quotient::User, NeoChatUser
|
* @sa Quotient::User
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE [[nodiscard]] QVariantList getUsers(const QString &keyword, int limit = -1) const;
|
Q_INVOKABLE [[nodiscard]] QVariantList getUsers(const QString &keyword, int limit = -1) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a user in the context of this room.
|
* @brief Get a user in the context of this room.
|
||||||
*
|
*
|
||||||
* This is different to getting a NeoChatUser object or Quotient::User object
|
* This is different to getting a Quotient::User object
|
||||||
* as neither of those can provide details like the displayName or avatarMediaId
|
* as neither of those can provide details like the displayName or avatarMediaId
|
||||||
* without the room context as these can vary from room to room. This function
|
* without the room context as these can vary from room to room. This function
|
||||||
* provides the room context and outputs the result as QVariantMap.
|
* provides the room context and outputs the result as QVariantMap.
|
||||||
@@ -431,16 +436,16 @@ public:
|
|||||||
* - avatarSource - The mxc URL for the user's avatar in the current room.
|
* - avatarSource - The mxc URL for the user's avatar in the current room.
|
||||||
* - avatarMediaId - Avatar id in the context of this room.
|
* - avatarMediaId - Avatar id in the context of this room.
|
||||||
* - color - Color for the user.
|
* - color - Color for the user.
|
||||||
* - object - The NeoChatUser object for the user.
|
* - object - The Quotient::User object for the user.
|
||||||
*
|
*
|
||||||
* @sa Quotient::User, NeoChatUser
|
* @sa Quotient::User
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE [[nodiscard]] QVariantMap getUser(const QString &userID) const;
|
Q_INVOKABLE [[nodiscard]] QVariantMap getUser(const QString &userID) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a user in the context of this room.
|
* @brief Get a user in the context of this room.
|
||||||
*
|
*
|
||||||
* This is different to getting a NeoChatUser object or Quotient::User object
|
* This is different to getting a Quotient::User object
|
||||||
* as neither of those can provide details like the displayName or avatarMediaId
|
* as neither of those can provide details like the displayName or avatarMediaId
|
||||||
* without the room context as these can vary from room to room. This function
|
* without the room context as these can vary from room to room. This function
|
||||||
* provides the room context and outputs the result as QVariantMap.
|
* provides the room context and outputs the result as QVariantMap.
|
||||||
@@ -457,11 +462,11 @@ public:
|
|||||||
* - avatarSource - The mxc URL for the user's avatar in the current room.
|
* - avatarSource - The mxc URL for the user's avatar in the current room.
|
||||||
* - avatarMediaId - Avatar id in the context of this room.
|
* - avatarMediaId - Avatar id in the context of this room.
|
||||||
* - color - Color for the user.
|
* - color - Color for the user.
|
||||||
* - object - The NeoChatUser object for the user.
|
* - object - The Quotient::User object for the user.
|
||||||
*
|
*
|
||||||
* @sa Quotient::User, NeoChatUser
|
* @sa Quotient::User
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE [[nodiscard]] QVariantMap getUser(NeoChatUser *user) const;
|
Q_INVOKABLE [[nodiscard]] QVariantMap getUser(Quotient::User *user) const;
|
||||||
|
|
||||||
[[nodiscard]] QVariantList getUsersTyping() const;
|
[[nodiscard]] QVariantList getUsersTyping() const;
|
||||||
|
|
||||||
@@ -602,7 +607,7 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] QString avatarMediaId() const;
|
[[nodiscard]] QString avatarMediaId() const;
|
||||||
|
|
||||||
NeoChatUser *directChatRemoteUser() const;
|
Quotient::User *directChatRemoteUser() const;
|
||||||
|
|
||||||
[[nodiscard]] bool isSpace();
|
[[nodiscard]] bool isSpace();
|
||||||
|
|
||||||
@@ -818,7 +823,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
Q_INVOKABLE QByteArray roomAcountDataJson(const QString &eventType);
|
Q_INVOKABLE QByteArray roomAcountDataJson(const QString &eventType);
|
||||||
|
|
||||||
Q_INVOKABLE [[nodiscard]] QUrl avatarForMember(NeoChatUser *user) const;
|
Q_INVOKABLE [[nodiscard]] QUrl avatarForMember(Quotient::User *user) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the event that is being replied to. This includes events that were manually loaded using NeoChatRoom::loadReply.
|
* @brief Returns the event that is being replied to. This includes events that were manually loaded using NeoChatRoom::loadReply.
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2019 Black Hat <bhat@encom.eu.org>
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
|
|
||||||
#include "neochatuser.h"
|
|
||||||
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QPalette>
|
|
||||||
|
|
||||||
#include <Quotient/connection.h>
|
|
||||||
|
|
||||||
using namespace Quotient;
|
|
||||||
|
|
||||||
NeoChatUser::NeoChatUser(QString userId, Connection *connection)
|
|
||||||
: User(std::move(userId), connection)
|
|
||||||
{
|
|
||||||
connect(static_cast<QGuiApplication *>(QGuiApplication::instance()), &QGuiApplication::paletteChanged, this, &NeoChatUser::polishColor);
|
|
||||||
polishColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor NeoChatUser::color()
|
|
||||||
{
|
|
||||||
return m_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NeoChatUser::setColor(const QColor &color)
|
|
||||||
{
|
|
||||||
if (m_color == color) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_color = color;
|
|
||||||
Q_EMIT colorChanged(m_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NeoChatUser::polishColor()
|
|
||||||
{
|
|
||||||
const auto lightness = static_cast<QGuiApplication *>(QGuiApplication::instance())->palette().color(QPalette::Active, QPalette::Window).lightnessF();
|
|
||||||
// https://github.com/quotient-im/libQuotient/wiki/User-color-coding-standard-draft-proposal
|
|
||||||
setColor(QColor::fromHslF(hueF(), 1, -0.7 * lightness + 0.9, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "moc_neochatuser.cpp"
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2018-2019 Black Hat <bhat@encom.eu.org>
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
#include <Quotient/user.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class NeoChatUser
|
|
||||||
*
|
|
||||||
* A class inherited from Quotient::User to add a user color function.
|
|
||||||
*
|
|
||||||
* @sa Quotient::User
|
|
||||||
*/
|
|
||||||
class NeoChatUser : public Quotient::User
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The color to use for the user.
|
|
||||||
*/
|
|
||||||
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
|
|
||||||
public:
|
|
||||||
explicit NeoChatUser(QString userId, Quotient::Connection *connection);
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
QColor color();
|
|
||||||
void setColor(const QColor &color);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void colorChanged(QColor _t1);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QColor m_color;
|
|
||||||
|
|
||||||
void polishColor();
|
|
||||||
};
|
|
||||||
@@ -293,12 +293,7 @@ QPixmap NotificationsManager::createNotificationImage(const QImage &icon, NeoCha
|
|||||||
roundedImage.fill(Qt::transparent);
|
roundedImage.fill(Qt::transparent);
|
||||||
|
|
||||||
QPainter painter(&roundedImage);
|
QPainter painter(&roundedImage);
|
||||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
painter.setPen(Qt::NoPen);
|
|
||||||
|
|
||||||
// Fill background for transparent avatars
|
|
||||||
painter.setBrush(Qt::white);
|
|
||||||
painter.drawRoundedRect(imageRect, imageRect.width(), imageRect.height());
|
|
||||||
|
|
||||||
QBrush brush(icon.scaledToHeight(biggestDimension));
|
QBrush brush(icon.scaledToHeight(biggestDimension));
|
||||||
painter.setBrush(brush);
|
painter.setBrush(brush);
|
||||||
@@ -309,9 +304,6 @@ QPixmap NotificationsManager::createNotificationImage(const QImage &icon, NeoCha
|
|||||||
if (icon != roomAvatar) {
|
if (icon != roomAvatar) {
|
||||||
const QRect lowerQuarter{imageRect.center(), imageRect.size() / 2};
|
const QRect lowerQuarter{imageRect.center(), imageRect.size() / 2};
|
||||||
|
|
||||||
painter.setBrush(Qt::white);
|
|
||||||
painter.drawRoundedRect(lowerQuarter, lowerQuarter.width(), lowerQuarter.height());
|
|
||||||
|
|
||||||
painter.setBrush(roomAvatar.scaled(lowerQuarter.size()));
|
painter.setBrush(roomAvatar.scaled(lowerQuarter.size()));
|
||||||
painter.drawRoundedRect(lowerQuarter, lowerQuarter.width(), lowerQuarter.height());
|
painter.drawRoundedRect(lowerQuarter, lowerQuarter.width(), lowerQuarter.height());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ Delegates.RoundedItemDelegate {
|
|||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
acceptedDevices: PointerDevice.Mouse
|
acceptedDevices: PointerDevice.Mouse
|
||||||
grabPermissions: PointerHandler.TakeOverForbidden
|
|
||||||
gesturePolicy: TapHandler.WithinBounds
|
|
||||||
onTapped: root.contextMenuRequested()
|
onTapped: root.contextMenuRequested()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ QQC2.Control {
|
|||||||
/**
|
/**
|
||||||
* @brief The current room that user is viewing.
|
* @brief The current room that user is viewing.
|
||||||
*/
|
*/
|
||||||
property NeoChatRoom currentRoom
|
required property NeoChatRoom currentRoom
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The QQC2.TextArea object.
|
* @brief The QQC2.TextArea object.
|
||||||
@@ -55,10 +55,10 @@ QQC2.Control {
|
|||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
id: attachmentAction
|
id: attachmentAction
|
||||||
|
|
||||||
property bool isBusy: currentRoom && currentRoom.hasFileUploading
|
property bool isBusy: root.currentRoom && root.currentRoom.hasFileUploading
|
||||||
|
|
||||||
// Matrix does not allow sending attachments in replies
|
// Matrix does not allow sending attachments in replies
|
||||||
visible: currentRoom.chatBoxReplyId.length === 0 && currentRoom.chatBoxAttachmentPath.length === 0
|
visible: root.currentRoom.chatBoxReplyId.length === 0 && root.currentRoom.chatBoxAttachmentPath.length === 0
|
||||||
icon.name: "mail-attachment"
|
icon.name: "mail-attachment"
|
||||||
text: i18n("Attach an image or file")
|
text: i18n("Attach an image or file")
|
||||||
displayHint: Kirigami.DisplayHint.IconOnly
|
displayHint: Kirigami.DisplayHint.IconOnly
|
||||||
@@ -72,7 +72,7 @@ QQC2.Control {
|
|||||||
if (!path) {
|
if (!path) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentRoom.chatBoxAttachmentPath = path;
|
root.currentRoom.chatBoxAttachmentPath = path;
|
||||||
})
|
})
|
||||||
fileDialog.open()
|
fileDialog.open()
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,6 @@ QQC2.Control {
|
|||||||
emojiDialog.open()
|
emojiDialog.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tooltip: text
|
|
||||||
},
|
},
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
id: mapButton
|
id: mapButton
|
||||||
@@ -107,9 +106,8 @@ QQC2.Control {
|
|||||||
displayHint: QQC2.AbstractButton.IconOnly
|
displayHint: QQC2.AbstractButton.IconOnly
|
||||||
|
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
locationChooserComponent.createObject(QQC2.ApplicationWindow.overlay, {room: currentRoom}).open()
|
locationChooserComponent.createObject(QQC2.ApplicationWindow.overlay, {room: root.currentRoom}).open()
|
||||||
}
|
}
|
||||||
tooltip: text
|
|
||||||
},
|
},
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
id: sendAction
|
id: sendAction
|
||||||
@@ -164,10 +162,12 @@ QQC2.Control {
|
|||||||
leftPadding: LayoutMirroring.enabled ? actionsRow.width : Kirigami.Units.largeSpacing
|
leftPadding: LayoutMirroring.enabled ? actionsRow.width : Kirigami.Units.largeSpacing
|
||||||
rightPadding: LayoutMirroring.enabled ? Kirigami.Units.largeSpacing : actionsRow.width + x * 2 + Kirigami.Units.largeSpacing * 2
|
rightPadding: LayoutMirroring.enabled ? Kirigami.Units.largeSpacing : actionsRow.width + x * 2 + Kirigami.Units.largeSpacing * 2
|
||||||
|
|
||||||
placeholderText: readOnly ? i18n("This room is encrypted. Build libQuotient with encryption enabled to send encrypted messages.") : currentRoom.usesEncryption ? i18n("Send an encrypted message…") : currentRoom.chatBoxAttachmentPath.length > 0 ? i18n("Set an attachment caption...") : i18n("Send a message…")
|
placeholderText: readOnly ? i18n("This room is encrypted. Build libQuotient with encryption enabled to send encrypted messages.") : root.currentRoom.usesEncryption ? i18n("Send an encrypted message…") : root.currentRoom.chatBoxAttachmentPath.length > 0 ? i18n("Set an attachment caption...") : i18n("Send a message…")
|
||||||
verticalAlignment: TextEdit.AlignVCenter
|
verticalAlignment: TextEdit.AlignVCenter
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
readOnly: (currentRoom.usesEncryption && !Controller.encryptionSupported)
|
readOnly: (root.currentRoom.usesEncryption && !Controller.encryptionSupported)
|
||||||
|
|
||||||
|
Accessible.description: placeholderText
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: repeatTimer
|
id: repeatTimer
|
||||||
@@ -177,10 +177,10 @@ QQC2.Control {
|
|||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
if (!repeatTimer.running && Config.typingNotifications) {
|
if (!repeatTimer.running && Config.typingNotifications) {
|
||||||
var textExists = text.length > 0
|
var textExists = text.length > 0
|
||||||
currentRoom.sendTypingNotification(textExists)
|
root.currentRoom.sendTypingNotification(textExists)
|
||||||
textExists ? repeatTimer.start() : repeatTimer.stop()
|
textExists ? repeatTimer.start() : repeatTimer.stop()
|
||||||
}
|
}
|
||||||
currentRoom.chatBoxText = text
|
root.currentRoom.chatBoxText = text
|
||||||
}
|
}
|
||||||
onCursorRectangleChanged: chatBarScrollView.ensureVisible(cursorRectangle)
|
onCursorRectangleChanged: chatBarScrollView.ensureVisible(cursorRectangle)
|
||||||
onSelectedTextChanged: {
|
onSelectedTextChanged: {
|
||||||
@@ -207,7 +207,7 @@ QQC2.Control {
|
|||||||
remove(cursorPosition, cursorPosition + 1)
|
remove(cursorPosition, cursorPosition + 1)
|
||||||
}
|
}
|
||||||
if (textField.text == selectedText || textField.text.length <= 1) {
|
if (textField.text == selectedText || textField.text.length <= 1) {
|
||||||
currentRoom.sendTypingNotification(false)
|
root.currentRoom.sendTypingNotification(false)
|
||||||
repeatTimer.stop()
|
repeatTimer.stop()
|
||||||
}
|
}
|
||||||
if (quickFormatBar.visible) {
|
if (quickFormatBar.visible) {
|
||||||
@@ -237,20 +237,20 @@ QQC2.Control {
|
|||||||
completionMenu.complete()
|
completionMenu.complete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Keys.onPressed: (event) => {
|
Keys.onPressed: {
|
||||||
if (event.key === Qt.Key_V && event.modifiers & Qt.ControlModifier) {
|
if (event.key === Qt.Key_V && event.modifiers & Qt.ControlModifier) {
|
||||||
event.accepted = root.pasteImage();
|
root.pasteImage();
|
||||||
} else if (event.key === Qt.Key_Up && event.modifiers & Qt.ControlModifier) {
|
} else if (event.key === Qt.Key_Up && event.modifiers & Qt.ControlModifier) {
|
||||||
currentRoom.replyLastMessage();
|
root.currentRoom.replyLastMessage();
|
||||||
} else if (event.key === Qt.Key_Up && textField.text.length === 0) {
|
} else if (event.key === Qt.Key_Up && textField.text.length === 0) {
|
||||||
currentRoom.editLastMessage();
|
root.currentRoom.editLastMessage();
|
||||||
} else if (event.key === Qt.Key_Up && completionMenu.visible) {
|
} else if (event.key === Qt.Key_Up && completionMenu.visible) {
|
||||||
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) {
|
} else if (event.key === Qt.Key_Backspace) {
|
||||||
if (textField.text == selectedText || textField.text.length <= 1) {
|
if (textField.text == selectedText || textField.text.length <= 1) {
|
||||||
currentRoom.sendTypingNotification(false)
|
root.currentRoom.sendTypingNotification(false)
|
||||||
repeatTimer.stop()
|
repeatTimer.stop()
|
||||||
}
|
}
|
||||||
if (quickFormatBar.visible && selectedText.length > 0) {
|
if (quickFormatBar.visible && selectedText.length > 0) {
|
||||||
@@ -282,19 +282,19 @@ QQC2.Control {
|
|||||||
Component {
|
Component {
|
||||||
id: replyPane
|
id: replyPane
|
||||||
ReplyPane {
|
ReplyPane {
|
||||||
userName: currentRoom.chatBoxReplyUser.displayName
|
userName: root.currentRoom.chatBoxReplyUser.displayName
|
||||||
userColor: currentRoom.chatBoxReplyUser.color
|
userColor: root.currentRoom.chatBoxReplyUser.color
|
||||||
userAvatar: currentRoom.chatBoxReplyUser.avatarSource
|
userAvatar: root.currentRoom.chatBoxReplyUser.avatarSource
|
||||||
text: currentRoom.chatBoxReplyMessage
|
text: root.currentRoom.chatBoxReplyMessage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
id: attachmentPane
|
id: attachmentPane
|
||||||
AttachmentPane {
|
AttachmentPane {
|
||||||
attachmentPath: currentRoom.chatBoxAttachmentPath
|
attachmentPath: root.currentRoom.chatBoxAttachmentPath
|
||||||
|
|
||||||
onAttachmentCancelled: {
|
onAttachmentCancelled: {
|
||||||
currentRoom.chatBoxAttachmentPath = "";
|
root.currentRoom.chatBoxAttachmentPath = "";
|
||||||
root.forceActiveFocus()
|
root.forceActiveFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,8 +346,8 @@ QQC2.Control {
|
|||||||
text: i18nc("@action:button", "Cancel reply")
|
text: i18nc("@action:button", "Cancel reply")
|
||||||
icon.name: "dialog-close"
|
icon.name: "dialog-close"
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
currentRoom.chatBoxReplyId = "";
|
root.currentRoom.chatBoxReplyId = "";
|
||||||
currentRoom.chatBoxAttachmentPath = "";
|
root.currentRoom.chatBoxAttachmentPath = "";
|
||||||
root.forceActiveFocus()
|
root.forceActiveFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,12 +384,11 @@ QQC2.Control {
|
|||||||
|
|
||||||
QQC2.ToolTip.visible: modelData.tooltip !== "" && hoverHandler.hovered
|
QQC2.ToolTip.visible: modelData.tooltip !== "" && hoverHandler.hovered
|
||||||
QQC2.ToolTip.text: modelData.tooltip
|
QQC2.ToolTip.text: modelData.tooltip
|
||||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
|
||||||
HoverHandler { id: hoverHandler }
|
HoverHandler { id: hoverHandler }
|
||||||
|
|
||||||
PieProgressBar {
|
PieProgressBar {
|
||||||
visible: modelData.isBusy
|
visible: modelData.isBusy
|
||||||
progress: currentRoom.fileUploadingProgress
|
progress: root.currentRoom.fileUploadingProgress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -404,6 +403,8 @@ QQC2.Control {
|
|||||||
includeCustom: true
|
includeCustom: true
|
||||||
closeOnChosen: false
|
closeOnChosen: false
|
||||||
|
|
||||||
|
currentRoom: root.currentRoom
|
||||||
|
|
||||||
onChosen: insertText(emoji)
|
onChosen: insertText(emoji)
|
||||||
onClosed: if (emojiButton.checked) emojiButton.checked = false
|
onClosed: if (emojiButton.checked) emojiButton.checked = false
|
||||||
}
|
}
|
||||||
@@ -467,18 +468,17 @@ QQC2.Control {
|
|||||||
function pasteImage() {
|
function pasteImage() {
|
||||||
let localPath = Clipboard.saveImage();
|
let localPath = Clipboard.saveImage();
|
||||||
if (localPath.length === 0) {
|
if (localPath.length === 0) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
root.currentRoom.chatBoxAttachmentPath = localPath;
|
root.currentRoom.chatBoxAttachmentPath = localPath
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function postMessage() {
|
function postMessage() {
|
||||||
actionsHandler.handleNewMessage();
|
actionsHandler.handleNewMessage();
|
||||||
repeatTimer.stop()
|
repeatTimer.stop()
|
||||||
currentRoom.markAllMessagesAsRead();
|
root.currentRoom.markAllMessagesAsRead();
|
||||||
textField.clear();
|
textField.clear();
|
||||||
currentRoom.chatBoxReplyId = "";
|
root.currentRoom.chatBoxReplyId = "";
|
||||||
messageSent()
|
messageSent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ import org.kde.neochat 1.0
|
|||||||
* @sa ChatBar
|
* @sa ChatBar
|
||||||
*/
|
*/
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: chatBox
|
id: root
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The current room that user is viewing.
|
* @brief The current room that user is viewing.
|
||||||
*/
|
*/
|
||||||
property NeoChatRoom currentRoom
|
required property NeoChatRoom currentRoom
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A message has been sent from the chat bar.
|
* @brief A message has been sent from the chat bar.
|
||||||
@@ -63,7 +63,7 @@ ColumnLayout {
|
|||||||
ChatBar {
|
ChatBar {
|
||||||
id: chatBar
|
id: chatBar
|
||||||
|
|
||||||
visible: currentRoom.canSendEvent("m.room.message")
|
visible: root.currentRoom.canSendEvent("m.room.message")
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.minimumHeight: Math.max(Kirigami.Units.gridUnit * 2, implicitHeight + Kirigami.Units.largeSpacing)
|
Layout.minimumHeight: Math.max(Kirigami.Units.gridUnit * 2, implicitHeight + Kirigami.Units.largeSpacing)
|
||||||
@@ -78,7 +78,7 @@ ColumnLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMessageSent: {
|
onMessageSent: {
|
||||||
chatBox.messageSent();
|
root.messageSent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,14 @@ import org.kde.neochat 1.0
|
|||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The current room that user is viewing.
|
||||||
|
*/
|
||||||
|
property NeoChatRoom currentRoom
|
||||||
|
|
||||||
property bool includeCustom: false
|
property bool includeCustom: false
|
||||||
property bool showQuickReaction: false
|
property bool showQuickReaction: false
|
||||||
|
property NeoChatRoom currentRoom
|
||||||
|
|
||||||
readonly property var currentEmojiModel: {
|
readonly property var currentEmojiModel: {
|
||||||
if (includeCustom) {
|
if (includeCustom) {
|
||||||
@@ -151,7 +157,7 @@ ColumnLayout {
|
|||||||
|
|
||||||
ImagePacksModel {
|
ImagePacksModel {
|
||||||
id: stickerPackModel
|
id: stickerPackModel
|
||||||
room: currentRoom
|
room: root.currentRoom
|
||||||
showStickers: true
|
showStickers: true
|
||||||
showEmoticons: false
|
showEmoticons: false
|
||||||
}
|
}
|
||||||
@@ -160,7 +166,7 @@ ColumnLayout {
|
|||||||
id: stickerModel
|
id: stickerModel
|
||||||
model: stickerPackModel
|
model: stickerPackModel
|
||||||
packIndex: 0
|
packIndex: 0
|
||||||
room: currentRoom
|
room: root.currentRoom
|
||||||
}
|
}
|
||||||
|
|
||||||
EmoticonFilterModel {
|
EmoticonFilterModel {
|
||||||
|
|||||||
@@ -26,20 +26,14 @@ QQC2.Popup {
|
|||||||
padding: 2
|
padding: 2
|
||||||
modal: true
|
modal: true
|
||||||
dim: true
|
dim: true
|
||||||
clip: false
|
|
||||||
onOpened: x = Math.min(parent.mapFromGlobal(QQC2.Overlay.overlay.width - tones.width, 0).x, -(width - parent.width) / 2)
|
onOpened: x = Math.min(parent.mapFromGlobal(QQC2.Overlay.overlay.width - tones.width, 0).x, -(width - parent.width) / 2)
|
||||||
background: Kirigami.ShadowedRectangle {
|
background: Kirigami.ShadowedRectangle {
|
||||||
color: Kirigami.Theme.backgroundColor
|
color: Kirigami.Theme.backgroundColor
|
||||||
radius: Kirigami.Units.mediumSpacing
|
radius: Kirigami.Units.smallSpacing
|
||||||
shadow {
|
shadow.size: Kirigami.Units.smallSpacing
|
||||||
size: Kirigami.Units.largeSpacing
|
shadow.color: Qt.rgba(0.0, 0.0, 0.0, 0.10)
|
||||||
color: Qt.rgba(0.0, 0.0, 0.0, 0.3)
|
border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15)
|
||||||
yOffset: 2
|
border.width: 1
|
||||||
}
|
|
||||||
border {
|
|
||||||
color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15)
|
|
||||||
width: 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ ApplicationWindow {
|
|||||||
asset: root.asset
|
asset: root.asset
|
||||||
author: root.author
|
author: root.author
|
||||||
isLive: true
|
isLive: true
|
||||||
|
heading: NaN
|
||||||
visible: !isNaN(root.latitude) && !isNaN(root.longitude)
|
visible: !isNaN(root.latitude) && !isNaN(root.longitude)
|
||||||
}
|
}
|
||||||
MapItemView {
|
MapItemView {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ 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.neochat 1.0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A component that provides a set of actions when a message is hovered in the timeline.
|
* @brief A component that provides a set of actions when a message is hovered in the timeline.
|
||||||
@@ -16,6 +17,11 @@ import org.kde.kirigami 2.15 as Kirigami
|
|||||||
QQC2.Control {
|
QQC2.Control {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The current room that user is viewing.
|
||||||
|
*/
|
||||||
|
required property NeoChatRoom currentRoom
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Whether the actions should be shown.
|
* @brief Whether the actions should be shown.
|
||||||
*/
|
*/
|
||||||
@@ -108,6 +114,7 @@ QQC2.Control {
|
|||||||
|
|
||||||
EmojiDialog {
|
EmojiDialog {
|
||||||
id: emojiDialog
|
id: emojiDialog
|
||||||
|
currentRoom: root.currentRoom
|
||||||
showQuickReaction: true
|
showQuickReaction: true
|
||||||
onChosen: (emoji) => root.reactClicked(emoji)
|
onChosen: (emoji) => root.reactClicked(emoji)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,11 +24,14 @@ MapQuickItem {
|
|||||||
|
|
||||||
required property bool isLive
|
required property bool isLive
|
||||||
|
|
||||||
|
required property real heading
|
||||||
|
|
||||||
anchorPoint.x: sourceItem.width / 2
|
anchorPoint.x: sourceItem.width / 2
|
||||||
anchorPoint.y: sourceItem.height
|
anchorPoint.y: sourceItem.height
|
||||||
coordinate: QtPositioning.coordinate(root.latitude, root.longitude)
|
coordinate: QtPositioning.coordinate(root.latitude, root.longitude)
|
||||||
autoFadeIn: false
|
autoFadeIn: false
|
||||||
sourceItem: Kirigami.Icon {
|
sourceItem: Kirigami.Icon {
|
||||||
|
id: mainIcon
|
||||||
width: height
|
width: height
|
||||||
height: Kirigami.Units.iconSizes.huge
|
height: Kirigami.Units.iconSizes.huge
|
||||||
source: "gps"
|
source: "gps"
|
||||||
@@ -55,5 +58,19 @@ MapQuickItem {
|
|||||||
source: root.author.avatarSource
|
source: root.author.avatarSource
|
||||||
color: root.author.color
|
color: root.author.color
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Kirigami.Icon {
|
||||||
|
id: headingIcon
|
||||||
|
source: "go-up-symbolic"
|
||||||
|
color: parent.color
|
||||||
|
visible: !isNaN(root.heading) && root.isLive
|
||||||
|
anchors.bottom: mainIcon.top
|
||||||
|
anchors.horizontalCenter: mainIcon.horizontalCenter
|
||||||
|
transform: Rotation {
|
||||||
|
origin.x: headingIcon.width/2
|
||||||
|
origin.y: headingIcon.height + mainIcon.height/2
|
||||||
|
angle: root.heading
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ Kirigami.Page {
|
|||||||
}
|
}
|
||||||
delegate: LocationMapItem {
|
delegate: LocationMapItem {
|
||||||
isLive: true
|
isLive: true
|
||||||
|
heading: NaN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ LoginStep {
|
|||||||
id: matrixIdField
|
id: matrixIdField
|
||||||
Kirigami.FormData.label: i18n("Matrix ID:")
|
Kirigami.FormData.label: i18n("Matrix ID:")
|
||||||
placeholderText: "@user:matrix.org"
|
placeholderText: "@user:matrix.org"
|
||||||
|
Accessible.name: i18n("Matrix ID")
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
LoginHelper.matrixId = text
|
LoginHelper.matrixId = text
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ LoginStep {
|
|||||||
id: passwordField
|
id: passwordField
|
||||||
onTextChanged: LoginHelper.password = text
|
onTextChanged: LoginHelper.password = text
|
||||||
enabled: !LoginHelper.isLoggingIn
|
enabled: !LoginHelper.isLoggingIn
|
||||||
|
Accessible.name: i18n("Password")
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
passwordField.forceActiveFocus()
|
passwordField.forceActiveFocus()
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ TimelineContainer {
|
|||||||
asset: root.asset
|
asset: root.asset
|
||||||
author: root.author
|
author: root.author
|
||||||
isLive: true
|
isLive: true
|
||||||
|
heading: NaN
|
||||||
}
|
}
|
||||||
|
|
||||||
TapHandler {
|
TapHandler {
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ TimelineContainer {
|
|||||||
isReply: root.isReply
|
isReply: root.isReply
|
||||||
|
|
||||||
textMessage: root.display
|
textMessage: root.display
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
enabled: !label.hoveredLink
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onLongPressed: root.openContextMenu()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loader {
|
Loader {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ Item {
|
|||||||
* - displayName - The display name of the reply author.
|
* - displayName - The display name of the reply author.
|
||||||
* - display - The name of the reply author.
|
* - display - The name of the reply author.
|
||||||
* - color - The color for the reply author.
|
* - color - The color for the reply author.
|
||||||
* - object - The NeoChatUser object for the reply author.
|
* - object - The Quotient::User object for the reply author.
|
||||||
*
|
*
|
||||||
* @sa NeoChatUser
|
* @sa Quotient::User
|
||||||
*/
|
*/
|
||||||
required property var author
|
required property var author
|
||||||
|
|
||||||
|
|||||||
@@ -27,12 +27,7 @@ TextEdit {
|
|||||||
/**
|
/**
|
||||||
* @brief Regex for detecting a message with a single emoji.
|
* @brief Regex for detecting a message with a single emoji.
|
||||||
*/
|
*/
|
||||||
readonly property var isEmojiRegex: /^(<span style='.*'>)?(\u00a9|\u00ae|[\u20D0-\u2fff]|[\u3190-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])+(<\/span>)?$/
|
readonly property var isEmoji: /^(<span style='.*'>)?(\u00a9|\u00ae|[\u20D0-\u2fff]|[\u3190-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])+(<\/span>)?$/
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Whether the message is an emoji
|
|
||||||
*/
|
|
||||||
readonly property var isEmoji: isEmojiRegex.test(textMessage)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Regex for detecting a message with a spoiler.
|
* @brief Regex for detecting a message with a spoiler.
|
||||||
@@ -90,10 +85,7 @@ a{
|
|||||||
color: Kirigami.Theme.textColor
|
color: Kirigami.Theme.textColor
|
||||||
selectedTextColor: Kirigami.Theme.highlightedTextColor
|
selectedTextColor: Kirigami.Theme.highlightedTextColor
|
||||||
selectionColor: Kirigami.Theme.highlightColor
|
selectionColor: Kirigami.Theme.highlightColor
|
||||||
font {
|
font.pointSize: !root.isReply && isEmoji.test(textMessage) ? Kirigami.Theme.defaultFont.pointSize * 4 : Kirigami.Theme.defaultFont.pointSize
|
||||||
pointSize: !root.isReply && root.isEmoji ? Kirigami.Theme.defaultFont.pointSize * 4 : Kirigami.Theme.defaultFont.pointSize
|
|
||||||
family: root.isEmoji ? 'emoji' : Kirigami.Theme.defaultFont.family
|
|
||||||
}
|
|
||||||
selectByMouse: !Kirigami.Settings.isMobile
|
selectByMouse: !Kirigami.Settings.isMobile
|
||||||
readOnly: true
|
readOnly: true
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
|
|||||||
@@ -54,9 +54,9 @@ ColumnLayout {
|
|||||||
* - displayName - The display name of the author.
|
* - displayName - The display name of the author.
|
||||||
* - display - The name of the author.
|
* - display - The name of the author.
|
||||||
* - color - The color for the author.
|
* - color - The color for the author.
|
||||||
* - object - The NeoChatUser object for the author.
|
* - object - The Quotient::User object for the author.
|
||||||
*
|
*
|
||||||
* @sa NeoChatUser
|
* @sa Quotient::User
|
||||||
*/
|
*/
|
||||||
required property var author
|
required property var author
|
||||||
|
|
||||||
@@ -137,9 +137,9 @@ ColumnLayout {
|
|||||||
* - displayName - The display name of the reply author.
|
* - displayName - The display name of the reply author.
|
||||||
* - display - The name of the reply author.
|
* - display - The name of the reply author.
|
||||||
* - color - The color for the reply author.
|
* - color - The color for the reply author.
|
||||||
* - object - The NeoChatUser object for the reply author.
|
* - object - The Quotient::User object for the reply author.
|
||||||
*
|
*
|
||||||
* @sa NeoChatUser
|
* @sa Quotient::User
|
||||||
*/
|
*/
|
||||||
required property var replyAuthor
|
required property var replyAuthor
|
||||||
|
|
||||||
@@ -485,7 +485,7 @@ ColumnLayout {
|
|||||||
|
|
||||||
Layout.maximumWidth: contentMaxWidth
|
Layout.maximumWidth: contentMaxWidth
|
||||||
|
|
||||||
active: root.isReply
|
active: root.isReply && root.reply
|
||||||
visible: active
|
visible: active
|
||||||
|
|
||||||
sourceComponent: ReplyComponent {
|
sourceComponent: ReplyComponent {
|
||||||
@@ -518,8 +518,7 @@ ColumnLayout {
|
|||||||
visible: cardBackground && !Config.compactLayout
|
visible: cardBackground && !Config.compactLayout
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||||
Kirigami.Theme.inherit: false
|
color: if (root.author.isLocalUser) {
|
||||||
color: if (root.author.isLocalUser) {
|
|
||||||
return Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.15)
|
return Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.15)
|
||||||
} else if (root.showHighlight) {
|
} else if (root.showHighlight) {
|
||||||
return Kirigami.Theme.positiveBackgroundColor
|
return Kirigami.Theme.positiveBackgroundColor
|
||||||
|
|||||||
@@ -16,9 +16,19 @@ import org.kde.neochat 1.0
|
|||||||
QQC2.ScrollView {
|
QQC2.ScrollView {
|
||||||
id: root
|
id: root
|
||||||
required property NeoChatRoom currentRoom
|
required property NeoChatRoom currentRoom
|
||||||
readonly property bool isLoaded: root.width * root.height > 10
|
onCurrentRoomChanged: {
|
||||||
|
roomChanging = true;
|
||||||
|
applicationWindow().hoverLinkIndicator.text = "";
|
||||||
|
messageListView.positionViewAtBeginning();
|
||||||
|
hasScrolledUpBefore = false;
|
||||||
|
roomChanging = true;
|
||||||
|
}
|
||||||
|
property bool roomChanging: false
|
||||||
readonly property bool atYEnd: messageListView.atYEnd
|
readonly property bool atYEnd: messageListView.atYEnd
|
||||||
|
|
||||||
|
/// Used to determine if scrolling to the bottom should mark the message as unread
|
||||||
|
property bool hasScrolledUpBefore: false;
|
||||||
|
|
||||||
signal focusChatBox()
|
signal focusChatBox()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
@@ -38,7 +48,7 @@ QQC2.ScrollView {
|
|||||||
interactive: Kirigami.Settings.isMobile
|
interactive: Kirigami.Settings.isMobile
|
||||||
bottomMargin: Kirigami.Units.largeSpacing + Math.round(Kirigami.Theme.defaultFont.pointSize * 2)
|
bottomMargin: Kirigami.Units.largeSpacing + Math.round(Kirigami.Theme.defaultFont.pointSize * 2)
|
||||||
|
|
||||||
model: !isLoaded ? undefined : collapseStateProxyModel
|
model: collapseStateProxyModel
|
||||||
|
|
||||||
MessageEventModel {
|
MessageEventModel {
|
||||||
id: messageEventModel
|
id: messageEventModel
|
||||||
@@ -70,13 +80,15 @@ QQC2.ScrollView {
|
|||||||
messageEventModel.fetchMore(messageEventModel.index(0, 0));
|
messageEventModel.fetchMore(messageEventModel.index(0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
onAtYEndChanged: if (atYEnd && hasScrolledUpBefore) {
|
onAtYEndChanged: if (!root.roomChanging) {
|
||||||
if (QQC2.ApplicationWindow.window && (QQC2.ApplicationWindow.window.visibility !== QQC2.ApplicationWindow.Hidden)) {
|
if (atYEnd && root.hasScrolledUpBefore) {
|
||||||
root.currentRoom.markAllMessagesAsRead();
|
if (QQC2.ApplicationWindow.window && (QQC2.ApplicationWindow.window.visibility !== QQC2.ApplicationWindow.Hidden)) {
|
||||||
|
root.currentRoom.markAllMessagesAsRead();
|
||||||
|
}
|
||||||
|
root.hasScrolledUpBefore = false;
|
||||||
|
} else if (!atYEnd) {
|
||||||
|
root.hasScrolledUpBefore = true;
|
||||||
}
|
}
|
||||||
hasScrolledUpBefore = false;
|
|
||||||
} else if (!atYEnd) {
|
|
||||||
hasScrolledUpBefore = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not rendered because the sections are part of the TimelineContainer.qml, this is only so that items have the section property available for use by sectionBanner.
|
// Not rendered because the sections are part of the TimelineContainer.qml, this is only so that items have the section property available for use by sectionBanner.
|
||||||
@@ -310,6 +322,7 @@ QQC2.ScrollView {
|
|||||||
y: delegate ? delegate.mapToItem(parent, 0, 0).y + delegate.bubbleY - height + Kirigami.Units.smallSpacing : 0
|
y: delegate ? delegate.mapToItem(parent, 0, 0).y + delegate.bubbleY - height + Kirigami.Units.smallSpacing : 0
|
||||||
width: delegate ? delegate.bubbleWidth : Kirigami.Units.gridUnit * 4
|
width: delegate ? delegate.bubbleWidth : Kirigami.Units.gridUnit * 4
|
||||||
|
|
||||||
|
currentRoom: root.currentRoom
|
||||||
showActions: delegate && delegate.hovered
|
showActions: delegate && delegate.hovered
|
||||||
verified: delegate && delegate.verified
|
verified: delegate && delegate.verified
|
||||||
editable: delegate && delegate.author.isLocalUser && (delegate.delegateType === MessageEventModel.Emote || delegate.delegateType === MessageEventModel.Message)
|
editable: delegate && delegate.author.isLocalUser && (delegate.delegateType === MessageEventModel.Emote || delegate.delegateType === MessageEventModel.Message)
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ import org.kde.neochat 1.0
|
|||||||
QQC2.Popup {
|
QQC2.Popup {
|
||||||
id: emojiPopup
|
id: emojiPopup
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The current room that user is viewing.
|
||||||
|
*/
|
||||||
|
property NeoChatRoom currentRoom
|
||||||
|
|
||||||
property bool includeCustom: false
|
property bool includeCustom: false
|
||||||
property bool closeOnChosen: true
|
property bool closeOnChosen: true
|
||||||
property bool showQuickReaction: false
|
property bool showQuickReaction: false
|
||||||
@@ -34,21 +39,15 @@ QQC2.Popup {
|
|||||||
background: Kirigami.ShadowedRectangle {
|
background: Kirigami.ShadowedRectangle {
|
||||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||||
color: Kirigami.Theme.backgroundColor
|
color: Kirigami.Theme.backgroundColor
|
||||||
radius: Kirigami.Units.mediumSpacing
|
radius: Kirigami.Units.smallSpacing
|
||||||
shadow {
|
shadow.size: Kirigami.Units.smallSpacing
|
||||||
size: Kirigami.Units.largeSpacing
|
shadow.color: Qt.rgba(0.0, 0.0, 0.0, 0.10)
|
||||||
color: Qt.rgba(0.0, 0.0, 0.0, 0.3)
|
border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15)
|
||||||
yOffset: 2
|
border.width: 2
|
||||||
}
|
|
||||||
border {
|
|
||||||
color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15)
|
|
||||||
width: 2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
modal: true
|
modal: true
|
||||||
focus: true
|
focus: true
|
||||||
clip: false
|
|
||||||
closePolicy: QQC2.Popup.CloseOnEscape | QQC2.Popup.CloseOnPressOutsideParent
|
closePolicy: QQC2.Popup.CloseOnEscape | QQC2.Popup.CloseOnPressOutsideParent
|
||||||
margins: 0
|
margins: 0
|
||||||
padding: 2
|
padding: 2
|
||||||
@@ -58,8 +57,10 @@ QQC2.Popup {
|
|||||||
contentItem: EmojiPicker {
|
contentItem: EmojiPicker {
|
||||||
id: emojiPicker
|
id: emojiPicker
|
||||||
height: 400
|
height: 400
|
||||||
|
currentRoom: root.currentRoom
|
||||||
includeCustom: emojiPopup.includeCustom
|
includeCustom: emojiPopup.includeCustom
|
||||||
showQuickReaction: emojiPopup.showQuickReaction
|
showQuickReaction: emojiPopup.showQuickReaction
|
||||||
|
currentRoom: RoomManager.currentRoom
|
||||||
onChosen: {
|
onChosen: {
|
||||||
emojiPopup.chosen(emoji)
|
emojiPopup.chosen(emoji)
|
||||||
if (emojiPopup.closeOnChosen) emojiPopup.close()
|
if (emojiPopup.closeOnChosen) emojiPopup.close()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents
|
|||||||
|
|
||||||
import org.kde.neochat 1.0
|
import org.kde.neochat 1.0
|
||||||
|
|
||||||
Kirigami.OverlaySheet {
|
Kirigami.Dialog {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
signal closed()
|
signal closed()
|
||||||
@@ -26,6 +26,9 @@ Kirigami.OverlaySheet {
|
|||||||
topPadding: 0
|
topPadding: 0
|
||||||
bottomPadding: 0
|
bottomPadding: 0
|
||||||
|
|
||||||
|
standardButtons: Kirigami.Dialog.NoButton
|
||||||
|
|
||||||
|
width: Math.min(applicationWindow().width, Kirigami.Units.gridUnit * 24)
|
||||||
title: i18nc("@title:menu Account detail dialog", "Account detail")
|
title: i18nc("@title:menu Account detail dialog", "Account detail")
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
@@ -196,10 +199,5 @@ Kirigami.OverlaySheet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@OVERLAYSHEET_OPEN@: {
|
|
||||||
if (!sheetOpen) {
|
|
||||||
closed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -193,6 +193,12 @@ Kirigami.Page {
|
|||||||
width: Kirigami.Units.iconSizes.small
|
width: Kirigami.Units.iconSizes.small
|
||||||
height: Kirigami.Units.iconSizes.small
|
height: Kirigami.Units.iconSizes.small
|
||||||
}
|
}
|
||||||
|
text: roomListModel.categoryVisible(section) ? i18nc("Collapse <section name>", "Collapse %1", roomListModel.categoryName(section)) : i18nc("Expand <section name", "Expand %1", roomListModel.categoryName(section))
|
||||||
|
display: QQC2.Button.IconOnly
|
||||||
|
|
||||||
|
QQC2.ToolTip.text: text
|
||||||
|
QQC2.ToolTip.visible: hovered
|
||||||
|
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||||
|
|
||||||
onClicked: roomListModel.setCategoryVisible(section, !roomListModel.categoryVisible(section))
|
onClicked: roomListModel.setCategoryVisible(section, !roomListModel.categoryVisible(section))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ Delegates.RoundedItemDelegate {
|
|||||||
|
|
||||||
readonly property bool hasNotifications: notificationCount > 0
|
readonly property bool hasNotifications: notificationCount > 0
|
||||||
|
|
||||||
|
Accessible.name: root.displayName
|
||||||
|
|
||||||
onPressAndHold: createRoomListContextMenu()
|
onPressAndHold: createRoomListContextMenu()
|
||||||
|
|
||||||
TapHandler {
|
TapHandler {
|
||||||
@@ -65,7 +67,6 @@ Delegates.RoundedItemDelegate {
|
|||||||
text: root.displayName
|
text: root.displayName
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font.weight: root.hasNotifications ? Font.Bold : Font.Normal
|
font.weight: root.hasNotifications ? Font.Bold : Font.Normal
|
||||||
textFormat: Text.PlainText
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.alignment: subtitle.visible ? Qt.AlignLeft | Qt.AlignBottom : Qt.AlignLeft | Qt.AlignVCenter
|
Layout.alignment: subtitle.visible ? Qt.AlignLeft | Qt.AlignBottom : Qt.AlignLeft | Qt.AlignVCenter
|
||||||
|
|||||||
@@ -24,13 +24,11 @@ Loader {
|
|||||||
QQC2.Menu {
|
QQC2.Menu {
|
||||||
QQC2.MenuItem {
|
QQC2.MenuItem {
|
||||||
text: i18nc("'Space' is a matrix space", "View Space")
|
text: i18nc("'Space' is a matrix space", "View Space")
|
||||||
icon.name: "view-list-details"
|
|
||||||
onTriggered: RoomManager.enterRoom(room);
|
onTriggered: RoomManager.enterRoom(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
QQC2.MenuItem {
|
QQC2.MenuItem {
|
||||||
text: i18nc("@action:inmenu", "Copy Address to Clipboard")
|
text: i18nc("@action:inmenu", "Copy Address to Clipboard")
|
||||||
icon.name: "edit-copy"
|
|
||||||
onTriggered: if (room.canonicalAlias.length === 0) {
|
onTriggered: if (room.canonicalAlias.length === 0) {
|
||||||
Clipboard.saveText(room.id)
|
Clipboard.saveText(room.id)
|
||||||
} else {
|
} else {
|
||||||
@@ -40,7 +38,6 @@ Loader {
|
|||||||
|
|
||||||
QQC2.MenuItem {
|
QQC2.MenuItem {
|
||||||
text: i18nc("'Space' is a matrix space", "Space Settings")
|
text: i18nc("'Space' is a matrix space", "Space Settings")
|
||||||
icon.name: 'settings-configure'
|
|
||||||
onTriggered: QQC2.ApplicationWindow.window.pageStack.pushDialogLayer('qrc:/Categories.qml', {room: room}, { title: i18n("Space Settings") })
|
onTriggered: QQC2.ApplicationWindow.window.pageStack.pushDialogLayer('qrc:/Categories.qml', {room: room}, { title: i18n("Space Settings") })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,13 +45,12 @@ Loader {
|
|||||||
|
|
||||||
QQC2.MenuItem {
|
QQC2.MenuItem {
|
||||||
text: i18nc("'Space' is a matrix space", "Leave Space")
|
text: i18nc("'Space' is a matrix space", "Leave Space")
|
||||||
icon.name: "go-previous"
|
|
||||||
onTriggered: RoomManager.leaveRoom(room)
|
onTriggered: RoomManager.leaveRoom(room)
|
||||||
}
|
}
|
||||||
|
|
||||||
onClosed: {
|
onClosed: {
|
||||||
root.closed()
|
root.closed()
|
||||||
regularMenu.destroy()
|
destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ QQC2.ToolBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout.fillWidth: true
|
width: parent.width
|
||||||
Layout.preferredHeight: contentHeight
|
Layout.preferredHeight: contentHeight
|
||||||
delegate: Delegates.RoundedItemDelegate {
|
delegate: Delegates.RoundedItemDelegate {
|
||||||
id: userDelegate
|
id: userDelegate
|
||||||
|
|||||||
@@ -19,25 +19,17 @@ Kirigami.Page {
|
|||||||
/// Not readonly because of the separate window view.
|
/// Not readonly because of the separate window view.
|
||||||
property NeoChatRoom currentRoom: RoomManager.currentRoom
|
property NeoChatRoom currentRoom: RoomManager.currentRoom
|
||||||
property bool loading: !root.currentRoom || (root.currentRoom.timelineSize === 0 && !root.currentRoom.allHistoryLoaded)
|
property bool loading: !root.currentRoom || (root.currentRoom.timelineSize === 0 && !root.currentRoom.allHistoryLoaded)
|
||||||
/// Used to determine if scrolling to the bottom should mark the message as unread
|
|
||||||
property bool hasScrolledUpBefore: false;
|
|
||||||
|
|
||||||
/// Disable cancel shortcut. Used by the separate window since it provides its own cancel implementation.
|
/// Disable cancel shortcut. Used by the separate window since it provides its own cancel implementation.
|
||||||
property bool disableCancelShortcut: false
|
property bool disableCancelShortcut: false
|
||||||
|
|
||||||
title: currentRoom.displayName
|
title: root.currentRoom.displayName
|
||||||
focus: true
|
focus: true
|
||||||
padding: 0
|
padding: 0
|
||||||
|
|
||||||
KeyNavigation.left: pageStack.get(0)
|
KeyNavigation.left: pageStack.get(0)
|
||||||
|
|
||||||
onCurrentRoomChanged: {
|
onCurrentRoomChanged: {
|
||||||
if (!timelineViewLoader.item) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
applicationWindow().hoverLinkIndicator.text = "";
|
|
||||||
timelineViewLoader.item.positionViewAtBeginning();
|
|
||||||
hasScrolledUpBefore = false;
|
|
||||||
if (!Kirigami.Settings.isMobile && chatBoxLoader.item) {
|
if (!Kirigami.Settings.isMobile && chatBoxLoader.item) {
|
||||||
chatBoxLoader.item.forceActiveFocus();
|
chatBoxLoader.item.forceActiveFocus();
|
||||||
}
|
}
|
||||||
@@ -66,7 +58,7 @@ Kirigami.Page {
|
|||||||
Loader {
|
Loader {
|
||||||
id: timelineViewLoader
|
id: timelineViewLoader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
active: currentRoom && !currentRoom.isInvite && !root.loading
|
active: root.currentRoom && !root.currentRoom.isInvite && !root.loading
|
||||||
sourceComponent: TimelineView {
|
sourceComponent: TimelineView {
|
||||||
id: timelineView
|
id: timelineView
|
||||||
currentRoom: root.currentRoom
|
currentRoom: root.currentRoom
|
||||||
@@ -80,7 +72,7 @@ Kirigami.Page {
|
|||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: invitationLoader
|
id: invitationLoader
|
||||||
active: currentRoom && currentRoom.isInvite
|
active: root.currentRoom && root.currentRoom.isInvite
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
sourceComponent: InvitationView {
|
sourceComponent: InvitationView {
|
||||||
currentRoom: root.currentRoom
|
currentRoom: root.currentRoom
|
||||||
@@ -106,7 +98,7 @@ Kirigami.Page {
|
|||||||
sourceComponent: ChatBox {
|
sourceComponent: ChatBox {
|
||||||
id: chatBox
|
id: chatBox
|
||||||
width: parent.width
|
width: parent.width
|
||||||
currentRoom: currentRoom
|
currentRoom: root.currentRoom
|
||||||
onMessageSent: {
|
onMessageSent: {
|
||||||
if (!timelineViewLoader.item.atYEnd) {
|
if (!timelineViewLoader.item.atYEnd) {
|
||||||
timelineViewLoader.item.goToLastMessage();
|
timelineViewLoader.item.goToLastMessage();
|
||||||
@@ -140,9 +132,9 @@ Kirigami.Page {
|
|||||||
Shortcut {
|
Shortcut {
|
||||||
sequence: StandardKey.Cancel
|
sequence: StandardKey.Cancel
|
||||||
onActivated: {
|
onActivated: {
|
||||||
if (!timelineViewLoader.item.atYEnd || currentRoom.hasUnreadMessages) {
|
if (!timelineViewLoader.item.atYEnd || root.currentRoom.hasUnreadMessages) {
|
||||||
goToLastMessage();
|
goToLastMessage();
|
||||||
currentRoom.markAllMessagesAsRead();
|
root.currentRoom.markAllMessagesAsRead();
|
||||||
} else {
|
} else {
|
||||||
applicationWindow().pageStack.get(0).forceActiveFocus();
|
applicationWindow().pageStack.get(0).forceActiveFocus();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ ColumnLayout {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: room ? room.displayName : i18n("No name")
|
text: room ? room.displayName : i18n("No name")
|
||||||
textFormat: Text.PlainText
|
textFormat: Text.PlainText
|
||||||
wrapMode: Text.Wrap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Kirigami.SelectableLabel {
|
Kirigami.SelectableLabel {
|
||||||
|
|||||||
@@ -156,8 +156,7 @@ Kirigami.OverlayDrawer {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
applicationWindow().pageStack.layers.push("qrc:/DevtoolsPage.qml", {room: room}, {title: i18n("Developer Tools")})
|
applicationWindow().pageStack.pushDialogLayer("qrc:/DevtoolsPage.qml", {room: room}, {title: i18n("Developer Tools")})
|
||||||
roomDrawer.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,8 +228,7 @@ Kirigami.OverlayDrawer {
|
|||||||
icon.name: "list-add-user"
|
icon.name: "list-add-user"
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
applicationWindow().pageStack.layers.push("qrc:/InviteUserPage.qml", {room: roomDrawer.room})
|
applicationWindow().pageStack.pushDialogLayer("qrc:/InviteUserPage.qml", {room: roomDrawer.room}, {title: i18nc("@title", "Invite a User")})
|
||||||
roomDrawer.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQC2.ToolTip.text: i18n("Invite user to room")
|
QQC2.ToolTip.text: i18n("Invite user to room")
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Kirigami.ScrollablePage {
|
|||||||
|
|
||||||
MobileForm.FormCheckDelegate {
|
MobileForm.FormCheckDelegate {
|
||||||
id: closeDelegate
|
id: closeDelegate
|
||||||
text: i18n("Close to system tray")
|
text: i18n("Show in System Tray")
|
||||||
checked: Config.systemTray
|
checked: Config.systemTray
|
||||||
visible: Controller.supportSystemTray
|
visible: Controller.supportSystemTray
|
||||||
enabled: !Config.isSystemTrayImmutable
|
enabled: !Config.isSystemTrayImmutable
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
<file alias="RoomDrawer.qml">qml/Panel/RoomDrawer.qml</file>
|
<file alias="RoomDrawer.qml">qml/Panel/RoomDrawer.qml</file>
|
||||||
<file alias="DirectChatDrawerHeader.qml">qml/Panel/DirectChatDrawerHeader.qml</file>
|
<file alias="DirectChatDrawerHeader.qml">qml/Panel/DirectChatDrawerHeader.qml</file>
|
||||||
<file alias="GroupChatDrawerHeader.qml">qml/Panel/GroupChatDrawerHeader.qml</file>
|
<file alias="GroupChatDrawerHeader.qml">qml/Panel/GroupChatDrawerHeader.qml</file>
|
||||||
<file alias="UserDetailDialog.qml">@CMAKE_CURRENT_BINARY_DIR@/qml/Dialog/UserDetailDialog.qml</file>
|
<file alias="UserDetailDialog.qml">qml/Dialog/UserDetailDialog.qml</file>
|
||||||
<file alias="CreateRoomDialog.qml">qml/Dialog/CreateRoomDialog.qml</file>
|
<file alias="CreateRoomDialog.qml">qml/Dialog/CreateRoomDialog.qml</file>
|
||||||
<file alias="CreateSpaceDialog.qml">qml/Dialog/CreateSpaceDialog.qml</file>
|
<file alias="CreateSpaceDialog.qml">qml/Dialog/CreateSpaceDialog.qml</file>
|
||||||
<file alias="EmojiDialog.qml">qml/Dialog/EmojiDialog.qml</file>
|
<file alias="EmojiDialog.qml">qml/Dialog/EmojiDialog.qml</file>
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
#include "texthandler.h"
|
#include "texthandler.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QUrl>
|
#include <QGuiApplication>
|
||||||
#include <QStringLiteral>
|
#include <QStringLiteral>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
#include <Quotient/events/roommessageevent.h>
|
#include <Quotient/events/roommessageevent.h>
|
||||||
#include <Quotient/util.h>
|
#include <Quotient/util.h>
|
||||||
@@ -15,6 +16,8 @@
|
|||||||
|
|
||||||
#include <Kirigami/PlatformTheme>
|
#include <Kirigami/PlatformTheme>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
static const QStringList allowedTags = {
|
static const QStringList allowedTags = {
|
||||||
QStringLiteral("font"), QStringLiteral("del"), QStringLiteral("h1"), QStringLiteral("h2"), QStringLiteral("h3"), QStringLiteral("h4"),
|
QStringLiteral("font"), QStringLiteral("del"), QStringLiteral("h1"), QStringLiteral("h2"), QStringLiteral("h3"), QStringLiteral("h4"),
|
||||||
QStringLiteral("h5"), QStringLiteral("h6"), QStringLiteral("blockquote"), QStringLiteral("p"), QStringLiteral("a"), QStringLiteral("ul"),
|
QStringLiteral("h5"), QStringLiteral("h6"), QStringLiteral("blockquote"), QStringLiteral("p"), QStringLiteral("a"), QStringLiteral("ul"),
|
||||||
@@ -135,9 +138,9 @@ QString TextHandler::handleRecieveRichText(Qt::TextFormat inputFormat, const Neo
|
|||||||
if (event != nullptr) {
|
if (event != nullptr) {
|
||||||
auto e = eventCast<const Quotient::RoomMessageEvent>(event);
|
auto e = eventCast<const Quotient::RoomMessageEvent>(event);
|
||||||
if (e->msgtype() == Quotient::MessageEventType::Emote) {
|
if (e->msgtype() == Quotient::MessageEventType::Emote) {
|
||||||
auto author = static_cast<NeoChatUser *>(room->user(e->senderId()));
|
auto author = room->user(e->senderId());
|
||||||
QString emoteString = QStringLiteral("* <a href=\"https://matrix.to/#/") + e->senderId() + QStringLiteral("\" style=\"color:")
|
QString emoteString = QStringLiteral("* <a href=\"https://matrix.to/#/") + e->senderId() + QStringLiteral("\" style=\"color:")
|
||||||
+ author->color().name() + QStringLiteral("\">") + author->displayname(room) + QStringLiteral("</a> ");
|
+ Utils::getUserColor(author->hueF()).name() + QStringLiteral("\">") + author->displayname(room) + QStringLiteral("</a> ");
|
||||||
if (outputString.startsWith(QStringLiteral("<p>"))) {
|
if (outputString.startsWith(QStringLiteral("<p>"))) {
|
||||||
outputString.insert(3, emoteString);
|
outputString.insert(3, emoteString);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
23
src/utils.h
Normal file
23
src/utils.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QPalette>
|
||||||
|
|
||||||
|
namespace Utils
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a color for a user from a hueF value.
|
||||||
|
*
|
||||||
|
* The lightness of the color will be modified depending on the current palette in
|
||||||
|
* order to maintain contrast.
|
||||||
|
*/
|
||||||
|
inline QColor getUserColor(qreal hueF)
|
||||||
|
{
|
||||||
|
const auto lightness = static_cast<QGuiApplication *>(QGuiApplication::instance())->palette().color(QPalette::Active, QPalette::Window).lightnessF();
|
||||||
|
// https://github.com/quotient-im/libQuotient/wiki/User-color-coding-standard-draft-proposal
|
||||||
|
return QColor::fromHslF(hueF, 1, -0.7 * lightness + 0.9, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user