Compare commits
4 Commits
work/redst
...
work/tobia
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
604c652821 | ||
|
|
cc2daa2021 | ||
|
|
e2de5b5f00 | ||
|
|
1896d69253 |
@@ -2,7 +2,7 @@
|
||||
"id": "org.kde.neochat",
|
||||
"branch": "master",
|
||||
"runtime": "org.kde.Platform",
|
||||
"runtime-version": "6.10",
|
||||
"runtime-version": "6.9",
|
||||
"sdk": "org.kde.Sdk",
|
||||
"command": "neochat",
|
||||
"tags": [
|
||||
@@ -31,6 +31,19 @@
|
||||
"/share/ndk-modules"
|
||||
],
|
||||
"modules": [
|
||||
{
|
||||
"name": "kirigamiaddons",
|
||||
"config-opts": [
|
||||
"-DBUILD_TESTING=OFF"
|
||||
],
|
||||
"buildsystem": "cmake-ninja",
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://invent.kde.org/libraries/kirigami-addons.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "opencv",
|
||||
"config-opts": [
|
||||
@@ -65,7 +78,6 @@
|
||||
"name": "olm",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"config-opts": [
|
||||
"-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
|
||||
"-DOLM_TESTS=OFF"
|
||||
],
|
||||
"sources": [
|
||||
@@ -172,8 +184,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://download.kde.org/stable/release-service/25.08.3/src/kunifiedpush-25.08.3.tar.xz",
|
||||
"sha256": "e8c924438d5359f0fa0930ab35111012076e3a0ff4e959d6929595571383320a",
|
||||
"url": "https://download.kde.org/stable/release-service/25.08.0/src/kunifiedpush-25.08.0.tar.xz",
|
||||
"sha256": "846db6ffc7d93f6afea7ce0d5a9f10b52792157ceb593856542279f4197f3518",
|
||||
"x-checker-data": {
|
||||
"type": "anitya",
|
||||
"project-id": 8763,
|
||||
|
||||
@@ -10,11 +10,11 @@ Dependencies:
|
||||
'frameworks/ki18n': '@latest-kf6'
|
||||
'frameworks/kconfig': '@latest-kf6'
|
||||
'frameworks/syntax-highlighting': '@latest-kf6'
|
||||
'frameworks/kiconthemes': '@latest-kf6'
|
||||
'frameworks/kitemmodels': '@latest-kf6'
|
||||
'frameworks/kquickcharts': '@latest-kf6'
|
||||
'frameworks/knotifications': '@latest-kf6'
|
||||
'frameworks/kcolorscheme': '@latest-kf6'
|
||||
'frameworks/kiconthemes': '@latest-kf6'
|
||||
'libraries/kquickimageeditor': '@latest-kf6'
|
||||
'frameworks/sonnet': '@latest-kf6'
|
||||
'frameworks/prison': '@latest-kf6'
|
||||
@@ -29,6 +29,7 @@ Dependencies:
|
||||
'frameworks/kio': '@latest-kf6'
|
||||
'frameworks/kwindowsystem': '@latest-kf6'
|
||||
'frameworks/kstatusnotifieritem': '@latest-kf6'
|
||||
'frameworks/kcrash': '@latest-kf6'
|
||||
- 'on': ['Linux', 'FreeBSD']
|
||||
'require':
|
||||
'frameworks/kdbusaddons': '@latest-kf6'
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# KDE Applications version, managed by release script.
|
||||
set(RELEASE_SERVICE_VERSION_MAJOR "26")
|
||||
set(RELEASE_SERVICE_VERSION_MINOR "03")
|
||||
set(RELEASE_SERVICE_VERSION_MAJOR "25")
|
||||
set(RELEASE_SERVICE_VERSION_MINOR "11")
|
||||
set(RELEASE_SERVICE_VERSION_MICRO "70")
|
||||
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
||||
|
||||
@@ -24,7 +24,7 @@ set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(KDE_COMPILERSETTINGS_LEVEL 6.17)
|
||||
set(KDE_COMPILERSETTINGS_LEVEL 6.0)
|
||||
|
||||
include(FeatureSummary)
|
||||
include(ECMSetupVersion)
|
||||
@@ -39,16 +39,17 @@ include(ECMCheckOutboundLicense)
|
||||
include(ECMQtDeclareLoggingCategory)
|
||||
include(ECMAddAndroidApk)
|
||||
include(ECMQmlModule)
|
||||
include(ECMDeprecationSettings)
|
||||
include(GenerateExportHeader)
|
||||
include(ECMGenerateHeaders)
|
||||
if (NOT ANDROID)
|
||||
include(KDEClangFormat)
|
||||
endif()
|
||||
|
||||
set(QUOTIENT_FORCE_NAMESPACED_INCLUDES TRUE)
|
||||
if(NEOCHAT_FLATPAK)
|
||||
include(cmake/Flatpak.cmake)
|
||||
endif()
|
||||
|
||||
ecm_set_disabled_deprecation_versions(Qt 6.9.0 KF 6.17.0)
|
||||
set(QUOTIENT_FORCE_NAMESPACED_INCLUDES TRUE)
|
||||
|
||||
ecm_setup_version(${PROJECT_VERSION}
|
||||
VARIABLE_PREFIX NEOCHAT
|
||||
@@ -65,7 +66,7 @@ if (QT_KNOWN_POLICY_QTP0004)
|
||||
qt_policy(SET QTP0004 NEW)
|
||||
endif ()
|
||||
|
||||
find_package(KF6 ${KF_MIN_VERSION} COMPONENTS Kirigami I18n Notifications Config CoreAddons Sonnet ItemModels ColorScheme IconThemes)
|
||||
find_package(KF6 ${KF_MIN_VERSION} COMPONENTS Kirigami I18n Notifications Config CoreAddons Sonnet ItemModels IconThemes ColorScheme)
|
||||
set_package_properties(KF6 PROPERTIES
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Basic application components"
|
||||
@@ -74,7 +75,7 @@ set_package_properties(KF6Kirigami PROPERTIES
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Kirigami application UI framework"
|
||||
)
|
||||
find_package(KF6KirigamiAddons 1.10.0 REQUIRED)
|
||||
find_package(KF6KirigamiAddons 1.6.0 REQUIRED)
|
||||
|
||||
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT NEOCHAT_FLATPAK AND NOT NEOCHAT_APPIMAGE)
|
||||
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS Purpose)
|
||||
@@ -88,7 +89,7 @@ if(ANDROID)
|
||||
)
|
||||
else()
|
||||
find_package(Qt6 ${QT_MIN_VERSION} COMPONENTS Widgets)
|
||||
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle KIO WindowSystem StatusNotifierItem)
|
||||
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS QQC2DesktopStyle KIO WindowSystem StatusNotifierItem Crash)
|
||||
find_package(KF6SyntaxHighlighting ${KF_MIN_VERSION} REQUIRED)
|
||||
set_package_properties(KF6QQC2DesktopStyle PROPERTIES
|
||||
TYPE RUNTIME
|
||||
|
||||
@@ -63,7 +63,7 @@ void ActionsTest::testActions_data()
|
||||
QTest::addColumn<std::optional<QString>>("resultText");
|
||||
QTest::addColumn<std::optional<Quotient::RoomMessageEvent::MsgType>>("type");
|
||||
|
||||
QTest::newRow("shrug") << u"/shrug Hello"_s << std::make_optional(u"¯\\\\\\_(ツ)\\_/¯ Hello"_s)
|
||||
QTest::newRow("shrug") << u"/shrug Hello"_s << std::make_optional(u"¯\\\\_(ツ)_/¯ Hello"_s)
|
||||
<< std::make_optional(Quotient::RoomMessageEvent::MsgType::Text);
|
||||
QTest::newRow("lenny") << u"/lenny Hello"_s << std::make_optional(u"( ͡° ͜ʖ ͡°) Hello"_s) << std::make_optional(Quotient::RoomMessageEvent::MsgType::Text);
|
||||
QTest::newRow("tableflip") << u"/tableflip Hello"_s << std::make_optional(u"(╯°□°)╯︵ ┻━┻ Hello"_s)
|
||||
|
||||
@@ -4,12 +4,15 @@
|
||||
#include "server.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QHttpServer>
|
||||
#include <QHttpServerResponder>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QNetworkReply>
|
||||
#include <QSslCertificate>
|
||||
#include <QSslKey>
|
||||
#include <QSslServer>
|
||||
#include <QUuid>
|
||||
|
||||
#include <Quotient/networkaccessmanager.h>
|
||||
|
||||
@@ -208,7 +208,7 @@ void TimelineMessageModelTest::idToRow()
|
||||
auto room = new TestUtils::TestRoom(connection, u"#myroom:kde.org"_s, u"test-min-sync.json"_s);
|
||||
model->setRoom(room);
|
||||
|
||||
QCOMPARE(model->indexForEventId(u"$153456789:example.org"_s).row(), 0);
|
||||
QCOMPARE(model->indexforEventId(u"$153456789:example.org"_s).row(), 0);
|
||||
}
|
||||
|
||||
void TimelineMessageModelTest::cleanup()
|
||||
|
||||
14
cmake/Flatpak.cmake
Normal file
14
cmake/Flatpak.cmake
Normal file
@@ -0,0 +1,14 @@
|
||||
# SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Include FontConfig config which uses the Emoji One font from the
|
||||
# KDE Flatpak SDK.
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Flatpak/99-noto-mono-color-emoji.conf
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_SYSCONFDIR}/fonts/local.conf
|
||||
)
|
||||
|
||||
23
cmake/Flatpak/99-noto-mono-color-emoji.conf
Normal file
23
cmake/Flatpak/99-noto-mono-color-emoji.conf
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<alias>
|
||||
<family>serif</family>
|
||||
<prefer>
|
||||
<family>Noto Color Emoji</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>sans-serif</family>
|
||||
<prefer>
|
||||
<family>Noto Color Emoji</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
<alias>
|
||||
<family>monospace</family>
|
||||
<prefer>
|
||||
<family>Noto Color Emoji</family>
|
||||
</prefer>
|
||||
</alias>
|
||||
</fontconfig>
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
<name xml:lang="pl">NeoChat</name>
|
||||
<name xml:lang="pt">NeoChat</name>
|
||||
<name xml:lang="pt-BR">NeoChat</name>
|
||||
<name xml:lang="ro">NeoChat</name>
|
||||
<name xml:lang="ru">NeoChat</name>
|
||||
<name xml:lang="sa">नवचैट्</name>
|
||||
<name xml:lang="sk">NeoChat</name>
|
||||
@@ -76,7 +75,6 @@
|
||||
<summary xml:lang="nn">Prat med via Matrix</summary>
|
||||
<summary xml:lang="pl">Rozmawiaj na Matriksie</summary>
|
||||
<summary xml:lang="pt-BR">Bate-papo na Matrix</summary>
|
||||
<summary xml:lang="ro">Discutați pe Matrix</summary>
|
||||
<summary xml:lang="ru">Общение в Matrix</summary>
|
||||
<summary xml:lang="sa">Matrix इत्यत्र गपशपं कुर्वन्तु</summary>
|
||||
<summary xml:lang="sl">Klepet na Matrixu</summary>
|
||||
@@ -111,7 +109,6 @@
|
||||
<p xml:lang="nn">NeoChat er ein prateapp som lèt deg bruka all funksjonalitet i Matrix-nettverket. Du kan utveksla tekst, lyd og videoar med vennar, familie og kollegaar på ein trygg måte.</p>
|
||||
<p xml:lang="pl">NoeChat to aplikacja do rozmów, która umożliwia wykorzystanie wszystkich możliwości Matriksa. Umożliwia wysyłanie wiadomości tekstowych, filmów i dźwięków w bezpieczny sposób do twojej rodziny, kolegów i przyjaciół.</p>
|
||||
<p xml:lang="pt-BR">O NeoChat é um aplicativo de bate-papo que permite que você aproveite ao máximo a rede Matrix. Ele oferece uma maneira segura de enviar mensagens de texto, vídeos e arquivos de áudio para sua família, colegas e amigos.</p>
|
||||
<p xml:lang="ro">NeoChat e o aplicație de discuții ce vă ajută să profitați din plin de rețeaua Matrix. Aceasta oferă o modalitate sigură de a trimite mesaje textuale, videoclipuri și fișiere audio familiei, colegilor și prietenilor.</p>
|
||||
<p xml:lang="ru">NeoChat — приложение для общения, предоставляющее все преимущества сети Matrix. С его помощью можно безопасно отправлять текстовые сообщения, видеозаписи и звуковые файлы родственникам, коллегам и друзьям.</p>
|
||||
<p xml:lang="sa">NeoChat इति एकं गपशप-अनुप्रयोगं यत् भवान् Matrix-जालस्य पूर्णं लाभं ग्रहीतुं शक्नोति । एतत् भवन्तं भवतः परिवाराय, सहकारिभ्यः, मित्रेभ्यः च पाठसन्देशान्, भिडियो, श्रव्यसञ्चिकाः च प्रेषयितुं सुरक्षितं मार्गं प्रदाति ।</p>
|
||||
<p xml:lang="sl">NeoChat je aplikacija za klepet, ki vam omogoča, da v celoti izkoristite omrežje Matrix. Zagotavlja vam varen način za pošiljanje besedilnih sporočil, videoposnetkov in zvočnih datotek vaši družini, sodelavcem in prijateljem.</p>
|
||||
@@ -145,7 +142,6 @@
|
||||
<p xml:lang="pl">NeoChat w zamyśle ma być pełnowartościową aplikacją wg wytycznych Matriksa. Z tego powodu, wszystko, co jest obecnie w stabilnych wytycznych z pominięciem VoIP, wątków i niektórych części szyfrowania Użytkownik-do-Użytkownika są obecnie obsługiwane. Pominięto też kilka mniejszych rzeczy ze względu na ciągły rozwój wytycznych Matriksa, lecz celem nadal jest zapewnienie obsługi wszystkich wytycznych.</p>
|
||||
<p xml:lang="pt">O NeoChat pretende ser uma aplicação completa para a especificação do Matrix. Como tal, tudo o que existe na especificação estável actual, com as notáveis excepções do VoIP, tópicos e alguns aspectos da Encriptação Ponto-a-Ponto, são suportados. Existem mais algumas omissões, devido ao facto que a norma do Matrix está em constante evolução, mas o objectivo continua a ser oferecer o suporte eventual para a norma por inteiro.</p>
|
||||
<p xml:lang="pt-BR">O NeoChat pretende ser um aplicativo completo para a especificação Matrix. Dessa forma, tudo na especificação estável atual, com as notáveis exceções de VoIP, tópicos e alguns aspectos da criptografia de ponta a ponta, é suportado. Há algumas outras pequenas omissões devido ao fato de a especificação Matrix estar em constante evolução, mas o objetivo continua sendo fornecer suporte eventual para toda a especificação.</p>
|
||||
<p xml:lang="ro">NeoChat vrea să fie o aplicație completă pentru specificațiile Matrix. Astfel, susține tot ce se găsește acum în specificațiile stabile cu excepția VoIP, a firelor de discuții, și a unor părți din criptarea punct-la-punct. Sunt și câteva omisiuni minore din cauza faptului că specificația Matrix evoluează continuu, dar scopul rămâne acela de a implementa întreaga specificație.</p>
|
||||
<p xml:lang="ru">Целью создания NeoChat является полноценная реализация программы для спецификации Matrix. Как следствие, реализовано всё в текущей стабильной спецификации (за исключением голосовой интернет-связи, потоков и некоторых аспектов сквозного шифрования). Есть также несколько других незначительных пробелов, обусловленных постоянными изменениями спецификации Matrix. Тем не менее, стоит задача в итоге предоставить полную поддержку спецификации.</p>
|
||||
<p xml:lang="sa">NeoChat इत्यस्य उद्देश्यं Matrix विनिर्देशस्य कृते पूर्णतया विशेषतायुक्तः अनुप्रयोगः भवितुम् अस्ति । यथा तथा वर्तमानस्थिरविनिर्देशे सर्वं VoIP इत्यस्य उल्लेखनीयअपवादैः सह, थ्रेड्स तथा च End-to-End Encryption इत्यस्य केचन पक्षाः समर्थिताः सन्ति । अन्ये कतिचन लघु लोपाः सन्ति यतोहि Matrix spec निरन्तरं विकसितः अस्ति परन्तु उद्देश्यं सम्पूर्ण spec कृते अन्ततः समर्थनं प्रदातुं अवशिष्टम् अस्ति</p>
|
||||
<p xml:lang="sl">Neochat cilja, da bi bila popolna aplikacija po specifikaciji Matrixa. Kot takšna vsebuje vse v trenutni stabilni specifikaciji z pomembnimi izjemami pri VoIP, nitih in nekaterih vidikov šifriranja od konca do konca. Obstaja nekaj drugih manjših opustitev zaradi dejstva, da se specifikacija Matrix nenehno razvija, vendar cilj ostaja zagotoviti morebitno podporo celotni specifikaciji.</p>
|
||||
@@ -179,7 +175,6 @@
|
||||
<p xml:lang="pl">Ze względu na sposób rozwoju Matriksa, NeoChat obsługuje także kilka niestabilnych możliwości. Obecnie są to:</p>
|
||||
<p xml:lang="pt">Devido à natureza do desenvolvimento da especificação do Matrix, o NeoChat também suporta diversas funcionalidades instáveis. De momento são:</p>
|
||||
<p xml:lang="pt-BR">Devido à natureza do desenvolvimento da especificação Matrix, o NeoChat também suporta diversos recursos instáveis. Atualmente, são eles:</p>
|
||||
<p xml:lang="ro">Datorită modului de dezvoltare a specificațiilor Matrix, NeoChat susține și numeroase caracteristici nestabile. Acum, acestea sunt:</p>
|
||||
<p xml:lang="ru">В силу природы разработки спецификации Matrix в NeoChat тоже предусмотрена поддержка многочисленных нестабильных возможностей. В текущей версии это следующие возможности:</p>
|
||||
<p xml:lang="sa">Matrix विनिर्देशविकासस्य प्रकृतेः कारणात् NeoChat अपि अनेकानाम् अस्थिरविशेषतानां समर्थनं करोति । सम्प्रति एते सन्ति :</p>
|
||||
<p xml:lang="sl">Zaradi narave razvoja specifikacije Matrixa NeoChat podpira tudi številne nestabilne zmožnosti. Trenutno so to:</p>
|
||||
@@ -214,7 +209,6 @@
|
||||
<li xml:lang="pl">Ankiety - MSC3381</li>
|
||||
<li xml:lang="pt">Inquéritos - MSC3381</li>
|
||||
<li xml:lang="pt-BR">Enquetes - MSC3381</li>
|
||||
<li xml:lang="ro">Sondaje - MSC3381</li>
|
||||
<li xml:lang="ru">Голосования — MSC3381</li>
|
||||
<li xml:lang="sa">मतदान - MSC3381</li>
|
||||
<li xml:lang="sl">Polls - MSC3381</li>
|
||||
@@ -248,7 +242,6 @@
|
||||
<li xml:lang="pl">Paczki naklejek - MSC2545</li>
|
||||
<li xml:lang="pt">Pacotes de Autocolantes - MSC2545</li>
|
||||
<li xml:lang="pt-BR">Pacotes de Stickers - MSC2545</li>
|
||||
<li xml:lang="ro">Colecții de abțibilduri - MSC2545</li>
|
||||
<li xml:lang="ru">Наборы стикеров — MSC2545</li>
|
||||
<li xml:lang="sa">स्टिकर पैक - MSC2545</li>
|
||||
<li xml:lang="sl">Sticker Packs - MSC2545</li>
|
||||
@@ -282,7 +275,6 @@
|
||||
<li xml:lang="pl">Wydarzenia w miejscach - MSC3488</li>
|
||||
<li xml:lang="pt">Eventos com Localizações - MSC3488</li>
|
||||
<li xml:lang="pt-BR">Localização de eventos - MSC3488</li>
|
||||
<li xml:lang="ro">Evenimente de amplasare - MSC3488</li>
|
||||
<li xml:lang="ru">События местоположения — MSC3488</li>
|
||||
<li xml:lang="sa">स्थान घटनाएँ - MSC3488</li>
|
||||
<li xml:lang="sl">Location Events - MSC3488</li>
|
||||
@@ -320,6 +312,7 @@
|
||||
<value key="KDE::windows_store::StoreLogoSquare">https://invent.kde.org/network/neochat/-/raw/master/icons/windows/storelogo-1080x1080.png</value>
|
||||
<value key="KDE::windows_store::Icon">https://invent.kde.org/network/neochat/-/raw/master/icons/300-apps-neochat.png</value>
|
||||
<value key="KDE::windows_store::PromotionalArt16x9">https://invent.kde.org/network/neochat/-/raw/master/icons/windows/promoimage-1920x1080.png</value>
|
||||
<value key="KDE::supporters">Tanguy Fardet;[dabe](https://freeradical.zone/@dabe);[lengau](https://mastodon.world/@lengau);Joshua Strobl;Stuart Turton</value>
|
||||
</custom>
|
||||
<launchable type="desktop-id">org.kde.neochat.desktop</launchable>
|
||||
<screenshots>
|
||||
@@ -351,7 +344,6 @@
|
||||
<caption xml:lang="pl">Główny widok z wykazem pokojów, rozmowami i szczegółami pokojów</caption>
|
||||
<caption xml:lang="pt">A área principal com a lista de salas e com informações sobre a conversa e a sala</caption>
|
||||
<caption xml:lang="pt-BR">Visão principal com lista de salas, bate-papo e informações sobre as salas</caption>
|
||||
<caption xml:lang="ro">Vederea principală cu lista de camere, discuție, și informații despre cameră</caption>
|
||||
<caption xml:lang="ru">Главное окно со списком комнат, чатом и информацией о комнате</caption>
|
||||
<caption xml:lang="sa">कक्षसूची, गपशपः, कक्षसूचना च सह मुख्यदृश्यम्</caption>
|
||||
<caption xml:lang="sl">Glavni pogled s seznamom sob, klepetom in informacijami o sobah</caption>
|
||||
@@ -388,7 +380,6 @@
|
||||
<caption xml:lang="nn">Oppdag nye fellesskap med Matrix Spaces</caption>
|
||||
<caption xml:lang="pl">Odkrywaj nowe społeczności w Przestrzeniach Matriksa</caption>
|
||||
<caption xml:lang="pt-BR">Descubra novas comunidades com os Espaços Matrix</caption>
|
||||
<caption xml:lang="ro">Descoperiți comunități noi cu Spații Matrix</caption>
|
||||
<caption xml:lang="ru">Поиск новых сообществ с помощью Matrix Spaces</caption>
|
||||
<caption xml:lang="sa">Matrix Spaces इत्यनेन सह नूतनानां समुदायानाम् अन्वेषणं कुर्वन्तु</caption>
|
||||
<caption xml:lang="sl">Odkrijte nove skupnosti z Matrix Spaces</caption>
|
||||
@@ -433,7 +424,6 @@
|
||||
<caption xml:lang="pl">Główny widok z wykazem pokojów, rozmowami i szczegółami pokojów</caption>
|
||||
<caption xml:lang="pt">A área principal com a lista de salas e com informações sobre a conversa e a sala</caption>
|
||||
<caption xml:lang="pt-BR">Visão principal com lista de salas, bate-papo e informações sobre as salas</caption>
|
||||
<caption xml:lang="ro">Vederea principală cu lista de camere, discuție, și informații despre cameră</caption>
|
||||
<caption xml:lang="ru">Главное окно со списком комнат, чатом и информацией о комнате</caption>
|
||||
<caption xml:lang="sa">कक्षसूची, गपशपः, कक्षसूचना च सह मुख्यदृश्यम्</caption>
|
||||
<caption xml:lang="sl">Glavni pogled s seznamom sob, klepetom in informacijami o sobah</caption>
|
||||
@@ -472,7 +462,6 @@
|
||||
<caption xml:lang="pl">Ekran logowania</caption>
|
||||
<caption xml:lang="pt">Ecrã de autenticação</caption>
|
||||
<caption xml:lang="pt-BR">Tela de login</caption>
|
||||
<caption xml:lang="ro">Ecran de autentificare</caption>
|
||||
<caption xml:lang="ru">Окно входа</caption>
|
||||
<caption xml:lang="sa">लॉगिन् स्क्रीन</caption>
|
||||
<caption xml:lang="sl">Prijavni zaslon</caption>
|
||||
@@ -487,10 +476,6 @@
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
</content_rating>
|
||||
<releases>
|
||||
<release version="25.12.1" date="2026-01-08"/>
|
||||
<release version="25.12.0" date="2025-12-11"/>
|
||||
<release version="25.08.3" date="2025-11-06"/>
|
||||
<release version="25.08.2" date="2025-10-09"/>
|
||||
<release version="25.08.1" date="2025-09-11"/>
|
||||
<release version="25.08.0" date="2025-08-14"/>
|
||||
<release version="25.04.3" date="2025-07-03"/>
|
||||
|
||||
@@ -108,12 +108,10 @@ Comment[ia]=Conversation en ditecto sur Matrix
|
||||
Comment[it]= su Matrix
|
||||
Comment[ka]=ჩატი Matrix-ზე
|
||||
Comment[ko]=Matrix에서 대화하기
|
||||
Comment[lt]=Pokalbiai per Matrix
|
||||
Comment[lv]=Tērzējiet „Matrix“ tīklā
|
||||
Comment[nl]=Chat op Matrix
|
||||
Comment[pl]=Rozmawiaj na Matriksie
|
||||
Comment[pt_BR]=Bate papo na Matrix
|
||||
Comment[ro]=Discutați pe Matrix
|
||||
Comment[ru]=Общение в Matrix
|
||||
Comment[sa]=Matrix इत्यत्र गपशपं कुर्वन्तु
|
||||
Comment[sl]=Klepet na Matrixu
|
||||
|
||||
2431
po/ar/neochat.po
2431
po/ar/neochat.po
File diff suppressed because it is too large
Load Diff
1948
po/ast/neochat.po
1948
po/ast/neochat.po
File diff suppressed because it is too large
Load Diff
2422
po/az/neochat.po
2422
po/az/neochat.po
File diff suppressed because it is too large
Load Diff
2289
po/ca/neochat.po
2289
po/ca/neochat.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2085
po/cs/neochat.po
2085
po/cs/neochat.po
File diff suppressed because it is too large
Load Diff
2259
po/da/neochat.po
2259
po/da/neochat.po
File diff suppressed because it is too large
Load Diff
3310
po/de/neochat.po
3310
po/de/neochat.po
File diff suppressed because it is too large
Load Diff
2522
po/el/neochat.po
2522
po/el/neochat.po
File diff suppressed because it is too large
Load Diff
2587
po/en_GB/neochat.po
2587
po/en_GB/neochat.po
File diff suppressed because it is too large
Load Diff
2570
po/eo/neochat.po
2570
po/eo/neochat.po
File diff suppressed because it is too large
Load Diff
2134
po/es/neochat.po
2134
po/es/neochat.po
File diff suppressed because it is too large
Load Diff
2434
po/eu/neochat.po
2434
po/eu/neochat.po
File diff suppressed because it is too large
Load Diff
2869
po/fi/neochat.po
2869
po/fi/neochat.po
File diff suppressed because it is too large
Load Diff
2438
po/fr/neochat.po
2438
po/fr/neochat.po
File diff suppressed because it is too large
Load Diff
7146
po/ga/neochat.po
7146
po/ga/neochat.po
File diff suppressed because it is too large
Load Diff
2580
po/gl/neochat.po
2580
po/gl/neochat.po
File diff suppressed because it is too large
Load Diff
2349
po/he/neochat.po
2349
po/he/neochat.po
File diff suppressed because it is too large
Load Diff
2540
po/hi/neochat.po
2540
po/hi/neochat.po
File diff suppressed because it is too large
Load Diff
2844
po/hu/neochat.po
2844
po/hu/neochat.po
File diff suppressed because it is too large
Load Diff
2580
po/ia/neochat.po
2580
po/ia/neochat.po
File diff suppressed because it is too large
Load Diff
2509
po/id/neochat.po
2509
po/id/neochat.po
File diff suppressed because it is too large
Load Diff
2397
po/ie/neochat.po
2397
po/ie/neochat.po
File diff suppressed because it is too large
Load Diff
2409
po/it/neochat.po
2409
po/it/neochat.po
File diff suppressed because it is too large
Load Diff
1945
po/ja/neochat.po
1945
po/ja/neochat.po
File diff suppressed because it is too large
Load Diff
2339
po/ka/neochat.po
2339
po/ka/neochat.po
File diff suppressed because it is too large
Load Diff
2962
po/ko/neochat.po
2962
po/ko/neochat.po
File diff suppressed because it is too large
Load Diff
3141
po/lt/neochat.po
3141
po/lt/neochat.po
File diff suppressed because it is too large
Load Diff
2716
po/lv/neochat.po
2716
po/lv/neochat.po
File diff suppressed because it is too large
Load Diff
2356
po/nl/neochat.po
2356
po/nl/neochat.po
File diff suppressed because it is too large
Load Diff
2271
po/nn/neochat.po
2271
po/nn/neochat.po
File diff suppressed because it is too large
Load Diff
2411
po/pa/neochat.po
2411
po/pa/neochat.po
File diff suppressed because it is too large
Load Diff
2495
po/pl/neochat.po
2495
po/pl/neochat.po
File diff suppressed because it is too large
Load Diff
2492
po/pt/neochat.po
2492
po/pt/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 % Brazilian-Portuguese "INCLUDE">
|
||||
]>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
|
||||
SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
-->
|
||||
|
||||
<refentry lang="&language;">
|
||||
<refentryinfo>
|
||||
<title
|
||||
>Manual do Usuário do NeoChat</title>
|
||||
<author
|
||||
><firstname
|
||||
>Carl</firstname
|
||||
><surname
|
||||
>Schwan</surname
|
||||
> <contrib
|
||||
>NeoChat man page.</contrib
|
||||
> <email
|
||||
>carl@carlschwan.eu</email
|
||||
></author>
|
||||
<date
|
||||
>01/11/2022</date>
|
||||
<releaseinfo
|
||||
>22.09</releaseinfo>
|
||||
<productname
|
||||
>NeoChat</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>
|
||||
<command
|
||||
>neochat</command>
|
||||
</refentrytitle>
|
||||
<manvolnum
|
||||
>1</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname
|
||||
>neochat</refname>
|
||||
<refpurpose
|
||||
>Cliente para interação com o protocolo de mensagens Matrix.</refpurpose>
|
||||
</refnamediv>
|
||||
<!-- body begins here -->
|
||||
<refsynopsisdiv id='synopsis'>
|
||||
<cmdsynopsis
|
||||
><command
|
||||
>neochat</command
|
||||
> <arg choice="opt"
|
||||
><replaceable
|
||||
>URI</replaceable
|
||||
></arg
|
||||
> </cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
|
||||
<refsect1 id="description">
|
||||
<title
|
||||
>Descrição</title>
|
||||
<para
|
||||
>O <command
|
||||
>neochat</command
|
||||
> é um aplicativo de bate-papo para o protocolo Matrix. Ele funciona tanto em computadores quanto em dispositivos móveis. </para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="options"
|
||||
><title
|
||||
>Opções</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term
|
||||
><option
|
||||
>URI</option
|
||||
></term>
|
||||
<listitem>
|
||||
<para
|
||||
>O URI da matriz para um usuário ou uma sala. Por exemplo, matrix:u/usuário:exemplo.org e matrix:r/root:exemplo.org. Isso fará com que o NeoChat tente abrir a sala ou conversa especificada. </para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="bug">
|
||||
<title
|
||||
>Relatar bugs</title>
|
||||
<para
|
||||
>Você pode reportar erros e solicitar novas funcionalidades em <ulink url="https://bugs.kde.org/enter_bug.cgi?product=NeoChat&component=General"
|
||||
>https://bugs.kde.org/enter_bug.cgi?product=NeoChat&component=General</ulink
|
||||
></para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title
|
||||
>Veja também</title>
|
||||
<simplelist>
|
||||
<member
|
||||
>Lista de perguntas frequentes sobre o Matrix <ulink url="https://matrix.org/faq/"
|
||||
>https://matrix.org/faq/</ulink
|
||||
> </member>
|
||||
<member
|
||||
>kf5options(7)</member>
|
||||
<member
|
||||
>qt5options(7)</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="copyright"
|
||||
><title
|
||||
>Direitos autorais</title>
|
||||
<para
|
||||
>Direitos autorais © 2020-2022 Tobias Fella </para>
|
||||
<para
|
||||
>Direitos autorais © 2020-2022 Carl Schwan </para>
|
||||
<para
|
||||
>Licença: GNU General Public Versão 3 ou posterior <ulink url="https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
>https://www.gnu.org/licenses/gpl-3.0.html</ulink
|
||||
>></para>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
2357
po/pt_BR/neochat.po
2357
po/pt_BR/neochat.po
File diff suppressed because it is too large
Load Diff
7339
po/ro/neochat.po
7339
po/ro/neochat.po
File diff suppressed because it is too large
Load Diff
2602
po/ru/neochat.po
2602
po/ru/neochat.po
File diff suppressed because it is too large
Load Diff
2546
po/sa/neochat.po
2546
po/sa/neochat.po
File diff suppressed because it is too large
Load Diff
2443
po/sk/neochat.po
2443
po/sk/neochat.po
File diff suppressed because it is too large
Load Diff
2293
po/sl/neochat.po
2293
po/sl/neochat.po
File diff suppressed because it is too large
Load Diff
2553
po/sv/neochat.po
2553
po/sv/neochat.po
File diff suppressed because it is too large
Load Diff
2870
po/ta/neochat.po
2870
po/ta/neochat.po
File diff suppressed because it is too large
Load Diff
2280
po/tok/neochat.po
2280
po/tok/neochat.po
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
>carl@carlschwan.eu</email
|
||||
></author>
|
||||
<date
|
||||
>2022‒11‒01</date>
|
||||
>2022-11-01</date>
|
||||
<releaseinfo
|
||||
>22.09</releaseinfo>
|
||||
<productname
|
||||
@@ -111,9 +111,9 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
||||
><title
|
||||
>Telif Hakkı</title>
|
||||
<para
|
||||
>Telif hakkı © 2020–2022 Tobias Fella </para>
|
||||
>Telif hakkı © 2020-2022 Tobias Fella </para>
|
||||
<para
|
||||
>Telif hakkı © 2020–2022 Carl Schwan </para>
|
||||
>Telif hakkı © 2020-2022 Carl Schwan </para>
|
||||
<para
|
||||
>Lisans: GNU Genel Kamu Lisansa, 3. sürüm veya sonrası <<ulink url="https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
>https://www.gnu.org/licenses/gpl-3.0.html</ulink
|
||||
|
||||
2309
po/tr/neochat.po
2309
po/tr/neochat.po
File diff suppressed because it is too large
Load Diff
2331
po/uk/neochat.po
2331
po/uk/neochat.po
File diff suppressed because it is too large
Load Diff
2261
po/zh_CN/neochat.po
2261
po/zh_CN/neochat.po
File diff suppressed because it is too large
Load Diff
2725
po/zh_TW/neochat.po
2725
po/zh_TW/neochat.po
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
# SPDX-FileCopyrightText: 2020-2021 Tobias Fella <tobias.fella@kde.org>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
qt_add_library(neochat STATIC
|
||||
add_library(neochat STATIC
|
||||
controller.cpp
|
||||
controller.h
|
||||
roommanager.cpp
|
||||
@@ -35,8 +35,6 @@ qt_add_library(neochat STATIC
|
||||
models/commonroomsmodel.h
|
||||
texttospeechhelper.h
|
||||
texttospeechhelper.cpp
|
||||
models/limitermodel.cpp
|
||||
models/limitermodel.h
|
||||
)
|
||||
|
||||
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
|
||||
@@ -105,8 +103,6 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
|
||||
qml/ReasonDialog.qml
|
||||
qml/NewPollDialog.qml
|
||||
qml/UserMenu.qml
|
||||
qml/MeetingDialog.qml
|
||||
qml/SeenByDialog.qml
|
||||
DEPENDENCIES
|
||||
QtCore
|
||||
QtQuick
|
||||
@@ -143,17 +139,10 @@ if(WIN32)
|
||||
set_target_properties(neochat PROPERTIES OUTPUT_NAME "neochatlib")
|
||||
endif()
|
||||
|
||||
qt_add_executable(neochat-app
|
||||
add_executable(neochat-app
|
||||
main.cpp
|
||||
)
|
||||
|
||||
if(ANDROID)
|
||||
set_target_properties(neochat-app PROPERTIES
|
||||
OUTPUT_NAME "neochat-app"
|
||||
PREFIX "lib"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(TARGET Qt::WebView)
|
||||
target_link_libraries(neochat-app PUBLIC Qt::WebView)
|
||||
target_compile_definitions(neochat-app PUBLIC -DHAVE_WEBVIEW)
|
||||
@@ -163,7 +152,6 @@ target_include_directories(neochat-app PRIVATE ${CMAKE_BINARY_DIR})
|
||||
|
||||
target_link_libraries(neochat-app PRIVATE
|
||||
neochat
|
||||
KF6::IconThemes
|
||||
)
|
||||
|
||||
ecm_add_app_icon(NEOCHAT_ICON ICONS ${CMAKE_SOURCE_DIR}/128-logo.png)
|
||||
@@ -194,7 +182,7 @@ else()
|
||||
endif()
|
||||
|
||||
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/models)
|
||||
target_link_libraries(neochat PRIVATE neochatplugin Loginplugin Roomsplugin RoomInfoplugin MessageContentplugin Timelineplugin Spacesplugin Chatbarplugin Settingsplugin Devtoolsplugin)
|
||||
target_link_libraries(neochat PRIVATE Loginplugin Roomsplugin RoomInfoplugin MessageContentplugin Timelineplugin Spacesplugin Chatbarplugin Settingsplugin Devtoolsplugin)
|
||||
target_link_libraries(neochat PUBLIC
|
||||
LibNeoChat
|
||||
Timeline
|
||||
@@ -214,9 +202,8 @@ target_link_libraries(neochat PUBLIC
|
||||
KF6::ConfigGui
|
||||
KF6::CoreAddons
|
||||
KF6::SonnetCore
|
||||
KF6::IconThemes
|
||||
KF6::ItemModels
|
||||
KF6::I18nQml
|
||||
KirigamiApp
|
||||
QuotientQt6
|
||||
Login
|
||||
Rooms
|
||||
@@ -224,6 +211,10 @@ target_link_libraries(neochat PUBLIC
|
||||
Spaces
|
||||
)
|
||||
|
||||
if (TARGET KF6::Crash)
|
||||
target_link_libraries(neochat PUBLIC KF6::Crash)
|
||||
endif()
|
||||
|
||||
kconfig_target_kcfg_file(neochat FILE neochatconfig.kcfg CLASS_NAME NeoChatConfig MUTATORS GENERATE_PROPERTIES DEFAULT_VALUE_GETTERS PARENT_IN_CONSTRUCTOR SINGLETON GENERATE_MOC QML_REGISTRATION)
|
||||
|
||||
if(NEOCHAT_FLATPAK)
|
||||
@@ -334,7 +325,6 @@ if(ANDROID)
|
||||
"kt-restore-defaults-symbolic"
|
||||
"user-symbolic"
|
||||
"mark-location-symbolic"
|
||||
"amarok_playcount"
|
||||
|
||||
${KIRIGAMI_ADDONS_ICONS}
|
||||
)
|
||||
@@ -363,8 +353,7 @@ endif()
|
||||
install(TARGETS neochat-app ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
||||
# krunner plugin must be the same as the app id for flatpak to export it
|
||||
install(FILES plasma-runner-neochat.desktop DESTINATION ${KDE_INSTALL_DATAROOTDIR}/krunner/dbusplugins RENAME org.kde.neochat.desktop)
|
||||
install(FILES plasma-runner-neochat.desktop DESTINATION ${KDE_INSTALL_DATAROOTDIR}/krunner/dbusplugins)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <Quotient/qt_connection_util.h>
|
||||
#include <Quotient/settings.h>
|
||||
|
||||
#include "accountmanager.h"
|
||||
#include "enums/roomsortparameter.h"
|
||||
#include "general_logging.h"
|
||||
#include "mediasizehelper.h"
|
||||
@@ -25,7 +26,9 @@
|
||||
#include "models/roomlistmodel.h"
|
||||
#include "models/roomtreemodel.h"
|
||||
#include "neochatconfig.h"
|
||||
#include "neochatconnection.h"
|
||||
#include "neochatroom.h"
|
||||
#include "notificationsmanager.h"
|
||||
#include "proxycontroller.h"
|
||||
#include "roommanager.h"
|
||||
|
||||
@@ -246,10 +249,7 @@ void Controller::initActiveConnection(NeoChatConnection *oldConnection, NeoChatC
|
||||
if (newConnection) {
|
||||
connect(newConnection, &NeoChatConnection::errorOccured, this, &Controller::errorOccured);
|
||||
connect(newConnection, &NeoChatConnection::badgeNotificationCountChanged, this, &Controller::updateBadgeNotificationCount);
|
||||
|
||||
// Refresh and update manually, in case we init too late for the badge count to actually change.
|
||||
newConnection->refreshBadgeNotificationCount();
|
||||
updateBadgeNotificationCount(newConnection->badgeNotificationCount());
|
||||
}
|
||||
Q_EMIT activeConnectionChanged(newConnection);
|
||||
}
|
||||
@@ -309,7 +309,8 @@ void Controller::listenForNotifications()
|
||||
connect(timer, &QTimer::timeout, qGuiApp, &QGuiApplication::quit);
|
||||
|
||||
connect(connector, &KUnifiedPush::Connector::messageReceived, [timer](const QByteArray &data) {
|
||||
NotificationsManager::postPushNotification(data);
|
||||
instance().m_notificationsManager.postPushNotification(data);
|
||||
timer->stop();
|
||||
});
|
||||
|
||||
// Wait five seconds to see if we received any messages or this happened to be an erroneous activation.
|
||||
|
||||
@@ -33,10 +33,13 @@
|
||||
#include <KWindowSystem>
|
||||
#endif
|
||||
|
||||
#if __has_include("KCrash")
|
||||
#include <KCrash>
|
||||
#endif
|
||||
|
||||
#include <KIconTheme>
|
||||
#include <KLocalizedQmlContext>
|
||||
#include <KLocalizedContext>
|
||||
#include <KLocalizedString>
|
||||
#include <KirigamiApp>
|
||||
|
||||
#include "neochat-version.h"
|
||||
|
||||
@@ -101,11 +104,8 @@ Q_DECL_EXPORT
|
||||
#endif
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
|
||||
// We currently need to do this ourselves,
|
||||
// KirigamiApp currently called this after constructing the app which breaks icons on Windows.
|
||||
KIconTheme::initTheme();
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
|
||||
#ifdef HAVE_WEBVIEW
|
||||
QtWebView::initialize();
|
||||
@@ -113,10 +113,24 @@ int main(int argc, char *argv[])
|
||||
QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
|
||||
#endif
|
||||
|
||||
KirigamiApp::App app(argc, argv);
|
||||
KirigamiApp kirigamiApp;
|
||||
#ifdef Q_OS_ANDROID
|
||||
QGuiApplication app(argc, argv);
|
||||
QQuickStyle::setStyle(u"org.kde.breeze"_s);
|
||||
#else
|
||||
QIcon::setFallbackThemeName("breeze"_L1);
|
||||
QApplication app(argc, argv);
|
||||
// Default to org.kde.desktop style unless the user forces another style
|
||||
if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) {
|
||||
QQuickStyle::setStyle(u"org.kde.desktop"_s);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
freopen("CONOUT$", "w", stderr);
|
||||
}
|
||||
|
||||
QApplication::setStyle(u"breeze"_s);
|
||||
QFont font(u"Segoe UI Emoji"_s);
|
||||
font.setPointSize(10);
|
||||
@@ -163,9 +177,19 @@ int main(int argc, char *argv[])
|
||||
KAboutData::setApplicationData(about);
|
||||
QGuiApplication::setWindowIcon(QIcon::fromTheme(u"org.kde.neochat"_s));
|
||||
|
||||
#if __has_include("KCrash")
|
||||
KCrash::initialize();
|
||||
#endif
|
||||
|
||||
Connection::setEncryptionDefault(true);
|
||||
Connection::setDirectChatEncryptionDefault(true);
|
||||
|
||||
#ifdef NEOCHAT_FLATPAK
|
||||
// Copy over the included FontConfig configuration to the
|
||||
// app's config dir:
|
||||
QFile::copy(u"/app/etc/fonts/conf.d/99-noto-mono-color-emoji.conf"_s, u"/var/config/fontconfig/conf.d/99-noto-mono-color-emoji.conf"_s);
|
||||
#endif
|
||||
|
||||
ColorSchemer colorScheme;
|
||||
|
||||
QCommandLineParser parser;
|
||||
@@ -181,7 +205,7 @@ int main(int argc, char *argv[])
|
||||
parser.addOption(testOption);
|
||||
|
||||
#ifdef HAVE_KUNIFIEDPUSH
|
||||
QCommandLineOption dbusActivatedOption(u"dbus-activated"_s);
|
||||
QCommandLineOption dbusActivatedOption(u"dbus-activated"_s, i18n("Internal usage only."));
|
||||
dbusActivatedOption.setFlags(QCommandLineOption::Flag::HiddenFromHelp);
|
||||
parser.addOption(dbusActivatedOption);
|
||||
#endif
|
||||
@@ -195,14 +219,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
#ifdef HAVE_KUNIFIEDPUSH
|
||||
if (parser.isSet(dbusActivatedOption)) {
|
||||
#ifdef HAVE_KDBUSADDONS
|
||||
// We *don't* want to use KDBusService here. I don't know why, but it makes activation super unreliable. We don't really need it anyway.
|
||||
if (!QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.neochat"))) {
|
||||
// Gracefully fail if NeoChat is already running
|
||||
qWarning() << "NeoChat already running, not sending push notifications.";
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
// We want to be replaceable by the main client
|
||||
KDBusService service(KDBusService::Replace);
|
||||
|
||||
#ifdef HAVE_RUNNER
|
||||
// If we are built with KRunner and KUnifiedPush support, we need to do something special.
|
||||
@@ -261,7 +279,7 @@ int main(int argc, char *argv[])
|
||||
});
|
||||
#endif
|
||||
|
||||
KLocalization::setupLocalizedContext(&engine);
|
||||
engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
|
||||
engine.setNetworkAccessManagerFactory(new NetworkAccessManagerFactory());
|
||||
|
||||
if (parser.isSet("ignore-ssl-errors"_L1)) {
|
||||
@@ -276,9 +294,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
engine.addImageProvider(u"blurhash"_s, new BlurhashImageProvider);
|
||||
|
||||
if (!kirigamiApp.start("org.kde.neochat", "Main", &engine)) {
|
||||
return -1;
|
||||
}
|
||||
engine.loadFromModule("org.kde.neochat", "Main");
|
||||
|
||||
if (!parser.positionalArguments().isEmpty() && !parser.isSet("share"_L1)) {
|
||||
RoomManager::instance().setUrlArgument(parser.positionalArguments()[0]);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "jobs/neochatgetcommonroomsjob.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <Quotient/room.h>
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
@@ -40,22 +39,8 @@ void CommonRoomsModel::setUserId(const QString &userId)
|
||||
|
||||
QVariant CommonRoomsModel::data(const QModelIndex &index, int roleName) const
|
||||
{
|
||||
auto roomId = m_commonRooms[index.row()];
|
||||
auto room = connection()->room(roomId);
|
||||
if (!room) {
|
||||
return {};
|
||||
}
|
||||
|
||||
switch (roleName) {
|
||||
case Qt::DisplayRole:
|
||||
case RoomNameRole:
|
||||
return room->displayName();
|
||||
case RoomAvatarRole:
|
||||
return room->avatarUrl();
|
||||
case RoomIdRole:
|
||||
return roomId;
|
||||
}
|
||||
|
||||
Q_UNUSED(index)
|
||||
Q_UNUSED(roleName)
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -65,15 +50,6 @@ int CommonRoomsModel::rowCount(const QModelIndex &parent) const
|
||||
return m_commonRooms.size();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> CommonRoomsModel::roleNames() const
|
||||
{
|
||||
return {
|
||||
{RoomIdRole, "roomId"},
|
||||
{RoomNameRole, "roomName"},
|
||||
{RoomAvatarRole, "roomAvatar"},
|
||||
};
|
||||
}
|
||||
|
||||
void CommonRoomsModel::reload()
|
||||
{
|
||||
if (!m_connection || m_userId.isEmpty()) {
|
||||
|
||||
@@ -24,9 +24,7 @@ class CommonRoomsModel : public QAbstractListModel
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
RoomIdRole = Qt::UserRole,
|
||||
RoomNameRole,
|
||||
RoomAvatarRole,
|
||||
RoomIdRole = Qt::DisplayRole,
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
@@ -41,8 +39,6 @@ public:
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int roleName) const override;
|
||||
[[nodiscard]] Q_INVOKABLE int rowCount(const QModelIndex &parent = {}) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void connectionChanged();
|
||||
void userIdChanged();
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2024 Joshua Goins <josh@redstrate.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "models/limitermodel.h"
|
||||
|
||||
LimiterModel::LimiterModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
connect(this, &QSortFilterProxyModel::rowsInserted, this, &LimiterModel::extraCountChanged);
|
||||
connect(this, &QSortFilterProxyModel::rowsRemoved, this, &LimiterModel::extraCountChanged);
|
||||
connect(this, &QSortFilterProxyModel::modelReset, this, &LimiterModel::extraCountChanged);
|
||||
}
|
||||
|
||||
int LimiterModel::maximumCount() const
|
||||
{
|
||||
return m_maximumCount;
|
||||
}
|
||||
|
||||
void LimiterModel::setMaximumCount(int maximumCount)
|
||||
{
|
||||
if (m_maximumCount != maximumCount) {
|
||||
m_maximumCount = maximumCount;
|
||||
Q_EMIT maximumCountChanged();
|
||||
}
|
||||
}
|
||||
|
||||
int LimiterModel::extraCount() const
|
||||
{
|
||||
if (sourceModel()) {
|
||||
return std::max(sourceModel()->rowCount() - maximumCount(), 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool LimiterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
Q_UNUSED(source_parent)
|
||||
return source_row < maximumCount();
|
||||
}
|
||||
|
||||
#include "moc_limitermodel.cpp"
|
||||
@@ -1,41 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2024 Joshua Goins <josh@redstrate.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QQmlEngine>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
/**
|
||||
* @class LimiterModel
|
||||
*
|
||||
* @brief Takes a source QAbstractItemModel model and only displays a desired maximum amount.
|
||||
*
|
||||
* Also gives you the remaining (filtered out) items, useful for sticking in a label or somesuch.
|
||||
*/
|
||||
class LimiterModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(int maximumCount READ maximumCount WRITE setMaximumCount NOTIFY maximumCountChanged)
|
||||
Q_PROPERTY(int extraCount READ extraCount NOTIFY extraCountChanged)
|
||||
|
||||
public:
|
||||
explicit LimiterModel(QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] int maximumCount() const;
|
||||
void setMaximumCount(int maximumCount);
|
||||
|
||||
[[nodiscard]] int extraCount() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void maximumCountChanged();
|
||||
void extraCountChanged();
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
||||
|
||||
private:
|
||||
int m_maximumCount = 0;
|
||||
};
|
||||
@@ -211,7 +211,6 @@ Name[pa]=ਨਵਾਂ ਸੱਦਾ
|
||||
Name[pl]=Nowe zaproszenie
|
||||
Name[pt]=Novo Convite
|
||||
Name[pt_BR]=Novo convite
|
||||
Name[ro]=Invitație nouă
|
||||
Name[ru]=Новое приглашение
|
||||
Name[sa]=नवीन आमन्त्रणम्
|
||||
Name[sl]=Novo povabilo
|
||||
@@ -253,13 +252,12 @@ Comment[pa]=ਰੂਮ ਲਈ ਨਵਾਂ ਸੱਦਾ ਹੈ
|
||||
Comment[pl]=Dostępna jest nowe zaproszenie do pokoju
|
||||
Comment[pt]=Existe um novo convite para uma sala
|
||||
Comment[pt_BR]=Existe um novo convite para uma sala
|
||||
Comment[ro]=E o nouă invitație la o cameră
|
||||
Comment[ru]=Доступно новое приглашение в комнату
|
||||
Comment[sa]=कक्षस्य नूतनं निमन्त्रणम् अस्ति
|
||||
Comment[sl]=Tam je novo povabilo v sobo
|
||||
Comment[sv]=Det finns en ny inbjudan till ett rum
|
||||
Comment[ta]=ஓர் அரங்கிற்கான புதிய அழைப்பிதழ் உள்ளது
|
||||
Comment[tr]=Bir odaya yeni bir davet var
|
||||
Comment[tr]=Bir odaya yeni bir davetiye var
|
||||
Comment[uk]=У кімнаті нове запрошення
|
||||
Comment[zh_CN]=有新的聊天室邀请
|
||||
Comment[zh_TW]=有新的加入聊天室邀請
|
||||
@@ -287,13 +285,11 @@ Name[ia]=Comparti
|
||||
Name[it]=Condivisione
|
||||
Name[ka]=გაზიარება
|
||||
Name[ko]=공유
|
||||
Name[lt]=Bendrinti
|
||||
Name[lv]=Kopīgot
|
||||
Name[nl]=Gedeelde
|
||||
Name[nn]=Del
|
||||
Name[pl]=Udostępnij
|
||||
Name[pt_BR]=Compartilhar
|
||||
Name[ro]=Partajare
|
||||
Name[ru]=Публикация
|
||||
Name[sa]=संविभागः
|
||||
Name[sl]=Deli
|
||||
@@ -323,13 +319,11 @@ Comment[ia]=Le exito de compartir un pecietta de contento
|
||||
Comment[it]=Il risultato della condivisione di un contenuto
|
||||
Comment[ka]=შემცველობის ნაწილის გაზიარების შედეგი
|
||||
Comment[ko]=콘텐츠 공유 결과
|
||||
Comment[lt]=Turinio dalies bendrinimo rezultatas
|
||||
Comment[lv]=Satura kopīgošanas rezultāts
|
||||
Comment[nl]=Het resultaat van het delen van een stukje inhoud
|
||||
Comment[nn]=Resultatet av deling av innhald
|
||||
Comment[pl]=Wynik udostępniania kawałka treści
|
||||
Comment[pt_BR]=O resultado de compartilhar um conteúdo
|
||||
Comment[ro]=Rezultatul partajării unei bucăți de conținut
|
||||
Comment[ru]=Результат публикации данных
|
||||
Comment[sa]=सामग्रीखण्डस्य साझाकरणस्य परिणामः
|
||||
Comment[sl]=Rezultat deljenega kosa vsebine
|
||||
|
||||
@@ -66,10 +66,6 @@
|
||||
</entry>
|
||||
</group>
|
||||
<group name="Timeline">
|
||||
<entry name="FontScale" type="double">
|
||||
<label>Scaling factor for font sizes</label>
|
||||
<default>1.0</default>
|
||||
</entry>
|
||||
<entry name="ShowAvatarInTimeline" type="bool">
|
||||
<label>Show avatar in the timeline</label>
|
||||
<default>true</default>
|
||||
@@ -211,6 +207,10 @@
|
||||
<label>Enable threads</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="SecretBackup" type="bool">
|
||||
<label>Enable secret backup</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="Phone3PId" type="bool">
|
||||
<label>Enable add phone numbers as 3PIDs</label>
|
||||
<default>false</default>
|
||||
|
||||
@@ -216,12 +216,12 @@ void NotificationsManager::postNotification(NeoChatRoom *room,
|
||||
}
|
||||
});
|
||||
|
||||
notification->setTitle(room->displayName());
|
||||
|
||||
QString entry;
|
||||
if (room->isDirectChat()) {
|
||||
if (sender == room->displayName()) {
|
||||
notification->setTitle(sender);
|
||||
entry = text.toHtmlEscaped();
|
||||
} else {
|
||||
notification->setTitle(room->displayName());
|
||||
entry = i18n("%1: %2", sender, text.toHtmlEscaped());
|
||||
}
|
||||
|
||||
@@ -253,9 +253,7 @@ void NotificationsManager::postNotification(NeoChatRoom *room,
|
||||
notification->setReplyAction(std::move(replyAction));
|
||||
}
|
||||
|
||||
if (Controller::instance().accounts()->rowCount() > 1) {
|
||||
notification->setHint(u"x-kde-origin-name"_s, room->localMember().id());
|
||||
}
|
||||
notification->setHint(u"x-kde-origin-name"_s, room->localMember().id());
|
||||
notification->sendEvent();
|
||||
}
|
||||
|
||||
@@ -349,9 +347,7 @@ void NotificationsManager::doPostInviteNotification(QPointer<NeoChatRoom> room)
|
||||
m_invitations.remove(room->id());
|
||||
});
|
||||
|
||||
if (Controller::instance().accounts()->rowCount() > 1) {
|
||||
notification->setHint(u"x-kde-origin-name"_s, room->localMember().id());
|
||||
}
|
||||
notification->setHint(u"x-kde-origin-name"_s, room->localMember().id());
|
||||
|
||||
notification->sendEvent();
|
||||
}
|
||||
@@ -392,7 +388,7 @@ void NotificationsManager::postPushNotification(const QByteArray &message)
|
||||
|
||||
#ifdef HAVE_KIO
|
||||
auto openAction = notification->addAction(i18n("Open NeoChat"));
|
||||
connect(openAction, &KNotificationAction::activated, notification, [=]() {
|
||||
connect(openAction, &KNotificationAction::activated, this, [=]() {
|
||||
QString properId = roomId;
|
||||
properId = properId.replace(u"#"_s, QString());
|
||||
properId = properId.replace(u"!"_s, QString());
|
||||
@@ -406,6 +402,8 @@ void NotificationsManager::postPushNotification(const QByteArray &message)
|
||||
connect(notification, &KNotification::closed, qGuiApp, &QGuiApplication::quit);
|
||||
|
||||
notification->sendEvent();
|
||||
|
||||
m_notifications.insert(roomId, {json["ts"_L1].toVariant().toLongLong(), notification});
|
||||
} else {
|
||||
qWarning() << "Skipping unsupported push notification" << type;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
/**
|
||||
* @brief Display a native notification for the given push notification.
|
||||
*/
|
||||
static void postPushNotification(const QByteArray &message);
|
||||
void postPushNotification(const QByteArray &message);
|
||||
|
||||
/**
|
||||
* @brief Handle the notifications for the given connection.
|
||||
|
||||
@@ -75,7 +75,6 @@ Comment[nn]=Finn rom i NeoChat
|
||||
Comment[pl]=Znajdź pokoje w NeoChat
|
||||
Comment[pt]=Procurar salas no NeoChat
|
||||
Comment[pt_BR]=Encontrar salas no NeoChat
|
||||
Comment[ro]=Găsește camere în NeoChat
|
||||
Comment[ru]=Поиск комнат NeoChat
|
||||
Comment[sa]=NeoChat इत्यत्र कक्ष्याः अन्वेषणं कुर्वन्तु
|
||||
Comment[sl]=Najdi sobe v NeoChatu
|
||||
|
||||
@@ -79,6 +79,7 @@ KirigamiComponents.ConvergentContextMenu {
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:inmenu", "Open Secret Backup")
|
||||
icon.name: "unlock"
|
||||
visible: NeoChatConfig.secretBackup
|
||||
onTriggered: root.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'UnlockSSSSDialog'), {}, {
|
||||
title: i18nc("@title:window", "Open Key Backup")
|
||||
})
|
||||
|
||||
@@ -91,7 +91,6 @@ Components.AbstractMaximizeComponent {
|
||||
color: Kirigami.Theme.textColor
|
||||
|
||||
font.family: "monospace"
|
||||
font.pointSize: Kirigami.Theme.defaultFont.pointSize * NeoChatConfig.fontScale
|
||||
|
||||
Kirigami.SpellCheck.enabled: false
|
||||
|
||||
|
||||
@@ -22,12 +22,12 @@ Labs.MenuBar {
|
||||
|
||||
Labs.MenuItem {
|
||||
icon.name: "list-add-user"
|
||||
text: i18nc("@action:inmenu", "Find User")
|
||||
text: i18nc("@action:inmenu", "Find your Friends")
|
||||
enabled: root.connection
|
||||
onTriggered: root.appWindow.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'UserSearchPage'), {
|
||||
connection: root.connection
|
||||
}, {
|
||||
title: i18nc("@title", "Find User")
|
||||
title: i18nc("@title", "Find your friends")
|
||||
})
|
||||
}
|
||||
Labs.MenuItem {
|
||||
@@ -45,12 +45,14 @@ Labs.MenuBar {
|
||||
}
|
||||
Labs.MenuItem {
|
||||
icon.name: "compass-symbolic"
|
||||
text: i18nc("@action:inmenu Explore public rooms and spaces", "Explore")
|
||||
text: i18nc("@action:inmenu", "Explore Rooms")
|
||||
enabled: root.connection
|
||||
onTriggered: {
|
||||
let dialog = root.appWindow.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ExploreRoomsPage'), {
|
||||
connection: root.connection
|
||||
}, {});
|
||||
}, {
|
||||
title: i18nc("@title", "Explore Rooms")
|
||||
});
|
||||
dialog.roomSelected.connect((roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
|
||||
RoomManager.resolveResource(roomId.length > 0 ? roomId : alias, isJoined ? "" : "join");
|
||||
});
|
||||
|
||||
@@ -27,17 +27,16 @@ ColumnLayout {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
KirigamiComponents.AvatarButton {
|
||||
KirigamiComponents.Avatar {
|
||||
id: avatar
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.huge
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.huge
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
name: root.invitingMember.displayName
|
||||
source: NeoChatConfig.hideImages ? undefined : root.invitingMember.avatarUrl
|
||||
color: root.invitingMember.color
|
||||
|
||||
onClicked: RoomManager.resolveResource(root.currentRoom.invitingUserId)
|
||||
}
|
||||
|
||||
Loader {
|
||||
@@ -55,12 +54,6 @@ ColumnLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
Kirigami.Heading {
|
||||
text: root.currentRoom.displayName
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
Kirigami.SelectableLabel {
|
||||
Layout.fillWidth: true
|
||||
font: Kirigami.Theme.smallFont
|
||||
@@ -68,7 +61,12 @@ ColumnLayout {
|
||||
visible: root.currentRoom && root.currentRoom.canonicalAlias
|
||||
text: root.currentRoom && root.currentRoom.canonicalAlias ? root.currentRoom.canonicalAlias : ""
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
Kirigami.Heading {
|
||||
text: root.currentRoom.displayName
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,24 +137,8 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
id: viewProfileDelegate
|
||||
|
||||
icon.name: "user-properties-symbolic"
|
||||
text: i18nc("@action:button View this user's profile", "View %1's Profile", root.invitingMember.displayName)
|
||||
|
||||
onClicked: RoomManager.resolveResource(root.currentRoom.invitingUserId)
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator {
|
||||
above: viewProfileDelegate
|
||||
below: ignoreUserDelegate
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
id: ignoreUserDelegate
|
||||
|
||||
icon.name: "list-remove-symbolic"
|
||||
text: i18nc("@action:button Ignore the user", "Ignore %1 and Reject Invite", root.invitingMember.displayName)
|
||||
text: i18nc("@action:button Block the user", "Block %1", root.invitingMember.displayName)
|
||||
|
||||
onClicked: {
|
||||
root.currentRoom.forget()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
@@ -8,8 +10,8 @@ import QtQuick.Window
|
||||
import QtQml
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.delegates as Delegates
|
||||
import org.kde.neochat
|
||||
import io.github.quotient_im.libquotient
|
||||
|
||||
Kirigami.Page {
|
||||
id: root
|
||||
@@ -163,7 +165,7 @@ Kirigami.Page {
|
||||
}
|
||||
}
|
||||
isDone: root.session.state === KeyVerificationSession.DONE
|
||||
onDone: root.closeDialog()
|
||||
onDone: root.Kirigami.PageStack.closeDialog()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,8 +100,7 @@ Kirigami.ApplicationWindow {
|
||||
|
||||
function onCurrentRoomChanged() {
|
||||
if (RoomManager.currentRoom && root.pageStack.depth <= 1 && root.initialized && Kirigami.Settings.isMobile) {
|
||||
let roomPage = pageStack.push(Qt.createComponent('org.kde.neochat', 'RoomPage'));
|
||||
roomPage.forceActiveFocus();
|
||||
let roomPage = root.pageStack.layers.push(Qt.createComponent('org.kde.neochat', 'RoomPage'));
|
||||
roomPage.backRequested.connect(event => {
|
||||
RoomManager.clearCurrentRoom();
|
||||
});
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
import QtQuick
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
|
||||
Kirigami.PromptDialog {
|
||||
id: root
|
||||
|
||||
required property bool hasExistingMeeting
|
||||
|
||||
title: hasExistingMeeting ? i18nc("@title", "Join Meeting") : i18nc("@title", "Start Meeting")
|
||||
subtitle: hasExistingMeeting ? i18nc("@info:label", "You are about to join a Jitsi meeting in your web browser.") : i18nc("@info:label", "You are about to start a new Jitsi meeting in your web browser.")
|
||||
standardButtons: Kirigami.Dialog.Cancel
|
||||
|
||||
customFooterActions: Kirigami.Action {
|
||||
icon.name: "camera-video-symbolic"
|
||||
text: hasExistingMeeting ? i18nc("@action:button Join the Jitsi meeting", "Join") : i18nc("@action:button Start a new Jitsi meeting", "Start")
|
||||
onTriggered: root.accept()
|
||||
}
|
||||
}
|
||||
@@ -23,45 +23,13 @@ Components.AlbumMaximizeComponent {
|
||||
*/
|
||||
required property NeoChatRoom currentRoom
|
||||
|
||||
readonly property string currentEventId: {
|
||||
const idx = (content as ListView).currentIndex;
|
||||
readonly property string currentEventId: model.data(model.index((content as ListView).currentIndex, 0), TimelineMessageModel.EventIdRole)
|
||||
|
||||
if (idx === -1) {
|
||||
return ""
|
||||
}
|
||||
readonly property var currentAuthor: model.data(model.index((content as ListView).currentIndex, 0), TimelineMessageModel.AuthorRole)
|
||||
|
||||
return model.data(model.index(idx, 0), TimelineMessageModel.EventIdRole)
|
||||
}
|
||||
readonly property var currentTime: model.data(model.index((content as ListView).currentIndex, 0), TimelineMessageModel.TimeRole)
|
||||
|
||||
readonly property var currentAuthor: {
|
||||
const idx = (content as ListView).currentIndex;
|
||||
|
||||
if (idx === -1) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return model.data(model.index(idx, 0), TimelineMessageModel.AuthorRole)
|
||||
}
|
||||
|
||||
readonly property var currentTime: {
|
||||
|
||||
const idx = (content as ListView).currentIndex;
|
||||
|
||||
if (idx === -1) {
|
||||
return {}
|
||||
}
|
||||
|
||||
model.data(model.index(idx, 0), TimelineMessageModel.TimeRole)
|
||||
}
|
||||
|
||||
readonly property var currentProgressInfo: {
|
||||
const idx = (content as ListView).currentIndex;
|
||||
|
||||
if (idx === -1) {
|
||||
return {}
|
||||
}
|
||||
model.data(model.index(idx, 0), TimelineMessageModel.ProgressInfoRole)
|
||||
}
|
||||
readonly property var currentProgressInfo: model.data(model.index((content as ListView).currentIndex, 0), TimelineMessageModel.ProgressInfoRole)
|
||||
|
||||
actions: [
|
||||
ShareAction {
|
||||
@@ -154,10 +122,7 @@ Components.AlbumMaximizeComponent {
|
||||
|
||||
onOpened: forceActiveFocus()
|
||||
|
||||
onItemRightClicked: {
|
||||
const event = root.currentRoom.findEvent(root.currentEventId);
|
||||
RoomManager.viewEventMenu(root.QQC2.Overlay.overlay, event, root.currentRoom)
|
||||
}
|
||||
onItemRightClicked: RoomManager.viewEventMenu(root.currentEventId, root.currentRoom)
|
||||
|
||||
onSaveItem: {
|
||||
var dialog = saveAsDialog.createObject(QQC2.Overlay.overlay) as Dialogs.FileDialog;
|
||||
|
||||
@@ -30,13 +30,15 @@ Kirigami.SearchDialog {
|
||||
emptyText: i18nc("Placeholder message", "No room found")
|
||||
Kirigami.Action {
|
||||
id: exploreRoomAction
|
||||
text: i18nc("@action:button Explore public rooms and spaces", "Explore")
|
||||
text: i18nc("@action:button", "Explore rooms")
|
||||
icon.name: "compass"
|
||||
onTriggered: {
|
||||
root.close()
|
||||
let dialog = root.window.pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ExploreRoomsPage'), {
|
||||
connection: root.connection
|
||||
}, {});
|
||||
}, {
|
||||
title: i18nc("@title", "Explore Rooms")
|
||||
});
|
||||
dialog.roomSelected.connect((roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
|
||||
RoomManager.resolveResource(roomId.length > 0 ? roomId : alias, isJoined ? "" : "join");
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ Kirigami.Page {
|
||||
Keys.onReturnPressed: event => {
|
||||
if (event.modifiers & Qt.ControlModifier) {
|
||||
root.accepted(reason.text);
|
||||
root.Kirigami.PageStack.closeDialog();
|
||||
root.closeDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,14 +52,14 @@ Kirigami.Page {
|
||||
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
|
||||
onClicked: {
|
||||
root.accepted(reason.text);
|
||||
root.Kirigami.PageStack.closeDialog();
|
||||
root.closeDialog();
|
||||
}
|
||||
}
|
||||
QQC2.Button {
|
||||
icon.name: "dialog-cancel-symbolic"
|
||||
text: i18nc("@action", "Cancel")
|
||||
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole
|
||||
onClicked: root.Kirigami.PageStack.closeDialog()
|
||||
onClicked: root.closeDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,78 +59,18 @@ Kirigami.Page {
|
||||
*/
|
||||
property MediaMessageFilterModel mediaMessageFilterModel: RoomManager.mediaMessageFilterModel
|
||||
|
||||
/**
|
||||
* @brief The WidgetModel to use.
|
||||
*
|
||||
* This model has the list of widgets available in the current room.
|
||||
*
|
||||
* @note For loading a room in a different window, override this with a new
|
||||
* WidgetModel.
|
||||
*
|
||||
* @sa WidgetModel
|
||||
*/
|
||||
property WidgetModel widgetModel: RoomManager.widgetModel
|
||||
|
||||
title: root.currentRoom ? root.currentRoom.displayName : ""
|
||||
focus: true
|
||||
padding: 0
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
id: jitsiMeetingAction
|
||||
|
||||
readonly property bool hasExistingMeeting: root.widgetModel.jitsiIndex >= 0
|
||||
readonly property bool canStartNewMeeting: root.currentRoom.canSendState("im.vector.modular.widgets")
|
||||
|
||||
tooltip: {
|
||||
if (hasExistingMeeting) {
|
||||
return i18nc("@action:button", "Join Jitsi meeting…");
|
||||
}
|
||||
|
||||
return canStartNewMeeting ? i18nc("@action:button", "Start Jitsi meeting…") : i18nc("@action:button", "You do not have permissions to start Jitsi meetings")
|
||||
}
|
||||
icon {
|
||||
name: "camera-video-symbolic"
|
||||
color: hasExistingMeeting ? Kirigami.Theme.highlightColor : "transparent"
|
||||
}
|
||||
enabled: hasExistingMeeting || canStartNewMeeting
|
||||
visible: root.currentRoom && !root.currentRoom.isSpace
|
||||
onTriggered: {
|
||||
const dialog = Qt.createComponent("org.kde.neochat", "MeetingDialog").createObject(QQC2.Overlay.overlay, { hasExistingMeeting });
|
||||
dialog.onAccepted.connect(doAction);
|
||||
dialog.open();
|
||||
}
|
||||
|
||||
function doAction(): void {
|
||||
let url;
|
||||
if (!hasExistingMeeting) {
|
||||
url = root.widgetModel.addJitsiConference();
|
||||
} else {
|
||||
let idx = root.widgetModel.index(root.widgetModel.jitsiIndex, 0);
|
||||
url = root.widgetModel.data(idx, WidgetModel.UrlRole);
|
||||
}
|
||||
Qt.openUrlExternally(url);
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
visible: Kirigami.Settings.isMobile || !(root.Kirigami.PageStack.pageStack as Kirigami.PageRow)?.wideMode
|
||||
visible: Kirigami.Settings.isMobile || !(root.Kirigami.PageStack.pageStack as Kirigami.PageRow).wideMode
|
||||
icon.name: "view-right-new"
|
||||
onTriggered: (root.QQC2.ApplicationWindow.window as Main).openRoomDrawer()
|
||||
}
|
||||
]
|
||||
|
||||
Kirigami.Action {
|
||||
enabled: root.currentRoom && !root.currentRoom.isSpace
|
||||
shortcut: "Ctrl+F"
|
||||
onTriggered: {
|
||||
((root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomSearchPage'), {
|
||||
room: root.currentRoom
|
||||
}, {
|
||||
title: i18nc("@action:title", "Search")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.left: (root.Kirigami.PageStack.pageStack as Kirigami.PageRow).get(0)
|
||||
|
||||
onCurrentRoomChanged: {
|
||||
@@ -227,8 +167,6 @@ Kirigami.Page {
|
||||
// Used to keep track of messages so we can hide the right one at the right time
|
||||
property string messageId
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
showCloseButton: true
|
||||
visible: false
|
||||
position: Kirigami.InlineMessage.Position.Header
|
||||
@@ -255,6 +193,7 @@ Kirigami.Page {
|
||||
id: timelineView
|
||||
messageFilterModel: root.messageFilterModel
|
||||
compactLayout: NeoChatConfig.compactLayout
|
||||
fileDropEnabled: !Controller.isFlatpak
|
||||
markReadCondition: NeoChatConfig.markReadCondition
|
||||
}
|
||||
}
|
||||
@@ -287,9 +226,15 @@ Kirigami.Page {
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
Kirigami.Theme.inherit: false
|
||||
color: NeoChatConfig.compactLayout ? Kirigami.Theme.backgroundColor : "transparent"
|
||||
}
|
||||
|
||||
footer: Loader {
|
||||
id: chatBarLoader
|
||||
height: active ? (item as ChatBar)?.implicitHeight : 0
|
||||
height: active ? (item as ChatBar).implicitHeight : 0
|
||||
active: timelineViewLoader.active && !root.currentRoom.readOnly
|
||||
sourceComponent: ChatBar {
|
||||
id: chatBar
|
||||
@@ -349,16 +294,14 @@ Kirigami.Page {
|
||||
});
|
||||
}
|
||||
|
||||
function onShowDelegateMenu(parent: QtObject, eventId: string, author, messageComponentType, plainText: string, richText: string, mimeType: string, progressInfo, selectedText: string, hoveredLink: string) {
|
||||
(delegateContextMenu.createObject(parent, {
|
||||
function onShowDelegateMenu(eventId: string, author, messageComponentType, plainText: string, richText: string, mimeType: string, progressInfo, isThread: bool, selectedText: string, hoveredLink: string) {
|
||||
(delegateContextMenu.createObject(root, {
|
||||
author: author,
|
||||
eventId: eventId,
|
||||
plainText: plainText,
|
||||
mimeType: mimeType,
|
||||
progressInfo: progressInfo,
|
||||
messageComponentType: messageComponentType,
|
||||
selectedText,
|
||||
hoveredLink,
|
||||
}) as DelegateContextMenu).popup();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2026 Joshua Goins <josh@redstrate.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.components as KirigamiComponents
|
||||
import org.kde.kirigamiaddons.delegates as Delegates
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
Kirigami.Dialog {
|
||||
id: root
|
||||
|
||||
property var model
|
||||
|
||||
standardButtons: Kirigami.Dialog.NoButton
|
||||
|
||||
width: Math.min(QQC2.ApplicationWindow.window.width, Kirigami.Units.gridUnit * 24)
|
||||
maximumHeight: Kirigami.Units.gridUnit * 24
|
||||
title: i18nc("@title:menu Seen by/read marker dialog", "Seen By")
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
QQC2.ScrollView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
|
||||
model: root.model
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
onCountChanged: {
|
||||
if (listView.count === 0) {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Delegates.RoundedItemDelegate {
|
||||
id: userDelegate
|
||||
|
||||
required property string displayName
|
||||
required property url avatarUrl
|
||||
required property color memberColor
|
||||
required property string userId
|
||||
|
||||
implicitHeight: Kirigami.Units.gridUnit * 2
|
||||
|
||||
text: displayName
|
||||
highlighted: false
|
||||
|
||||
onClicked: {
|
||||
root.close();
|
||||
RoomManager.resolveResource(userDelegate.userId);
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
KirigamiComponents.Avatar {
|
||||
implicitWidth: height
|
||||
sourceSize {
|
||||
height: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 2.5
|
||||
width: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 2.5
|
||||
}
|
||||
source: userDelegate.avatarUrl
|
||||
name: userDelegate.displayName
|
||||
color: userDelegate.memberColor
|
||||
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
QQC2.Label {
|
||||
text: userDelegate.displayName
|
||||
textFormat: Text.PlainText
|
||||
elide: Text.ElideRight
|
||||
clip: true // Intentional to limit insane Unicode in display names
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,13 @@ import QtQuick
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
import io.github.quotient_im.libquotient
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
FormCard.FormCardPage {
|
||||
id: root
|
||||
|
||||
property bool processing: false
|
||||
|
||||
title: i18nc("@title:window", "Load your encrypted messages")
|
||||
|
||||
topPadding: Kirigami.Units.gridUnit
|
||||
@@ -27,42 +26,75 @@ FormCard.FormCardPage {
|
||||
position: Kirigami.InlineMessage.Position.Header
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Controller.activeConnection
|
||||
function onKeyBackupError(): void {
|
||||
securityKeyField.clear()
|
||||
root.processing = false
|
||||
banner.text = i18nc("@info:status", "The security key or backup passphrase was not correct.")
|
||||
banner.visible = true
|
||||
}
|
||||
property SSSSHandler ssssHandler: SSSSHandler {
|
||||
id: ssssHandler
|
||||
|
||||
function onKeyBackupUnlocked(): void {
|
||||
root.processing = false
|
||||
property bool processing: false
|
||||
|
||||
connection: Controller.activeConnection
|
||||
onKeyBackupUnlocked: {
|
||||
ssssHandler.processing = false
|
||||
banner.text = i18nc("@info:status", "Encryption keys restored.")
|
||||
banner.type = Kirigami.MessageType.Positive
|
||||
banner.visible = true
|
||||
}
|
||||
onError: error => {
|
||||
if (error !== SSSSHandler.WrongKeyError) {
|
||||
banner.text = error
|
||||
banner.visible = true
|
||||
return;
|
||||
}
|
||||
passwordField.clear()
|
||||
ssssHandler.processing = false
|
||||
banner.text = i18nc("@info:status", "The security phrase was not correct.")
|
||||
banner.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title", "Unlock using Security Key or Backup Passphrase")
|
||||
title: i18nc("@title", "Unlock using Passphrase")
|
||||
}
|
||||
FormCard.FormCard {
|
||||
FormCard.FormTextDelegate {
|
||||
description: i18nc("@info", "If you have a security key or backup passphrase for this account, enter it below or upload it as a file.")
|
||||
description: i18nc("@info", "If you have a backup passphrase for this account, enter it below.")
|
||||
}
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: passwordField
|
||||
label: i18nc("@label:textbox", "Backup Password:")
|
||||
echoMode: TextInput.Password
|
||||
}
|
||||
FormCard.FormButtonDelegate {
|
||||
id: unlockButton
|
||||
text: i18nc("@action:button", "Unlock")
|
||||
icon.name: "unlock"
|
||||
enabled: passwordField.text.length > 0 && !ssssHandler.processing
|
||||
onClicked: {
|
||||
ssssHandler.processing = true
|
||||
banner.visible = false
|
||||
ssssHandler.unlockSSSSWithPassphrase(passwordField.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title", "Unlock using Security Key")
|
||||
}
|
||||
FormCard.FormCard {
|
||||
FormCard.FormTextDelegate {
|
||||
description: i18nc("@info", "If you have a security key for this account, enter it below or upload it as a file.")
|
||||
}
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: securityKeyField
|
||||
label: i18nc("@label:textbox", "Security Key or Backup Passphrase:")
|
||||
label: i18nc("@label:textbox", "Security Key:")
|
||||
echoMode: TextInput.Password
|
||||
}
|
||||
FormCard.FormButtonDelegate {
|
||||
id: uploadSecurityKeyButton
|
||||
text: i18nc("@action:button", "Upload from File")
|
||||
icon.name: "cloud-upload"
|
||||
enabled: !root.processing
|
||||
enabled: !ssssHandler.processing
|
||||
onClicked: {
|
||||
root.processing = true
|
||||
ssssHandler.processing = true
|
||||
openFileDialog.open()
|
||||
}
|
||||
}
|
||||
@@ -70,10 +102,10 @@ FormCard.FormCardPage {
|
||||
id: unlockSecurityKeyButton
|
||||
text: i18nc("@action:button", "Unlock")
|
||||
icon.name: "unlock"
|
||||
enabled: securityKeyField.text.length > 0 && !root.processing
|
||||
enabled: securityKeyField.text.length > 0 && !ssssHandler.processing
|
||||
onClicked: {
|
||||
root.processing = true
|
||||
Controller.activeConnection.unlockSSSS(securityKeyField.text)
|
||||
ssssHandler.processing = true
|
||||
ssssHandler.unlockSSSSFromSecurityKey(securityKeyField.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,10 +121,10 @@ FormCard.FormCardPage {
|
||||
id: unlockCrossSigningButton
|
||||
icon.name: "emblem-shared-symbolic"
|
||||
text: i18nc("@action:button", "Request from other Devices")
|
||||
enabled: !root.processing
|
||||
enabled: !ssssHandler.processing
|
||||
onClicked: {
|
||||
root.processing = true
|
||||
Controller.activeConnection.unlockSSSS("")
|
||||
ssssHandler.processing = true
|
||||
ssssHandler.unlockSSSSFromCrossSigning()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,47 +20,29 @@ Kirigami.Dialog {
|
||||
// Make sure that code is prepared to deal with this property being null
|
||||
property NeoChatRoom room
|
||||
property var user
|
||||
// Used for the "View Main Profile" feature so you can toggle back to the room profile.
|
||||
property NeoChatRoom oldRoom
|
||||
|
||||
property NeoChatConnection connection
|
||||
|
||||
property CommonRoomsModel model: CommonRoomsModel {
|
||||
connection: root.connection
|
||||
userId: root.user.id
|
||||
}
|
||||
|
||||
property LimiterModel limiterModel: LimiterModel {
|
||||
maximumCount: 5
|
||||
sourceModel: root.model
|
||||
}
|
||||
|
||||
readonly property bool isSelf: root.user.id === root.connection.localUserId
|
||||
readonly property bool hasMutualRooms: root.model.count > 0
|
||||
readonly property bool isRoomProfile: root.room
|
||||
readonly property string shareUrl: "https://matrix.to/#/" + root.user.id
|
||||
|
||||
leftPadding: Kirigami.Units.largeSpacing * 2
|
||||
rightPadding: Kirigami.Units.largeSpacing * 2
|
||||
topPadding: Kirigami.Units.largeSpacing * 2
|
||||
bottomPadding: Kirigami.Units.largeSpacing * 2
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
standardButtons: Kirigami.Dialog.NoButton
|
||||
|
||||
width: Math.min(QQC2.ApplicationWindow.window.width, Kirigami.Units.gridUnit * 24)
|
||||
title: i18nc("@title:menu Account details dialog", "Account Details")
|
||||
|
||||
header: null
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
RowLayout {
|
||||
id: detailRow
|
||||
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
KirigamiComponents.Avatar {
|
||||
id: avatar
|
||||
@@ -68,14 +50,7 @@ Kirigami.Dialog {
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.huge
|
||||
|
||||
name: root.room ? root.room.member(root.user.id).displayName : root.user.displayName
|
||||
source: {
|
||||
if (root.room) {
|
||||
return root.room.member(root.user.id).avatarUrl;
|
||||
} else if(root.user.avatarUrl.toString() !== '') {
|
||||
return root.connection.makeMediaUrl(root.user.avatarUrl);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
source: root.room ? root.room.member(root.user.id).avatarUrl : root.user.avatarUrl
|
||||
color: root.room ? root.room.member(root.user.id).color : QmlUtils.getUserColor(root.user.hueF)
|
||||
}
|
||||
|
||||
@@ -100,355 +75,223 @@ Kirigami.Dialog {
|
||||
id: idLabel
|
||||
textFormat: TextEdit.PlainText
|
||||
text: idLabelTextMetrics.elidedText
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
|
||||
TextMetrics {
|
||||
id: idLabelTextMetrics
|
||||
text: root.user.id
|
||||
elide: Qt.ElideRight
|
||||
elideWidth: root.availableWidth - avatar.width - detailRow.spacing * 2 - detailRow.Layout.leftMargin - detailRow.Layout.rightMargin
|
||||
elideWidth: root.availableWidth - avatar.width - qrButton.width - detailRow.spacing * 2 - detailRow.Layout.leftMargin - detailRow.Layout.rightMargin
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.ActionToolBar {
|
||||
QQC2.Label {
|
||||
property CommonRoomsModel model: CommonRoomsModel {
|
||||
connection: root.connection
|
||||
userId: root.user.id
|
||||
}
|
||||
|
||||
text: i18ncp("@info", "One mutual room", "%1 mutual rooms", model.count)
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
visible: model.count > 0
|
||||
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:intoolbar Message this user directly", "Message")
|
||||
icon.name: "document-send-symbolic"
|
||||
|
||||
onTriggered: {
|
||||
root.close();
|
||||
root.connection.requestDirectChat(root.user.id);
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
icon.name: "im-invisible-user-symbolic"
|
||||
text: root.connection.isIgnored(root.user.id) ? i18nc("@action:intoolbar Unignore or 'unblock' this user", "Unignore") : i18nc("@action:intoolbar Ignore or 'block' this user", "Ignore")
|
||||
|
||||
onTriggered: {
|
||||
root.close();
|
||||
root.connection.isIgnored(root.user.id) ? root.connection.removeFromIgnoredUsers(root.user.id) : root.connection.addToIgnoredUsers(root.user.id);
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:intoolbar Copy shareable link for this user", "Copy Link")
|
||||
icon.name: "username-copy-symbolic"
|
||||
|
||||
onTriggered: Clipboard.saveText(root.shareUrl)
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:intoolbar Search for this user's messages.", "Search Messages…")
|
||||
icon.name: "search-symbolic"
|
||||
|
||||
onTriggered: {
|
||||
((root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomSearchPage'), {
|
||||
room: root.room,
|
||||
senderId: root.user.id
|
||||
}, {
|
||||
title: i18nc("@action:title", "Search")
|
||||
});
|
||||
root.close();
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:intoolbar", "Show QR Code")
|
||||
icon.name: "view-barcode-qr-symbolic"
|
||||
|
||||
onTriggered: {
|
||||
let qrCode = Qt.createComponent('org.kde.neochat', 'QrCodeMaximizeComponent').createObject(QQC2.Overlay.overlay, {
|
||||
text: root.shareUrl,
|
||||
title: root.room ? root.room.member(root.user.id).displayName : root.user.displayName,
|
||||
subtitle: root.user.id,
|
||||
avatarColor: root.room?.member(root.user.id).color,
|
||||
avatarSource: root.room? root.room.member(root.user.id).avatarUrl : root.user.avatarUrl
|
||||
}) as QrCodeMaximizeComponent;
|
||||
root.close();
|
||||
qrCode.open();
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:button 'Report' as in 'Report this user to the administrators'", "Report…")
|
||||
icon.name: "dialog-warning-symbolic"
|
||||
visible: root.connection.supportsMatrixSpecVersion("v1.13")
|
||||
|
||||
onTriggered: {
|
||||
let dialog = ((root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Report User"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for reporting this user"),
|
||||
icon: "dialog-warning-symbolic",
|
||||
actionText: i18nc("@action:button 'Report' as in 'Report this user to the administrators'", "Report")
|
||||
}, {
|
||||
title: i18nc("@title", "Report User"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
}) as ReasonDialog;
|
||||
dialog.accepted.connect(reason => {
|
||||
root.connection.reportUser(root.user.id, reason);
|
||||
});
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
visible: root.room
|
||||
|
||||
text: i18nc("@action:button", "View Main Profile")
|
||||
icon.name: "user-properties-symbolic"
|
||||
onTriggered: {
|
||||
root.oldRoom = root.room;
|
||||
root.room = null;
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
visible: !root.room && root.oldRoom
|
||||
|
||||
text: i18nc("@action:button", "View Room Profile")
|
||||
icon.name: "user-properties-symbolic"
|
||||
onTriggered: {
|
||||
root.room = root.oldRoom;
|
||||
root.oldRoom = null;
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
QQC2.AbstractButton {
|
||||
id: qrButton
|
||||
Layout.minimumHeight: avatar.height * 0.75
|
||||
Layout.maximumHeight: avatar.height * 1.5
|
||||
Layout.maximumWidth: avatar.height * 1.5
|
||||
|
||||
Kirigami.Heading {
|
||||
text: i18nc("@title Moderation actions for this user", "Moderation")
|
||||
level: 2
|
||||
visible: root.isRoomProfile && moderationToolbar.actions.filter(function (it) { return it.visible; }).length > 0
|
||||
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
}
|
||||
|
||||
Kirigami.ActionToolBar {
|
||||
id: moderationToolbar
|
||||
|
||||
flat: false
|
||||
visible: root.isRoomProfile
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
visible: {
|
||||
if (root.room) {
|
||||
return !root.isSelf && root.room.canSendState("kick") && root.room.containsUser(root.user.id) && root.room.memberEffectivePowerLevel(root.user.id) < root.room.memberEffectivePowerLevel(root.connection.localUserId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
text: i18nc("@action:button Kick the user from the room", "Kick…")
|
||||
icon.name: "im-kick-user"
|
||||
onTriggered: {
|
||||
let dialog = (root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Kick User"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for kicking this user"),
|
||||
actionText: i18nc("@action:button 'Kick' as in 'Kick this user from the room'", "Kick"),
|
||||
icon: "im-kick-user"
|
||||
}, {
|
||||
title: i18nc("@title:dialog", "Kick User"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
root.room.kickMember(root.user.id, reason);
|
||||
});
|
||||
root.close();
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
visible: {
|
||||
if (root.room) {
|
||||
return !root.isSelf && root.room.canSendState("ban") && !root.room.isUserBanned(root.user.id) && root.room.memberEffectivePowerLevel(root.user.id) < root.room.memberEffectivePowerLevel(root.connection.localUserId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
text: i18nc("@action:button Ban this user from the room", "Ban…")
|
||||
icon.name: "im-ban-user"
|
||||
icon.color: Kirigami.Theme.negativeTextColor
|
||||
onTriggered: {
|
||||
let dialog = (root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Ban User"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for banning this user"),
|
||||
actionText: i18nc("@action:button 'Ban' as in 'Ban this user'", "Ban"),
|
||||
icon: "im-ban-user"
|
||||
}, {
|
||||
title: i18nc("@title:dialog", "Ban User"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
root.room.ban(root.user.id, reason);
|
||||
});
|
||||
root.close();
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
visible: {
|
||||
if (root.room) {
|
||||
return !root.isSelf && root.room.canSendState("ban") && root.room.isUserBanned(root.user.id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
text: i18nc("@action:button Unban the user from this room", "Unban")
|
||||
icon.name: "im-irc"
|
||||
icon.color: Kirigami.Theme.negativeTextColor
|
||||
onTriggered: {
|
||||
root.room.unban(root.user.id);
|
||||
root.close();
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
visible: (root.user.id === root.connection.localUserId || (root.room?.canSendState("redact") ?? false))
|
||||
|
||||
text: i18nc("@action:button Remove messages from the user in this room", "Remove Messages…")
|
||||
icon.name: "delete"
|
||||
icon.color: Kirigami.Theme.negativeTextColor
|
||||
onTriggered: {
|
||||
let dialog = ((root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Remove Messages"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for removing this user's recent messages"),
|
||||
actionText: i18nc("@action:button 'Remove' as in 'Remove these messages'", "Remove"),
|
||||
icon: "delete"
|
||||
}, {
|
||||
title: i18nc("@title", "Remove Messages"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
root.room.deleteMessagesByUser(root.user.id, reason);
|
||||
});
|
||||
root.close();
|
||||
}
|
||||
contentItem: Barcode {
|
||||
id: barcode
|
||||
barcodeType: Barcode.QRCode
|
||||
content: "https://matrix.to/#/" + root.user.id
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Kirigami.Heading {
|
||||
text: i18nc("@title Role such as 'Admin' or 'Moderator' for this user", "Power Level")
|
||||
level: 2
|
||||
visible: root.isRoomProfile
|
||||
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
visible: root.isRoomProfile
|
||||
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
|
||||
QQC2.Label {
|
||||
text: root.room ? QmlUtils.nameForPowerLevelValue(root.room.memberEffectivePowerLevel(root.user.id)) : ""
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
visible: {
|
||||
if (root.room) {
|
||||
return root.room.canSendState("m.room.power_levels") && !(root.room.roomCreatorHasUltimatePowerLevel() && root.room.isCreator(root.user.id));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
text: i18nc("@action:button Set the power level (such as 'Admin') for this user", "Set Power Level")
|
||||
icon.name: "document-edit-symbolic"
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
|
||||
onClicked: {
|
||||
(powerLevelDialog.createObject(this, {
|
||||
room: root.room,
|
||||
userId: root.user.id,
|
||||
powerLevel: root.room.memberEffectivePowerLevel(root.user.id)
|
||||
}) as PowerLevelDialog).open();
|
||||
let qrCode = Qt.createComponent('org.kde.neochat', 'QrCodeMaximizeComponent').createObject(QQC2.Overlay.overlay, {
|
||||
text: barcode.content,
|
||||
title: root.room ? root.room.member(root.user.id).displayName : root.user.displayName,
|
||||
subtitle: root.user.id,
|
||||
avatarColor: root.room?.member(root.user.id).color,
|
||||
avatarSource: root.room? root.room.member(root.user.id).avatarUrl : root.user.avatarUrl
|
||||
}) as QrCodeMaximizeComponent;
|
||||
root.close();
|
||||
qrCode.open();
|
||||
}
|
||||
|
||||
Component {
|
||||
id: powerLevelDialog
|
||||
PowerLevelDialog {
|
||||
id: powerLevelDialog
|
||||
}
|
||||
}
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.text: barcode.content
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.Heading {
|
||||
text: i18nc("@title The set of common rooms between your current user and the one shown", "Mutual Rooms")
|
||||
level: 4
|
||||
visible: !root.isSelf && root.hasMutualRooms
|
||||
Kirigami.Chip {
|
||||
visible: root.room
|
||||
text: root.room ? QmlUtils.nameForPowerLevelValue(root.room.memberEffectivePowerLevel(root.user.id)) : ""
|
||||
closable: false
|
||||
checkable: false
|
||||
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
visible: !root.isSelf && root.hasMutualRooms
|
||||
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
|
||||
Repeater {
|
||||
model: root.limiterModel
|
||||
|
||||
delegate: KirigamiComponents.AvatarButton {
|
||||
required property string roomName
|
||||
required property string roomAvatar
|
||||
required property string roomId
|
||||
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.medium
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.medium
|
||||
|
||||
name: roomName
|
||||
source: roomAvatar
|
||||
|
||||
onClicked: {
|
||||
root.close();
|
||||
RoomManager.resolveResource(roomId);
|
||||
}
|
||||
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.text: name
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
text: i18ncp("@info:label And '%1' more rooms you have in common with this user, but are not shown", "and 1 more…", "and %1 more…", root.limiterModel.extraCount)
|
||||
visible: root.limiterModel.extraCount > 0
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.Heading {
|
||||
text: i18nc("@title Private note for this user", "Private Note")
|
||||
level: 4
|
||||
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
}
|
||||
|
||||
QQC2.TextArea {
|
||||
id: noteText
|
||||
|
||||
text: root.connection.noteForUser(root.user.id)
|
||||
textFormat: TextEdit.PlainText
|
||||
wrapMode: TextEdit.Wrap
|
||||
placeholderText: i18nc("@info:placeholder", "Only visible to you")
|
||||
|
||||
onTextEdited: editTimer.restart()
|
||||
|
||||
Kirigami.Separator {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
}
|
||||
|
||||
// Prevent unnecessary edits by waiting 1 second
|
||||
Timer {
|
||||
id: editTimer
|
||||
|
||||
interval: 1000
|
||||
onTriggered: root.connection.setNoteForUser(root.user.id, noteText.text)
|
||||
FormCard.FormButtonDelegate {
|
||||
visible: root.user.id !== root.connection.localUserId && !!root.user
|
||||
text: !!root.user && root.connection.isIgnored(root.user.id) ? i18n("Unignore this user") : i18n("Ignore this user")
|
||||
icon.name: "im-invisible-user"
|
||||
onClicked: {
|
||||
root.close();
|
||||
root.connection.isIgnored(root.user.id) ? root.connection.removeFromIgnoredUsers(root.user.id) : root.connection.addToIgnoredUsers(root.user.id);
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
visible: root.room && root.user.id !== root.connection.localUserId && root.room.canSendState("kick") && root.room.containsUser(root.user.id) && root.room.memberEffectivePowerLevel(root.user.id) < root.room.memberEffectivePowerLevel(root.connection.localUserId)
|
||||
|
||||
text: i18nc("@action:button", "Kick this user")
|
||||
icon.name: "im-kick-user"
|
||||
onClicked: {
|
||||
let dialog = (root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Kick User"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for kicking this user"),
|
||||
actionText: i18nc("@action:button 'Kick' as in 'Kick this user from the room'", "Kick"),
|
||||
icon: "im-kick-user"
|
||||
}, {
|
||||
title: i18nc("@title:dialog", "Kick User"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
root.room.kickMember(root.user.id, reason);
|
||||
});
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
visible: root.room && root.user.id !== root.connection.localUserId && root.room.canSendState("invite") && !root.room.containsUser(root.user.id)
|
||||
|
||||
enabled: root.room && !root.room.isUserBanned(root.user.id)
|
||||
text: i18nc("@action:button", "Invite this user")
|
||||
icon.name: "list-add-user"
|
||||
onClicked: {
|
||||
root.room.inviteToRoom(root.user.id);
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
visible: root.room && root.user.id !== root.connection.localUserId && root.room.canSendState("ban") && !root.room.isUserBanned(root.user.id) && root.room.memberEffectivePowerLevel(root.user.id) < root.room.memberEffectivePowerLevel(root.connection.localUserId)
|
||||
|
||||
text: i18nc("@action:button", "Ban this user")
|
||||
icon.name: "im-ban-user"
|
||||
icon.color: Kirigami.Theme.negativeTextColor
|
||||
onClicked: {
|
||||
let dialog = (root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Ban User"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for banning this user"),
|
||||
actionText: i18nc("@action:button 'Ban' as in 'Ban this user'", "Ban"),
|
||||
icon: "im-ban-user"
|
||||
}, {
|
||||
title: i18nc("@title:dialog", "Ban User"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
root.room.ban(root.user.id, reason);
|
||||
});
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
visible: root.room && root.user.id !== root.connection.localUserId && root.room.canSendState("ban") && root.room.isUserBanned(root.user.id)
|
||||
|
||||
text: i18nc("@action:button", "Unban this user")
|
||||
icon.name: "im-irc"
|
||||
icon.color: Kirigami.Theme.negativeTextColor
|
||||
onClicked: {
|
||||
root.room.unban(root.user.id);
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
visible: root.room && root.room.canSendState("m.room.power_levels")
|
||||
text: i18nc("@action:button", "Set user power level")
|
||||
icon.name: "visibility"
|
||||
onClicked: {
|
||||
(powerLevelDialog.createObject(this, {
|
||||
room: root.room,
|
||||
userId: root.user.id,
|
||||
powerLevel: root.room.memberEffectivePowerLevel(root.user.id)
|
||||
}) as PowerLevelDialog).open();
|
||||
root.close();
|
||||
}
|
||||
|
||||
Component {
|
||||
id: powerLevelDialog
|
||||
PowerLevelDialog {
|
||||
id: powerLevelDialog
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
visible: root.room && (root.user.id === root.connection.localUserId || root.room.canSendState("redact"))
|
||||
|
||||
text: i18nc("@action:button", "Remove recent messages by this user")
|
||||
icon.name: "delete"
|
||||
icon.color: Kirigami.Theme.negativeTextColor
|
||||
onClicked: {
|
||||
let dialog = ((QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Remove Messages"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for removing this user's recent messages"),
|
||||
actionText: i18nc("@action:button 'Remove' as in 'Remove these messages'", "Remove"),
|
||||
icon: "delete"
|
||||
}, {
|
||||
title: i18nc("@title", "Remove Messages"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
root.room.deleteMessagesByUser(root.user.id, reason);
|
||||
});
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
visible: root.user.id !== root.connection.localUserId
|
||||
text: root.connection.directChatExists(root.user) ? i18nc("%1 is the name of the user.", "Chat with %1", root.room ? root.room.member(root.user.id).htmlSafeDisplayName : QmlUtils.escapeString(root.user.displayName)) : i18n("Invite to private chat")
|
||||
icon.name: "document-send"
|
||||
onClicked: {
|
||||
root.connection.requestDirectChat(root.user.id);
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button %1 is the name of the user.", "Search room for %1's messages", root.room ? root.room.member(root.user.id).htmlSafeDisplayName : QmlUtils.escapeString(root.user.displayName))
|
||||
icon.name: "search-symbolic"
|
||||
onClicked: {
|
||||
((QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomSearchPage'), {
|
||||
room: root.room,
|
||||
senderId: root.user.id
|
||||
}, {
|
||||
title: i18nc("@action:title", "Search")
|
||||
});
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18n("Copy link")
|
||||
icon.name: "username-copy"
|
||||
onClicked: Clipboard.saveText("https://matrix.to/#/" + root.user.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ SearchPage {
|
||||
*/
|
||||
required property NeoChatConnection connection
|
||||
|
||||
title: i18nc("@action:title", "Find User")
|
||||
title: i18nc("@action:title", "Find Your Friends")
|
||||
|
||||
Component.onCompleted: focusSearch()
|
||||
|
||||
@@ -81,7 +81,7 @@ SearchPage {
|
||||
}
|
||||
QQC2.Label {
|
||||
visible: userDelegate.directChatExists
|
||||
text: i18nc("@info", "Direct Messages")
|
||||
text: i18nc("@info", "Friends")
|
||||
textFormat: Text.PlainText
|
||||
color: Kirigami.Theme.positiveTextColor
|
||||
}
|
||||
|
||||
@@ -5,25 +5,14 @@ import QtQuick
|
||||
import QtQml
|
||||
|
||||
import org.kde.neochat
|
||||
import io.github.quotient_im.libquotient
|
||||
|
||||
VerificationMessage {
|
||||
id: root
|
||||
|
||||
required property int reason
|
||||
|
||||
icon: {
|
||||
switch (root.reason) {
|
||||
case KeyVerificationSession.TIMEOUT:
|
||||
case KeyVerificationSession.REMOTE_TIMEOUT:
|
||||
case KeyVerificationSession.USER:
|
||||
case KeyVerificationSession.REMOTE_USER:
|
||||
case KeyVerificationSession.SESSION_ACCEPTED:
|
||||
case KeyVerificationSession.REMOTE_SESSION_ACCEPTED:
|
||||
return "dialog-information";
|
||||
default:
|
||||
return "security-low";
|
||||
}
|
||||
}
|
||||
icon: "security-low"
|
||||
text: {
|
||||
switch (root.reason) {
|
||||
case KeyVerificationSession.NONE:
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "controller.h"
|
||||
#include "eventhandler.h"
|
||||
#include "models/actionsmodel.h"
|
||||
#include "models/messagefiltermodel.h"
|
||||
#include "models/sortfilterroomtreemodel.h"
|
||||
#include "neochatconfig.h"
|
||||
#include "neochatconnection.h"
|
||||
#include "neochatroom.h"
|
||||
@@ -41,7 +43,6 @@ RoomManager::RoomManager(QObject *parent)
|
||||
, m_messageFilterModel(new MessageFilterModel(this, m_timelineModel))
|
||||
, m_mediaMessageFilterModel(new MediaMessageFilterModel(this, m_messageFilterModel))
|
||||
, m_userListModel(new UserListModel(this))
|
||||
, m_widgetModel(new WidgetModel(this))
|
||||
{
|
||||
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(UBUNTU_TOUCH)
|
||||
m_isMobile = true;
|
||||
@@ -54,7 +55,6 @@ RoomManager::RoomManager(QObject *parent)
|
||||
#endif
|
||||
|
||||
connect(this, &RoomManager::currentRoomChanged, this, [this]() {
|
||||
m_widgetModel->setRoom(m_currentRoom);
|
||||
m_userListModel->setRoom(m_currentRoom);
|
||||
m_timelineModel->setRoom(m_currentRoom);
|
||||
m_sortFilterRoomTreeModel->setCurrentRoom(m_currentRoom);
|
||||
@@ -197,11 +197,6 @@ void RoomManager::activateUserModel()
|
||||
m_userListModel->activate();
|
||||
}
|
||||
|
||||
WidgetModel *RoomManager::widgetModel() const
|
||||
{
|
||||
return m_widgetModel;
|
||||
}
|
||||
|
||||
void RoomManager::resolveResource(const QString &idOrUri, const QString &action)
|
||||
{
|
||||
resolveResource(Uri{idOrUri}, action);
|
||||
@@ -282,21 +277,26 @@ void RoomManager::viewEventSource(const QString &eventId)
|
||||
Q_EMIT showEventSource(eventId);
|
||||
}
|
||||
|
||||
void RoomManager::viewEventMenu(QObject *parent, const RoomEvent *event, NeoChatRoom *room, const QString &selectedText, const QString &hoveredLink)
|
||||
void RoomManager::viewEventMenu(const QString &eventId, NeoChatRoom *room, const QString &selectedText, const QString &hoveredLink)
|
||||
{
|
||||
if (!event) {
|
||||
qWarning() << "Tried to open event menu with empty event";
|
||||
if (eventId.isEmpty()) {
|
||||
qWarning() << "Tried to open event menu with empty event id";
|
||||
return;
|
||||
}
|
||||
|
||||
Q_EMIT showDelegateMenu(parent,
|
||||
event->id(),
|
||||
room->qmlSafeMember(event->senderId()),
|
||||
MessageComponentType::typeForEvent(*event),
|
||||
EventHandler::plainBody(room, event),
|
||||
EventHandler::richBody(room, event),
|
||||
EventHandler::mediaInfo(room, event)["mimeType"_L1].toString(),
|
||||
room->fileTransferInfo(event->id()),
|
||||
const auto it = room->findInTimeline(eventId);
|
||||
if (it == room->historyEdge()) {
|
||||
// This is probably a pending event
|
||||
return;
|
||||
}
|
||||
const auto &event = **it;
|
||||
Q_EMIT showDelegateMenu(eventId,
|
||||
room->qmlSafeMember(event.senderId()),
|
||||
MessageComponentType::typeForEvent(event),
|
||||
EventHandler::plainBody(room, &event),
|
||||
EventHandler::richBody(room, &event),
|
||||
EventHandler::mediaInfo(room, &event)["mimeType"_L1].toString(),
|
||||
room->fileTransferInfo(eventId),
|
||||
selectedText,
|
||||
hoveredLink);
|
||||
}
|
||||
@@ -514,14 +514,7 @@ void RoomManager::setCurrentSpace(const QString &spaceId, bool setRoom)
|
||||
|
||||
// This need to happen before the signal so TreeView.expandRecursively() can work nicely.
|
||||
m_sortFilterRoomTreeModel->setActiveSpaceId(m_currentSpaceId);
|
||||
|
||||
if (m_currentSpaceId == u"DM") {
|
||||
m_sortFilterRoomTreeModel->setMode(SortFilterRoomTreeModel::DirectChats);
|
||||
} else if (m_currentSpaceId.isEmpty()) {
|
||||
m_sortFilterRoomTreeModel->setMode(SortFilterRoomTreeModel::Rooms);
|
||||
} else {
|
||||
m_sortFilterRoomTreeModel->setMode(SortFilterRoomTreeModel::All);
|
||||
}
|
||||
m_sortFilterRoomTreeModel->setMode(m_currentSpaceId == u"DM"_s ? SortFilterRoomTreeModel::DirectChats : SortFilterRoomTreeModel::Rooms);
|
||||
|
||||
Q_EMIT currentSpaceChanged();
|
||||
if (m_connection) {
|
||||
@@ -549,45 +542,6 @@ void RoomManager::setCurrentSpace(const QString &spaceId, bool setRoom)
|
||||
setCurrentRoom({});
|
||||
}
|
||||
|
||||
QString RoomManager::findSpaceIdForCurrentRoom() const
|
||||
{
|
||||
if (!m_currentRoom) {
|
||||
return m_currentSpaceId;
|
||||
}
|
||||
if (m_currentRoom->isDirectChat()) {
|
||||
const auto roomsInSpace = SpaceHierarchyCache::instance().getRoomListForSpace(m_currentSpaceId, false);
|
||||
if (roomsInSpace.contains(m_currentRoom->id())) {
|
||||
return m_currentSpaceId;
|
||||
}
|
||||
return "DM"_L1;
|
||||
}
|
||||
const auto &parentSpaces = SpaceHierarchyCache::instance().parentSpaces(m_currentRoom->id());
|
||||
if (parentSpaces.contains(m_currentSpaceId)) {
|
||||
return m_currentSpaceId;
|
||||
}
|
||||
static auto config = NeoChatConfig::self();
|
||||
if (config->allRoomsInHome()) {
|
||||
return {};
|
||||
}
|
||||
if (const auto &parent = m_connection->room(m_currentRoom->canonicalParent())) {
|
||||
for (const auto &parentParent : SpaceHierarchyCache::instance().parentSpaces(parent->id())) {
|
||||
if (SpaceHierarchyCache::instance().parentSpaces(parentParent).isEmpty()) {
|
||||
return parentParent;
|
||||
}
|
||||
}
|
||||
return parent->id();
|
||||
}
|
||||
for (const auto &space : parentSpaces) {
|
||||
if (SpaceHierarchyCache::instance().parentSpaces(space).isEmpty()) {
|
||||
return space;
|
||||
}
|
||||
}
|
||||
if (m_currentRoom->isSpace()) {
|
||||
return m_currentSpaceId;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void RoomManager::setCurrentRoom(const QString &roomId)
|
||||
{
|
||||
if (m_currentRoom != nullptr) {
|
||||
@@ -605,23 +559,56 @@ void RoomManager::setCurrentRoom(const QString &roomId)
|
||||
}
|
||||
|
||||
Q_EMIT currentRoomChanged();
|
||||
|
||||
if (m_connection) {
|
||||
if (roomId.isEmpty()) {
|
||||
m_lastRoomConfig.deleteEntry(m_currentSpaceId);
|
||||
} else {
|
||||
// We can't have empty keys in KConfig, so name it "Home"
|
||||
if (m_currentSpaceId.isEmpty()) {
|
||||
m_lastRoomConfig.writeEntry(u"Home"_s, roomId);
|
||||
} else {
|
||||
m_lastRoomConfig.writeEntry(m_currentSpaceId, roomId);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (roomId.isEmpty()) {
|
||||
m_lastRoomConfig.deleteEntry(m_currentSpaceId);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto spaceIdForRoom = findSpaceIdForCurrentRoom();
|
||||
// We can't have empty keys in KConfig, so name it "Home"
|
||||
if (spaceIdForRoom.isEmpty()) {
|
||||
m_lastRoomConfig.writeEntry(u"Home"_s, roomId);
|
||||
} else {
|
||||
m_lastRoomConfig.writeEntry(spaceIdForRoom, roomId);
|
||||
if (m_currentRoom->isSpace()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_currentSpaceId != spaceIdForRoom) {
|
||||
setCurrentSpace(spaceIdForRoom, false);
|
||||
if (m_currentRoom->isDirectChat()) {
|
||||
if (m_currentSpaceId != "DM"_L1) {
|
||||
setCurrentSpace("DM"_L1, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const auto &parentSpaces = SpaceHierarchyCache::instance().parentSpaces(roomId);
|
||||
if (parentSpaces.contains(m_currentSpaceId)) {
|
||||
return;
|
||||
}
|
||||
static auto config = NeoChatConfig::self();
|
||||
if (config->allRoomsInHome()) {
|
||||
setCurrentSpace({}, false);
|
||||
return;
|
||||
}
|
||||
if (const auto &parent = m_connection->room(m_currentRoom->canonicalParent())) {
|
||||
for (const auto &parentParent : SpaceHierarchyCache::instance().parentSpaces(parent->id())) {
|
||||
if (SpaceHierarchyCache::instance().parentSpaces(parentParent).isEmpty()) {
|
||||
setCurrentSpace(parentParent, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
setCurrentSpace(parent->id(), false);
|
||||
return;
|
||||
}
|
||||
for (const auto &space : parentSpaces) {
|
||||
if (SpaceHierarchyCache::instance().parentSpaces(space).isEmpty()) {
|
||||
setCurrentSpace(space, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
setCurrentSpace({}, false);
|
||||
}
|
||||
|
||||
void RoomManager::clearCurrentRoom()
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "models/sortfilterspacelistmodel.h"
|
||||
#include "models/timelinemodel.h"
|
||||
#include "models/userlistmodel.h"
|
||||
#include "models/widgetmodel.h"
|
||||
#include "neochatroommember.h"
|
||||
|
||||
class NeoChatRoom;
|
||||
@@ -130,14 +129,6 @@ class RoomManager : public QObject, public UriResolverBase
|
||||
*/
|
||||
Q_PROPERTY(UserListModel *userListModel READ userListModel CONSTANT)
|
||||
|
||||
/**
|
||||
* @brief The WidgetModel that should be used for room widget visualisation.
|
||||
*
|
||||
* @note Available here so that the room page and drawer both have access to the
|
||||
* same model.
|
||||
*/
|
||||
Q_PROPERTY(WidgetModel *widgetModel READ widgetModel CONSTANT)
|
||||
|
||||
/**
|
||||
* @brief Whether a room is currently open in NeoChat.
|
||||
*
|
||||
@@ -169,8 +160,6 @@ public:
|
||||
UserListModel *userListModel() const;
|
||||
Q_INVOKABLE void activateUserModel();
|
||||
|
||||
WidgetModel *widgetModel() const;
|
||||
|
||||
/**
|
||||
* @brief Resolve the given resource.
|
||||
*
|
||||
@@ -233,8 +222,7 @@ public:
|
||||
/**
|
||||
* @brief Show a context menu for the given event.
|
||||
*/
|
||||
Q_INVOKABLE void
|
||||
viewEventMenu(QObject *parent, const RoomEvent *event, NeoChatRoom *room, const QString &selectedText = {}, const QString &hoveredLink = {});
|
||||
Q_INVOKABLE void viewEventMenu(const QString &eventId, NeoChatRoom *room, const QString &selectedText = {}, const QString &hoveredLink = {});
|
||||
|
||||
/**
|
||||
* @brief Set a URL to be loaded as the initial room.
|
||||
@@ -307,8 +295,7 @@ Q_SIGNALS:
|
||||
/**
|
||||
* @brief Request to show a menu for the given event.
|
||||
*/
|
||||
void showDelegateMenu(QObject *parent,
|
||||
const QString &eventId,
|
||||
void showDelegateMenu(const QString &eventId,
|
||||
const NeochatRoomMember *author,
|
||||
MessageComponentType::Type messageComponentType,
|
||||
const QString &plainText,
|
||||
@@ -369,21 +356,11 @@ private:
|
||||
MediaMessageFilterModel *m_mediaMessageFilterModel;
|
||||
|
||||
UserListModel *m_userListModel;
|
||||
WidgetModel *m_widgetModel;
|
||||
|
||||
QPointer<NeoChatConnection> m_connection;
|
||||
|
||||
void setCurrentRoom(const QString &roomId);
|
||||
|
||||
/**
|
||||
* @brief Find the most appropriate space for the currently selected room
|
||||
*
|
||||
* Should be used to figure out what space to switch to after a room change.
|
||||
*
|
||||
* @return The Space ID that the currently set room should be displayed as part of. (or "DM" for DM and "" for Home)
|
||||
*/
|
||||
QString findSpaceIdForCurrentRoom() const;
|
||||
|
||||
// Space ID, "DM", or empty string
|
||||
void setCurrentSpace(const QString &spaceId, bool setRoom = true);
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <KWindowSystem>
|
||||
|
||||
#include "controller.h"
|
||||
#include "models/roomlistmodel.h"
|
||||
#include "models/sortfilterroomlistmodel.h"
|
||||
#include "roommanager.h"
|
||||
#include "windowcontroller.h"
|
||||
|
||||
|
||||
@@ -263,7 +263,6 @@ QQC2.Control {
|
||||
wrapMode: TextEdit.Wrap
|
||||
// This has to stay PlainText or else formatting starts breaking in strange ways
|
||||
textFormat: TextEdit.PlainText
|
||||
font.pointSize: Kirigami.Theme.defaultFont.pointSize * NeoChatConfig.fontScale
|
||||
|
||||
Accessible.description: placeholderText
|
||||
|
||||
@@ -286,8 +285,6 @@ QQC2.Control {
|
||||
quickFormatBar.selectionStart = selectionStart;
|
||||
quickFormatBar.selectionEnd = selectionEnd;
|
||||
quickFormatBar.open();
|
||||
} else if (quickFormatBar.visible) {
|
||||
quickFormatBar.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,9 +375,7 @@ QQC2.Control {
|
||||
id: actionDelegate
|
||||
required property BusyAction modelData
|
||||
icon.name: modelData.isBusy ? "" : (modelData.icon.name.length > 0 ? modelData.icon.name : modelData.icon.source)
|
||||
onClicked: if (!pieProgress.visible) {
|
||||
modelData.trigger()
|
||||
}
|
||||
onClicked: modelData.trigger()
|
||||
|
||||
padding: Kirigami.Units.smallSpacing
|
||||
|
||||
@@ -388,9 +383,7 @@ QQC2.Control {
|
||||
QQC2.ToolTip.text: modelData.tooltip
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
|
||||
PieProgressBar {
|
||||
id: pieProgress
|
||||
anchors.fill: parent
|
||||
contentItem: PieProgressBar {
|
||||
visible: actionDelegate.modelData.isBusy
|
||||
progress: root.currentRoom.fileUploadingProgress
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.neochat
|
||||
|
||||
QQC2.ItemDelegate {
|
||||
id: root
|
||||
@@ -30,7 +29,6 @@ QQC2.ItemDelegate {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.family: "emoji"
|
||||
font.pointSize: Kirigami.Theme.defaultFont.pointSize * NeoChatConfig.fontScale
|
||||
|
||||
Kirigami.Icon {
|
||||
width: Kirigami.Units.gridUnit * 0.5
|
||||
|
||||
@@ -65,7 +65,7 @@ QQC2.Popup {
|
||||
padding: 2
|
||||
|
||||
implicitHeight: Kirigami.Units.gridUnit * 20 + 2 * padding
|
||||
width: Math.min(contentItem.categoryIconSize * 11 + 2 * padding, QQC2.ApplicationWindow.window?.width)
|
||||
width: Math.min(contentItem.categoryIconSize * 11 + 2 * padding, QQC2.ApplicationWindow.window.width)
|
||||
contentItem: EmojiPicker {
|
||||
id: emojiPicker
|
||||
height: 400
|
||||
|
||||
@@ -148,7 +148,7 @@ ColumnLayout {
|
||||
id: quickReactions
|
||||
Layout.fillWidth: true
|
||||
|
||||
model: ["👍", "👎", "😄", "🎉", "😕", "❤️", "🚀", "👀"]
|
||||
model: ["👍", "👎", "😄", "🎉", "😕", "❤", "🚀", "👀"]
|
||||
|
||||
delegate: EmojiDelegate {
|
||||
required property string modelData
|
||||
|
||||
@@ -17,7 +17,6 @@ Kirigami.ScrollablePage {
|
||||
|
||||
property NeoChatRoom room
|
||||
required property NeoChatConnection connection
|
||||
property alias currentTabIndex: tabBar.currentIndex
|
||||
|
||||
title: i18nc("@title", "Developer Tools")
|
||||
|
||||
|
||||
@@ -21,6 +21,12 @@ FormCard.FormCard {
|
||||
|
||||
onToggled: NeoChatConfig.threads = checked
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
text: i18nc("@option:check Enable the matrix 'secret backup' feature", "Secret Backup")
|
||||
checked: NeoChatConfig.secretBackup
|
||||
|
||||
onToggled: NeoChatConfig.secretBackup = checked
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
text: i18nc("@option:check Enable the matrix feature to add a phone number as a third party ID", "Add phone numbers as 3PIDs")
|
||||
checked: NeoChatConfig.phone3PId
|
||||
|
||||
@@ -33,8 +33,6 @@ target_sources(LibNeoChat PRIVATE
|
||||
events/imagepackevent.cpp
|
||||
events/pollevent.cpp
|
||||
jobs/neochatgetcommonroomsjob.cpp
|
||||
jobs/neochatreportroomjob.cpp
|
||||
jobs/neochatreportuserjob.cpp
|
||||
models/actionsmodel.cpp
|
||||
models/completionmodel.cpp
|
||||
models/completionproxymodel.cpp
|
||||
@@ -47,8 +45,6 @@ target_sources(LibNeoChat PRIVATE
|
||||
models/stickermodel.cpp
|
||||
models/userfiltermodel.cpp
|
||||
models/userlistmodel.cpp
|
||||
models/widgetmodel.cpp
|
||||
models/widgetmodel.h
|
||||
)
|
||||
|
||||
if (TARGET KF6::KIOWidgets)
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
|
||||
#include "chatbarcache.h"
|
||||
|
||||
#include <QMimeData>
|
||||
|
||||
#include <KUrlMimeData>
|
||||
|
||||
#include <Quotient/roommember.h>
|
||||
|
||||
#include "eventhandler.h"
|
||||
@@ -299,17 +295,4 @@ void ChatBarCache::clearCache()
|
||||
clearRelations();
|
||||
}
|
||||
|
||||
void ChatBarCache::drop(QList<QUrl> u, const QString &transferPortal)
|
||||
{
|
||||
QMimeData mimeData;
|
||||
mimeData.setUrls(u);
|
||||
if (!transferPortal.isEmpty()) {
|
||||
mimeData.setData(u"application/vnd.portal.filetransfer"_s, transferPortal.toLatin1());
|
||||
}
|
||||
auto urls = KUrlMimeData::urlsFromMimeData(&mimeData);
|
||||
if (urls.size() > 0) {
|
||||
setAttachmentPath(urls[0].toString());
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_chatbarcache.cpp"
|
||||
|
||||
@@ -198,8 +198,6 @@ public:
|
||||
*/
|
||||
Q_INVOKABLE void postMessage();
|
||||
|
||||
Q_INVOKABLE void drop(QList<QUrl> urls, const QString &transferPortal);
|
||||
|
||||
Q_SIGNALS:
|
||||
void textChanged();
|
||||
void relationIdChanged(const QString &oldEventId, const QString &newEventId);
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
ServerNotice, /**< Official messages from the server. */
|
||||
Deprioritized, /**< The room is set as low priority. */
|
||||
Space, /**< The room is a space. */
|
||||
AddDirect, /**< So we can show the add direct message delegate. */
|
||||
AddDirect, /**< So we can show the add friend delegate. */
|
||||
TypesCount, /**< Number of different types (this should always be last). */
|
||||
};
|
||||
Q_ENUM(Types);
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
case NeoChatRoomType::Favorite:
|
||||
return i18n("Favorite");
|
||||
case NeoChatRoomType::Direct:
|
||||
return i18n("Direct Messages");
|
||||
return i18n("Friends");
|
||||
case NeoChatRoomType::Normal:
|
||||
return i18n("Normal");
|
||||
case NeoChatRoomType::Deprioritized:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user