Compare commits

..

1 Commits

Author SHA1 Message Date
Torrie Fischer
be7617d366 wip: accessability :D 2023-07-15 17:28:25 +02:00
155 changed files with 22037 additions and 19243 deletions

View File

@@ -9,7 +9,7 @@ cmake_minimum_required(VERSION 3.16)
# KDE Applications version, managed by release script. # KDE Applications version, managed by release script.
set(RELEASE_SERVICE_VERSION_MAJOR "23") set(RELEASE_SERVICE_VERSION_MAJOR "23")
set(RELEASE_SERVICE_VERSION_MINOR "07") set(RELEASE_SERVICE_VERSION_MINOR "07")
set(RELEASE_SERVICE_VERSION_MICRO "80") set(RELEASE_SERVICE_VERSION_MICRO "70")
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}") set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION}) project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})
@@ -53,24 +53,13 @@ if(QT_MAJOR_VERSION STREQUAL "6")
set(OVERLAYSHEET_OPEN "onOpened") set(OVERLAYSHEET_OPEN "onOpened")
set(QTQUICK_MODULE_QML_VERSION "") set(QTQUICK_MODULE_QML_VERSION "")
set(QTLOCATION_MODULE_QML_VERSION "") set(QTLOCATION_MODULE_QML_VERSION "")
set(QTMULTIMEDIA_MODULE_QML_VERSION "")
set(QTMULTIMEDIA_AUDIO "MediaPlayer")
# in Audio qt6 we don't have it but we disable it in qt5 => it seems ok
set(QTMULTIMEDIA_AUDIO_AUTOLOAD "")
# In Video qml qt6 we don't have it.
set(QTMULTIMEDIA_VIDEO_FLUSHMODE "")
else() else()
set(BASICLISTITEM_BOLD "bold") set(BASICLISTITEM_BOLD "bold")
set(OVERLAYSHEET_OPEN "onSheetOpenChanged") set(OVERLAYSHEET_OPEN "onSheetOpenChanged")
set(QTQUICK_MODULE_QML_VERSION "2.15") set(QTQUICK_MODULE_QML_VERSION "2.15")
set(QTLOCATION_MODULE_QML_VERSION "5.15") set(QTLOCATION_MODULE_QML_VERSION "5.15")
set(QTMULTIMEDIA_MODULE_QML_VERSION "5.15")
set(QTMULTIMEDIA_AUDIO "Audio")
set(QTMULTIMEDIA_AUDIO_AUTOLOAD "autoLoad: false")
set(QTMULTIMEDIA_VIDEO_FLUSHMODE "flushMode: VideoOutput.FirstFrame")
endif() endif()
set(QUOTIENT_FORCE_NAMESPACED_INCLUDES TRUE)
ecm_setup_version(${PROJECT_VERSION} ecm_setup_version(${PROJECT_VERSION}
VARIABLE_PREFIX NEOCHAT VARIABLE_PREFIX NEOCHAT

View File

@@ -7,9 +7,9 @@
#include "neochatroom.h" #include "neochatroom.h"
#include <Quotient/connection.h> #include <connection.h>
#include <Quotient/quotient_common.h> #include <quotient_common.h>
#include <Quotient/syncdata.h> #include <syncdata.h>
using namespace Quotient; using namespace Quotient;

View File

@@ -6,9 +6,9 @@
#include "texthandler.h" #include "texthandler.h"
#include <Quotient/quotient_common.h>
#include <Quotient/syncdata.h>
#include <qnamespace.h> #include <qnamespace.h>
#include <quotient_common.h>
#include <syncdata.h>
using namespace Quotient; using namespace Quotient;

View File

@@ -40,6 +40,7 @@
<name xml:lang="ru">NeoChat</name> <name xml:lang="ru">NeoChat</name>
<name xml:lang="sk">NeoChat</name> <name xml:lang="sk">NeoChat</name>
<name xml:lang="sl">NeoChat</name> <name xml:lang="sl">NeoChat</name>
<name xml:lang="sv">NeoChat</name>
<name xml:lang="ta">நியோச்சாட்</name> <name xml:lang="ta">நியோச்சாட்</name>
<name xml:lang="tr">NeoChat</name> <name xml:lang="tr">NeoChat</name>
<name xml:lang="uk">NeoChat</name> <name xml:lang="uk">NeoChat</name>
@@ -76,6 +77,7 @@
<summary xml:lang="ru">Клиент для Matrix — децентрализованного коммуникационного протокола</summary> <summary xml:lang="ru">Клиент для Matrix — децентрализованного коммуникационного протокола</summary>
<summary xml:lang="sk">Klient pre matrix, decentralizovaný komunikačný protokol</summary> <summary xml:lang="sk">Klient pre matrix, decentralizovaný komunikačný protokol</summary>
<summary xml:lang="sl">Odjemalec za matrix, decentralizirani komunikacijski protokol</summary> <summary xml:lang="sl">Odjemalec za matrix, decentralizirani komunikacijski protokol</summary>
<summary xml:lang="sv">En klient för Matrix, det decentraliserade kommunikationsprotokollet</summary>
<summary xml:lang="ta">மையமில்லா தகவல் பரிமாற்ற நெறிமுறையான மேட்ரிக்ஸுக்கான செயலி</summary> <summary xml:lang="ta">மையமில்லா தகவல் பரிமாற்ற நெறிமுறையான மேட்ரிக்ஸுக்கான செயலி</summary>
<summary xml:lang="tr">Merkezi olmayan iletişim protokolü Matrix için bir istemci</summary> <summary xml:lang="tr">Merkezi olmayan iletişim protokolü Matrix için bir istemci</summary>
<summary xml:lang="uk">Клієнт matrix, децентралізованого протоколу обміну даними</summary> <summary xml:lang="uk">Клієнт matrix, децентралізованого протоколу обміну даними</summary>
@@ -96,7 +98,6 @@ to provide a convergent experience across multiple platforms.</p>
<p xml:lang="ia">NeoChat es un cliente per Matrix, le protocollo de communication decentralisate per messager instantanee. Illo te permitte inviar messager de texto, files de video e audio a tu familia, collegas e amicos usante. Illo usa KDE frameworks e super toto Kirigamii forni un experientia convergente trans platteforme multiple.</p> <p xml:lang="ia">NeoChat es un cliente per Matrix, le protocollo de communication decentralisate per messager instantanee. Illo te permitte inviar messager de texto, files de video e audio a tu familia, collegas e amicos usante. Illo usa KDE frameworks e super toto Kirigamii forni un experientia convergente trans platteforme multiple.</p>
<p xml:lang="it">NeoChat è un client per Matrix, il protocollo di comunicazione decentralizzato per la messaggistica istantanea. Ti consente di inviare messaggi di testo, video e file audio a familiari, colleghi e amici. Utilizza i framework KDE e in particolare Kirigami per fornire un'esperienza convergente su più piattaforme.</p> <p xml:lang="it">NeoChat è un client per Matrix, il protocollo di comunicazione decentralizzato per la messaggistica istantanea. Ti consente di inviare messaggi di testo, video e file audio a familiari, colleghi e amici. Utilizza i framework KDE e in particolare Kirigami per fornire un'esperienza convergente su più piattaforme.</p>
<p xml:lang="ka">NeoChat არის Matrix კლიენტი. ის საშუალებას გაძლევთ გაგზავნოთ ტექსტური შეტყობინებები, ვიდეოები და აუდიო ფაილები თქვენს ოჯახს, კოლეგებსა და მეგობრებს მატრიქსის პროტოკოლის გამოყენებით.</p> <p xml:lang="ka">NeoChat არის Matrix კლიენტი. ის საშუალებას გაძლევთ გაგზავნოთ ტექსტური შეტყობინებები, ვიდეოები და აუდიო ფაილები თქვენს ოჯახს, კოლეგებსა და მეგობრებს მატრიქსის პროტოკოლის გამოყენებით.</p>
<p xml:lang="ko">NeoChat은 분산형 인스턴트 메시징 통신 프로토콜인 Matrix 클라이언트입니다. 가족, 동료, 친구에게 텍스트 메시지, 동영상, 오디오 파일을 전송할 수 있습니다. KDE 프레임워크와 Kirigami를 사용하여 다양한 플랫폼에서 일관적인 사용자 경험을 제공합니다.</p>
<p xml:lang="nl">NeoChat is een client voor Matrix, het gedecentraliseerde communicatieprotocol voor instant messages. Het biedt u het verzenden van tekstberichten, video's en geluidsbestanden naar uw familie, collega's en vrienden. Het gebruik KDE frameworks en het meest opmerkelijk Kirigami om een convergente ervaring te leveren op meerdere platforms.</p> <p xml:lang="nl">NeoChat is een client voor Matrix, het gedecentraliseerde communicatieprotocol voor instant messages. Het biedt u het verzenden van tekstberichten, video's en geluidsbestanden naar uw familie, collega's en vrienden. Het gebruik KDE frameworks en het meest opmerkelijk Kirigami om een convergente ervaring te leveren op meerdere platforms.</p>
<p xml:lang="nn">NeoChat er ein klient for Matrix, ein protokoll for desentralisert kommunikasjon. Du kan utveksla tekst, lyd og videoar med kollegaar, vennar og familie. Programmet brukar KDE Frameworks og Kirigami for å gje ei brukarflate tilpassa ulike plattformer.</p> <p xml:lang="nn">NeoChat er ein klient for Matrix, ein protokoll for desentralisert kommunikasjon. Du kan utveksla tekst, lyd og videoar med kollegaar, vennar og familie. Programmet brukar KDE Frameworks og Kirigami for å gje ei brukarflate tilpassa ulike plattformer.</p>
<p xml:lang="pl">NeoChat jest programem do Matriksa, protokołu rozproszonego porozumiewania się w czasie rzeczywistym. Umożliwia wysyłanie wiadomości tekstowych, filmów oraz dźwięku do twojej rodziny, znajomych oraz przyjaciół. Używa szkieletów KDE i głównie Kirigami, aby zapewnić spójne wrażenia na wielu platformach</p> <p xml:lang="pl">NeoChat jest programem do Matriksa, protokołu rozproszonego porozumiewania się w czasie rzeczywistym. Umożliwia wysyłanie wiadomości tekstowych, filmów oraz dźwięku do twojej rodziny, znajomych oraz przyjaciół. Używa szkieletów KDE i głównie Kirigami, aby zapewnić spójne wrażenia na wielu platformach</p>
@@ -117,7 +118,6 @@ to provide a convergent experience across multiple platforms.</p>
<p xml:lang="ia">NeoChat aspira a esser un application plenemente eminente per le specification de Matrix. Tal como omne cosas in le specification currentemente stabile con le exceptiones notabile de VOIP, threads e alcun aspectos del cryptation End-to-End es supportate. Il ha ltere pauc omissiones, debite al facto que le specification de Matrix es in evolution constante ma le aspiration remane a fornir supporto eventual per le integre specification.</p> <p xml:lang="ia">NeoChat aspira a esser un application plenemente eminente per le specification de Matrix. Tal como omne cosas in le specification currentemente stabile con le exceptiones notabile de VOIP, threads e alcun aspectos del cryptation End-to-End es supportate. Il ha ltere pauc omissiones, debite al facto que le specification de Matrix es in evolution constante ma le aspiration remane a fornir supporto eventual per le integre specification.</p>
<p xml:lang="it">NeoChat mira ad essere un'applicazione completa per le specifiche Matrix. Pertanto, sono supportati tutti gli elementi dell'attuale specifica stabile con le notevoli eccezioni di VoIP, conversazioni e alcuni aspetti della cifratura end-to-end. Ci sono alcune altre piccole omissioni dovute al fatto che le specifiche Matrix sono in continua evoluzione, ma l'obiettivo rimane quello di fornire un eventuale supporto per l'intera specifica.</p> <p xml:lang="it">NeoChat mira ad essere un'applicazione completa per le specifiche Matrix. Pertanto, sono supportati tutti gli elementi dell'attuale specifica stabile con le notevoli eccezioni di VoIP, conversazioni e alcuni aspetti della cifratura end-to-end. Ci sono alcune altre piccole omissioni dovute al fatto che le specifiche Matrix sono in continua evoluzione, ma l'obiettivo rimane quello di fornire un eventuale supporto per l'intera specifica.</p>
<p xml:lang="ka">NeoChat-ი მიზნად ისახავს Matrix სპეციფიკაციის სრული განხორციელება ჰქონდეს. როგორც ასეთი, ყველაფერი მიმდინარე სპეციფიკაციიდან, VoIP-ის, ძაფებისა და გამჭოლი დაშიფვრის ზოგიერთი ასპექტის გარდა, მხარდაჭერილია. შეძლება ასევე იყოს მცირე ლაფსუსებიც იმის გამო, რომ Matrix-ის სპეციფიკაცია მუდმივად ვითარგდება, მაგრამ ჩვენი მიზანი მისი სრული მხარდაჭერაა.</p> <p xml:lang="ka">NeoChat-ი მიზნად ისახავს Matrix სპეციფიკაციის სრული განხორციელება ჰქონდეს. როგორც ასეთი, ყველაფერი მიმდინარე სპეციფიკაციიდან, VoIP-ის, ძაფებისა და გამჭოლი დაშიფვრის ზოგიერთი ასპექტის გარდა, მხარდაჭერილია. შეძლება ასევე იყოს მცირე ლაფსუსებიც იმის გამო, რომ Matrix-ის სპეციფიკაცია მუდმივად ვითარგდება, მაგრამ ჩვენი მიზანი მისი სრული მხარდაჭერაა.</p>
<p xml:lang="ko">NeoChat은 Matrix 표준을 따르는 프로그램을 목표로 합니다. 현재 안정 버전의 표준에서 제공하는 기능의 대부분을 지원하며, VoIP, 스레드, 일부 종단간 암호화와 같은 기능은 아직 지원하지 않습니다. Matrix 표준은 계속하여 진화 중이기 때문에 일부 기능이 빠져 있을 수도 있지만 장기적으로는 전체 표준을 지원하는 것이 목표입니다.</p>
<p xml:lang="nl">NeoChat richt zich op het volledig bieden van alle mogelijkheden van de Matrix-specificatie. Alles in de huidige stabiele specificatie met merkbare uitzondering van VoIP, gekoppelde discussies en sommige aspecten van eind-tot-eind versleuteling worden ondersteund. Er zijn een paar andere kleinere omissies vanwege het feit dat de Matrix specificatie constant evolueert maar het doel blijft het eventueel bieden van ondersteuning van de gehele specificatie.</p> <p xml:lang="nl">NeoChat richt zich op het volledig bieden van alle mogelijkheden van de Matrix-specificatie. Alles in de huidige stabiele specificatie met merkbare uitzondering van VoIP, gekoppelde discussies en sommige aspecten van eind-tot-eind versleuteling worden ondersteund. Er zijn een paar andere kleinere omissies vanwege het feit dat de Matrix specificatie constant evolueert maar het doel blijft het eventueel bieden van ondersteuning van de gehele specificatie.</p>
<p xml:lang="nn">NeoChat har som mål å støtta all funksjonalitet i Matrix-spesifikasjonen. Førebels er alt i den gjeldande stabile spesifikasjonen støtta, med unntak av VoIP, trådar og nokre delar av ende-til-kryptering. Det finst òg andre småting som ikkje er støtta, sidan Matrix-spesifikasjon er i stadig endring, men målet er altså støtte for alt.</p> <p xml:lang="nn">NeoChat har som mål å støtta all funksjonalitet i Matrix-spesifikasjonen. Førebels er alt i den gjeldande stabile spesifikasjonen støtta, med unntak av VoIP, trådar og nokre delar av ende-til-kryptering. Det finst òg andre småting som ikkje er støtta, sidan Matrix-spesifikasjon er i stadig endring, men målet er altså støtte for alt.</p>
<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="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>
@@ -138,7 +138,6 @@ to provide a convergent experience across multiple platforms.</p>
<p xml:lang="ia">Debite al natura del disveloppamento de specification de Matrix NeoChat tamben supporta numerose characteristicas instabile. Currentemente istes es:</p> <p xml:lang="ia">Debite al natura del disveloppamento de specification de Matrix NeoChat tamben supporta numerose characteristicas instabile. Currentemente istes es:</p>
<p xml:lang="it">A causa della natura dello sviluppo delle specifiche Matrix, NeoChat supporta anche numerose funzionalità instabili. Attualmente queste sono:</p> <p xml:lang="it">A causa della natura dello sviluppo delle specifiche Matrix, NeoChat supporta anche numerose funzionalità instabili. Attualmente queste sono:</p>
<p xml:lang="ka">Matrix-ის სპეციფიკაციის განვითარების ბუნების გამო NeoChat-ს ასევე აქვს უამრავი არასტაბილური ფუნქციაც. ახლა ისინია:</p> <p xml:lang="ka">Matrix-ის სპეციფიკაციის განვითარების ბუნების გამო NeoChat-ს ასევე აქვს უამრავი არასტაბილური ფუნქციაც. ახლა ისინია:</p>
<p xml:lang="ko">Matrix 표준 개발의 특징으로 인하여 NeoChat은 일부 실험적인 기능을 지원합니다. 현재 지원하는 기능은 다음과 같습니다.</p>
<p xml:lang="nl">Vanwege de aard van de ontwikkeling van de Matrix specificatie ondersteunt NeoChat ook talloze onstabiele mogelijkheden. Dit zijn nu:</p> <p xml:lang="nl">Vanwege de aard van de ontwikkeling van de Matrix specificatie ondersteunt NeoChat ook talloze onstabiele mogelijkheden. Dit zijn nu:</p>
<p xml:lang="nn">På grunn av måten Matrix-spesifikasjonen vert utvikla på, støttar NeoChat òg nokre uferdige funksjonar:</p> <p xml:lang="nn">På grunn av måten Matrix-spesifikasjonen vert utvikla på, støttar NeoChat òg nokre uferdige funksjonar:</p>
<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="pl">Ze względu na sposób rozwoju Matriksa, NeoChat obsługuje także kilka niestabilnych możliwości. Obecnie są to:</p>
@@ -160,7 +159,6 @@ to provide a convergent experience across multiple platforms.</p>
<li xml:lang="ia">Inquestas - MSC3381</li> <li xml:lang="ia">Inquestas - MSC3381</li>
<li xml:lang="it">Sondaggi - MSC3381</li> <li xml:lang="it">Sondaggi - MSC3381</li>
<li xml:lang="ka">Polls - MSC3381</li> <li xml:lang="ka">Polls - MSC3381</li>
<li xml:lang="ko">투표 - MSC3381</li>
<li xml:lang="nl">Polls - MSC3381</li> <li xml:lang="nl">Polls - MSC3381</li>
<li xml:lang="nn">Avstemmingar  MSC3381</li> <li xml:lang="nn">Avstemmingar  MSC3381</li>
<li xml:lang="pt">Inquéritos - MSC3381</li> <li xml:lang="pt">Inquéritos - MSC3381</li>
@@ -181,7 +179,6 @@ to provide a convergent experience across multiple platforms.</p>
<li xml:lang="ia">Etiquetta gummate (sticker) -MSC2545</li> <li xml:lang="ia">Etiquetta gummate (sticker) -MSC2545</li>
<li xml:lang="it">Pacchetti di adesivi - MSC2545</li> <li xml:lang="it">Pacchetti di adesivi - MSC2545</li>
<li xml:lang="ka">სტიკერების პაკეტები - MSC2545</li> <li xml:lang="ka">სტიკერების პაკეტები - MSC2545</li>
<li xml:lang="ko">스티커 팩 - MSC2545</li>
<li xml:lang="nl">Sticker Packs - MSC2545</li> <li xml:lang="nl">Sticker Packs - MSC2545</li>
<li xml:lang="nn">Klistremerke-pakkar  MSC2545</li> <li xml:lang="nn">Klistremerke-pakkar  MSC2545</li>
<li xml:lang="pt">Pacotes de Autocolantes - MSC2545</li> <li xml:lang="pt">Pacotes de Autocolantes - MSC2545</li>
@@ -202,7 +199,6 @@ to provide a convergent experience across multiple platforms.</p>
<li xml:lang="ia">Eventos de Location - MSC3488</li> <li xml:lang="ia">Eventos de Location - MSC3488</li>
<li xml:lang="it">Località eventi - MSC3488</li> <li xml:lang="it">Località eventi - MSC3488</li>
<li xml:lang="ka">მდებარეობის მოვლენები - MSC3488</li> <li xml:lang="ka">მდებარეობის მოვლენები - MSC3488</li>
<li xml:lang="ko">위치 이벤트 - MSC3488</li>
<li xml:lang="nl">Locatie gebeurtenissen - MSC3488</li> <li xml:lang="nl">Locatie gebeurtenissen - MSC3488</li>
<li xml:lang="nn">Posisjonshendingar  MSC3488</li> <li xml:lang="nn">Posisjonshendingar  MSC3488</li>
<li xml:lang="pt">Eventos com Localizações - MSC3488</li> <li xml:lang="pt">Eventos com Localizações - MSC3488</li>
@@ -249,6 +245,7 @@ to provide a convergent experience across multiple platforms.</p>
<developer_name xml:lang="ru">Сообщество KDE</developer_name> <developer_name xml:lang="ru">Сообщество KDE</developer_name>
<developer_name xml:lang="sk">KDE Komunita</developer_name> <developer_name xml:lang="sk">KDE Komunita</developer_name>
<developer_name xml:lang="sl">Skupnost KDE</developer_name> <developer_name xml:lang="sl">Skupnost KDE</developer_name>
<developer_name xml:lang="sv">KDE-gemenskapen</developer_name>
<developer_name xml:lang="ta">கே.டீ.யீ. சமூகம்</developer_name> <developer_name xml:lang="ta">கே.டீ.யீ. சமூகம்</developer_name>
<developer_name xml:lang="tr">KDE Topluluğu</developer_name> <developer_name xml:lang="tr">KDE Topluluğu</developer_name>
<developer_name xml:lang="uk">Спільнота KDE</developer_name> <developer_name xml:lang="uk">Спільнота KDE</developer_name>
@@ -269,15 +266,10 @@ to provide a convergent experience across multiple platforms.</p>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ca">Vista principal amb la llista de sales, xats i informació de les sales</value> <value key="KDE::windows_store::screenshots::1::caption" xml:lang="ca">Vista principal amb la llista de sales, xats i informació de les sales</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ca-valencia">Vista principal amb la llista de sales, xats i informació de les sales</value> <value key="KDE::windows_store::screenshots::1::caption" xml:lang="ca-valencia">Vista principal amb la llista de sales, xats i informació de les sales</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="es">Vista principal con la lista de salas, chat e información de la sala</value> <value key="KDE::windows_store::screenshots::1::caption" xml:lang="es">Vista principal con la lista de salas, chat e información de la sala</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="fr">Vue principale avec la liste des salons ainsi que des informations sur les salons et forums de discussions</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ia">Vista principal con lista de sala, chat e information de sala</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="it">Vista principale con elenco delle stanze, chat e informazioni sulla stanza</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ka">მთავარი ხედი სურათების სიით, ჩატით და ოთახის ინფორმაციით</value> <value key="KDE::windows_store::screenshots::1::caption" xml:lang="ka">მთავარი ხედი სურათების სიით, ჩატით და ოთახის ინფორმაციით</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ko">대화방 목록, 채팅, 대화방 정보가 표시된 주 보기</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="nl">Hoofdweergave met lijst met rooms, chat en roominformatie</value> <value key="KDE::windows_store::screenshots::1::caption" xml:lang="nl">Hoofdweergave met lijst met rooms, chat en roominformatie</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="pt">A área principal com a lista de salas e com informações sobre a conversa e a sala</value> <value key="KDE::windows_store::screenshots::1::caption" xml:lang="pt">A área principal com a lista de salas e com informações sobre a conversa e a sala</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="sl">Glavni pogled s seznamom sob, klepetom in informacijami o sobah</value> <value key="KDE::windows_store::screenshots::1::caption" xml:lang="sl">Glavni pogled s seznamom sob, klepetom in informacijami o sobah</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="ta">அரங்குப்பட்டியல், உரையாடல், மற்றும் அரங்குவிவரங்களைக் கொண்டுள்ள பிரதான காட்சி</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="tr">Oda listesini, sohbet penceresini ve oda bilgisini gösteren ana görünüm</value> <value key="KDE::windows_store::screenshots::1::caption" xml:lang="tr">Oda listesini, sohbet penceresini ve oda bilgisini gösteren ana görünüm</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="uk">Головна панель із списком кімнат, спілкуванням та даними щодо кімнати</value> <value key="KDE::windows_store::screenshots::1::caption" xml:lang="uk">Головна панель із списком кімнат, спілкуванням та даними щодо кімнати</value>
<value key="KDE::windows_store::screenshots::1::caption" xml:lang="x-test">xxMain view with room list, chat, and room informationxx</value> <value key="KDE::windows_store::screenshots::1::caption" xml:lang="x-test">xxMain view with room list, chat, and room informationxx</value>
@@ -286,15 +278,10 @@ to provide a convergent experience across multiple platforms.</p>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ca">Pantalla d'inici de sessió</value> <value key="KDE::windows_store::screenshots::2::caption" xml:lang="ca">Pantalla d'inici de sessió</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ca-valencia">Pantalla d'inici de sessió</value> <value key="KDE::windows_store::screenshots::2::caption" xml:lang="ca-valencia">Pantalla d'inici de sessió</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="es">Pantalla de inicio de sesión</value> <value key="KDE::windows_store::screenshots::2::caption" xml:lang="es">Pantalla de inicio de sesión</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="fr">Écran de connexion</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ia">Schermo de accesso</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="it">Schermata di accesso</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ka">შესვლის ეკრანი</value> <value key="KDE::windows_store::screenshots::2::caption" xml:lang="ka">შესვლის ეკრანი</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ko">로그인 화면</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="nl">Aanmeldscherm</value> <value key="KDE::windows_store::screenshots::2::caption" xml:lang="nl">Aanmeldscherm</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="pt">Ecrã de autenticação</value> <value key="KDE::windows_store::screenshots::2::caption" xml:lang="pt">Ecrã de autenticação</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="sl">Prijavni zaslon</value> <value key="KDE::windows_store::screenshots::2::caption" xml:lang="sl">Prijavni zaslon</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="ta">நுழைவுத் திரை</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="tr">Oturum açma ekranı</value> <value key="KDE::windows_store::screenshots::2::caption" xml:lang="tr">Oturum açma ekranı</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="uk">Вікно входу</value> <value key="KDE::windows_store::screenshots::2::caption" xml:lang="uk">Вікно входу</value>
<value key="KDE::windows_store::screenshots::2::caption" xml:lang="x-test">xxLogin screenxx</value> <value key="KDE::windows_store::screenshots::2::caption" xml:lang="x-test">xxLogin screenxx</value>

View File

@@ -35,6 +35,7 @@ Name[ro]=NeoChat
Name[ru]=NeoChat Name[ru]=NeoChat
Name[sk]=NeoChat Name[sk]=NeoChat
Name[sl]=NeoChat Name[sl]=NeoChat
Name[sv]=NeoChat
Name[ta]=நியோச்சாட் Name[ta]=நியோச்சாட்
Name[tr]=NeoChat Name[tr]=NeoChat
Name[uk]=NeoChat Name[uk]=NeoChat
@@ -73,6 +74,7 @@ GenericName[ro]=Client Matrix
GenericName[ru]=Клиент Matrix GenericName[ru]=Клиент Matrix
GenericName[sk]=Matrix Client GenericName[sk]=Matrix Client
GenericName[sl]=Odjemalec Matrix GenericName[sl]=Odjemalec Matrix
GenericName[sv]=Matrix-klient
GenericName[ta]=Matrix வாங்கி GenericName[ta]=Matrix வாங்கி
GenericName[tr]=Matrix İstemcisi GenericName[tr]=Matrix İstemcisi
GenericName[uk]=Клієнт Matrix GenericName[uk]=Клієнт Matrix
@@ -110,6 +112,7 @@ Comment[ro]=Client pentru protocolul Matrix
Comment[ru]=Клиент для протокола Matrix Comment[ru]=Клиент для протокола Matrix
Comment[sk]=Klient protokolu Matrix Comment[sk]=Klient protokolu Matrix
Comment[sl]=Odjemalec za protokol Matrix Comment[sl]=Odjemalec za protokol Matrix
Comment[sv]=Klient för protokollet Matrix
Comment[ta]=Matrix நெறிமுறைக்கான வாங்கி Comment[ta]=Matrix நெறிமுறைக்கான வாங்கி
Comment[tr]=Matrix protokolü için istemci Comment[tr]=Matrix protokolü için istemci
Comment[uk]=Клієнт протоколу Matrix Comment[uk]=Клієнт протоколу Matrix

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4589
po/sv/neochat.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,6 @@ configure_file(qml/Page/RoomList/RoomDelegate.qml ${CMAKE_CURRENT_BINARY_DIR}/qm
configure_file(qml/Component/QuickSwitcher.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/QuickSwitcher.qml) configure_file(qml/Component/QuickSwitcher.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/QuickSwitcher.qml)
configure_file(qml/Dialog/UserDetailDialog.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Dialog/UserDetailDialog.qml) configure_file(qml/Dialog/UserDetailDialog.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Dialog/UserDetailDialog.qml)
configure_file(qml/Dialog/PowerLevelDialog.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Dialog/PowerLevelDialog.qml) configure_file(qml/Dialog/PowerLevelDialog.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Dialog/PowerLevelDialog.qml)
configure_file(qml/Component/Timeline/AudioDelegate.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/Timeline/AudioDelegate.qml)
configure_file(qml/Component/Timeline/VideoDelegate.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/Timeline/VideoDelegate.qml)
configure_file(qml/Component/Timeline/OsmLocationPlugin.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/Timeline/OsmLocationPlugin.qml) configure_file(qml/Component/Timeline/OsmLocationPlugin.qml ${CMAKE_CURRENT_BINARY_DIR}/qml/Component/Timeline/OsmLocationPlugin.qml)
configure_file(res.qrc ${CMAKE_CURRENT_SOURCE_DIR}/res.generated.qrc) configure_file(res.qrc ${CMAKE_CURRENT_SOURCE_DIR}/res.generated.qrc)
@@ -66,7 +64,6 @@ add_library(neochat STATIC
chatdocumenthandler.h chatdocumenthandler.h
models/devicesmodel.cpp models/devicesmodel.cpp
models/devicesmodel.h models/devicesmodel.h
models/devicesproxymodel.cpp
filetypesingleton.cpp filetypesingleton.cpp
filetypesingleton.h filetypesingleton.h
login.cpp login.cpp

View File

@@ -3,8 +3,8 @@
#include "actionshandler.h" #include "actionshandler.h"
#include <Quotient/csapi/joining.h> #include <csapi/joining.h>
#include <Quotient/events/roommemberevent.h> #include <events/roommemberevent.h>
#include <cmark.h> #include <cmark.h>

View File

@@ -5,7 +5,7 @@
#include <QObject> #include <QObject>
#include <Quotient/events/roommessageevent.h> #include <events/roommessageevent.h>
#include "neochatroom.h" #include "neochatroom.h"

View File

@@ -218,8 +218,8 @@ void ChatDocumentHandler::setRoom(NeoChatRoom *room)
void ChatDocumentHandler::complete(int index) void ChatDocumentHandler::complete(int index)
{ {
if (m_completionModel->autoCompletionType() == CompletionModel::User) { if (m_completionModel->autoCompletionType() == CompletionModel::User) {
auto name = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::DisplayNameRole).toString(); auto name = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Text).toString();
auto id = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::SubtitleRole).toString(); auto id = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
auto text = getText(); auto text = getText();
auto at = text.lastIndexOf(QLatin1Char('@'), cursorPosition() - 1); auto at = text.lastIndexOf(QLatin1Char('@'), cursorPosition() - 1);
QTextCursor cursor(document()->textDocument()); QTextCursor cursor(document()->textDocument());
@@ -232,7 +232,7 @@ void ChatDocumentHandler::complete(int index)
pushMention({cursor, name, 0, 0, id}); pushMention({cursor, name, 0, 0, id});
m_highlighter->rehighlight(); m_highlighter->rehighlight();
} else if (m_completionModel->autoCompletionType() == CompletionModel::Command) { } else if (m_completionModel->autoCompletionType() == CompletionModel::Command) {
auto command = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedTextRole).toString(); auto command = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
auto text = getText(); auto text = getText();
auto at = text.lastIndexOf(QLatin1Char('/')); auto at = text.lastIndexOf(QLatin1Char('/'));
QTextCursor cursor(document()->textDocument()); QTextCursor cursor(document()->textDocument());
@@ -240,7 +240,7 @@ void ChatDocumentHandler::complete(int index)
cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor); cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor);
cursor.insertText(QStringLiteral("/%1 ").arg(command)); cursor.insertText(QStringLiteral("/%1 ").arg(command));
} else if (m_completionModel->autoCompletionType() == CompletionModel::Room) { } else if (m_completionModel->autoCompletionType() == CompletionModel::Room) {
auto alias = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::SubtitleRole).toString(); auto alias = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
auto text = getText(); auto text = getText();
auto at = text.lastIndexOf(QLatin1Char('#'), cursorPosition() - 1); auto at = text.lastIndexOf(QLatin1Char('#'), cursorPosition() - 1);
QTextCursor cursor(document()->textDocument()); QTextCursor cursor(document()->textDocument());
@@ -253,7 +253,7 @@ void ChatDocumentHandler::complete(int index)
pushMention({cursor, alias, 0, 0, alias}); pushMention({cursor, alias, 0, 0, alias});
m_highlighter->rehighlight(); m_highlighter->rehighlight();
} else if (m_completionModel->autoCompletionType() == CompletionModel::Emoji) { } else if (m_completionModel->autoCompletionType() == CompletionModel::Emoji) {
auto shortcode = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedTextRole).toString(); auto shortcode = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
auto text = getText(); auto text = getText();
auto at = text.lastIndexOf(QLatin1Char(':')); auto at = text.lastIndexOf(QLatin1Char(':'));
QTextCursor cursor(document()->textDocument()); QTextCursor cursor(document()->textDocument());

View File

@@ -31,15 +31,16 @@
#include <signal.h> #include <signal.h>
#include <Quotient/accountregistry.h> #include "accountregistry.h"
#include <Quotient/connection.h>
#include <Quotient/csapi/content-repo.h> #include <connection.h>
#include <Quotient/csapi/logout.h> #include <csapi/content-repo.h>
#include <Quotient/csapi/profile.h> #include <csapi/logout.h>
#include <Quotient/jobs/downloadfilejob.h> #include <csapi/profile.h>
#include <Quotient/qt_connection_util.h> #include <jobs/downloadfilejob.h>
#include <Quotient/csapi/notifications.h> #include <qt_connection_util.h>
#include <Quotient/eventstats.h>
#include <eventstats.h>
#include "neochatconfig.h" #include "neochatconfig.h"
#include "neochatroom.h" #include "neochatroom.h"
@@ -101,17 +102,17 @@ Controller::Controller(QObject *parent)
} }
#endif #endif
connect(&m_accountRegistry, &AccountRegistry::accountCountChanged, this, &Controller::activeConnectionIndexChanged); connect(&Accounts, &AccountRegistry::accountCountChanged, this, &Controller::activeConnectionIndexChanged);
static int oldAccountCount = 0; static int oldAccountCount = 0;
connect(&m_accountRegistry, &AccountRegistry::accountCountChanged, this, [this]() { connect(&Accounts, &AccountRegistry::accountCountChanged, this, [this]() {
if (m_accountRegistry.size() > oldAccountCount) { if (Accounts.size() > oldAccountCount) {
auto connection = m_accountRegistry.accounts()[m_accountRegistry.size() - 1]; auto connection = Accounts.accounts()[Accounts.size() - 1];
connect(connection, &Connection::syncDone, this, [connection]() { connect(connection, &Connection::syncDone, this, [connection]() {
NotificationsManager::instance().handleNotifications(connection); NotificationsManager::instance().handleNotifications(connection);
}); });
} }
oldAccountCount = m_accountRegistry.size(); oldAccountCount = Accounts.size();
}); });
QTimer::singleShot(0, this, [this] { QTimer::singleShot(0, this, [this] {
@@ -147,10 +148,10 @@ void Controller::logout(Connection *conn, bool serverSideLogout)
job.start(); job.start();
loop.exec(); loop.exec();
if (m_accountRegistry.count() > 1) { if (Accounts.count() > 1) {
// Only set the connection if the the account being logged out is currently active // Only set the connection if the the account being logged out is currently active
if (conn == activeConnection()) { if (conn == activeConnection()) {
setActiveConnection(m_accountRegistry.accounts()[0]); setActiveConnection(Accounts.accounts()[0]);
} }
} else { } else {
setActiveConnection(nullptr); setActiveConnection(nullptr);
@@ -165,7 +166,7 @@ void Controller::addConnection(Connection *c)
{ {
Q_ASSERT_X(c, __FUNCTION__, "Attempt to add a null connection"); Q_ASSERT_X(c, __FUNCTION__, "Attempt to add a null connection");
m_accountRegistry.add(c); Accounts.add(c);
c->setLazyLoading(true); c->setLazyLoading(true);
@@ -180,7 +181,7 @@ void Controller::addConnection(Connection *c)
}); });
connect(c, &Connection::requestFailed, this, [this](BaseJob *job) { connect(c, &Connection::requestFailed, this, [this](BaseJob *job) {
if (job->error() == BaseJob::UserConsentRequired) { if (job->error() == BaseJob::UserConsentRequiredError) {
Q_EMIT userConsentRequired(job->errorUrl()); Q_EMIT userConsentRequired(job->errorUrl());
} }
}); });
@@ -247,7 +248,7 @@ void Controller::invokeLogin()
connect(connection, &Connection::networkError, this, [this](const QString &error, const QString &, int, int) { connect(connection, &Connection::networkError, this, [this](const QString &error, const QString &, int, int) {
Q_EMIT errorOccured(i18n("Network Error: %1", error)); Q_EMIT errorOccured(i18n("Network Error: %1", error));
}); });
connection->assumeIdentity(account.userId(), accessToken); connection->assumeIdentity(account.userId(), accessToken, account.deviceId());
}); });
} }
} }
@@ -263,7 +264,7 @@ QKeychain::ReadPasswordJob *Controller::loadAccessTokenFromKeyChain(const Accoun
job->setKey(account.userId()); job->setKey(account.userId());
// Handling of errors // Handling of errors
connect(job, &QKeychain::Job::finished, this, [this, job]() { connect(job, &QKeychain::Job::finished, this, [this, &account, job]() {
if (job->error() == QKeychain::Error::NoError) { if (job->error() == QKeychain::Error::NoError) {
return; return;
} }
@@ -391,7 +392,7 @@ NeochatChangePasswordJob::NeochatChangePasswordJob(const QString &newPassword, b
int Controller::accountCount() const int Controller::accountCount() const
{ {
return m_accountRegistry.count(); return Accounts.count();
} }
void Controller::setQuitOnLastWindowClosed() void Controller::setQuitOnLastWindowClosed()
@@ -625,10 +626,10 @@ void Controller::setApplicationProxy()
int Controller::activeConnectionIndex() const int Controller::activeConnectionIndex() const
{ {
auto result = std::find_if(m_accountRegistry.accounts().begin(), m_accountRegistry.accounts().end(), [this](const auto &it) { auto result = std::find_if(Accounts.accounts().begin(), Accounts.accounts().end(), [this](const auto &it) {
return it == m_connection; return it == m_connection;
}); });
return result - m_accountRegistry.accounts().begin(); return result - Accounts.accounts().begin();
} }
int Controller::quotientMinorVersion() const int Controller::quotientMinorVersion() const
@@ -681,9 +682,4 @@ QVariantList Controller::getSupportedRoomVersions(Quotient::Connection *connecti
return supportedRoomVersions; return supportedRoomVersions;
} }
AccountRegistry &Controller::accounts()
{
return m_accountRegistry;
}
#include "moc_controller.cpp" #include "moc_controller.cpp"

View File

@@ -9,9 +9,8 @@
#include <KFormat> #include <KFormat>
#include <Quotient/accountregistry.h> #include <jobs/basejob.h>
#include <Quotient/jobs/basejob.h> #include <settings.h>
#include <Quotient/settings.h>
class NeoChatRoom; class NeoChatRoom;
class NeoChatUser; class NeoChatUser;
@@ -230,8 +229,6 @@ public:
Q_INVOKABLE QVariantList getSupportedRoomVersions(Quotient::Connection *connection); Q_INVOKABLE QVariantList getSupportedRoomVersions(Quotient::Connection *connection);
Quotient::AccountRegistry &accounts();
private: private:
explicit Controller(QObject *parent = nullptr); explicit Controller(QObject *parent = nullptr);
@@ -248,7 +245,6 @@ private:
bool hasWindowSystem() const; bool hasWindowSystem() const;
QPointer<PushRuleModel> m_pushRuleModel; QPointer<PushRuleModel> m_pushRuleModel;
Quotient::AccountRegistry m_accountRegistry;
private Q_SLOTS: private Q_SLOTS:
void invokeLogin(); void invokeLogin();

View File

@@ -4,8 +4,8 @@
#pragma once #pragma once
#include <QVector> #include <QVector>
#include <Quotient/events/eventcontent.h> #include <events/eventcontent.h>
#include <Quotient/events/stateevent.h> #include <events/stateevent.h>
namespace Quotient namespace Quotient
{ {

View File

@@ -3,7 +3,7 @@
#pragma once #pragma once
#include <Quotient/events/stateevent.h> #include <events/stateevent.h>
namespace Quotient namespace Quotient
{ {

View File

@@ -3,7 +3,8 @@
#pragma once #pragma once
#include <Quotient/events/roomevent.h> #include <events/eventcontent.h>
#include <events/roomevent.h>
namespace Quotient namespace Quotient
{ {

View File

@@ -3,10 +3,8 @@
#include "linkpreviewer.h" #include "linkpreviewer.h"
#include "controller.h" #include <connection.h>
#include <csapi/content-repo.h>
#include <Quotient/connection.h>
#include <Quotient/csapi/content-repo.h>
#include "neochatroom.h" #include "neochatroom.h"

View File

@@ -3,9 +3,10 @@
#include "login.h" #include "login.h"
#include <Quotient/accountregistry.h> #include <accountregistry.h>
#include <Quotient/connection.h>
#include <Quotient/qt_connection_util.h> #include <connection.h>
#include <qt_connection_util.h>
#include "controller.h" #include "controller.h"
@@ -42,7 +43,7 @@ void Login::init()
return; return;
} }
m_isLoggedIn = Controller::instance().accounts().isLoggedIn(m_matrixId); m_isLoggedIn = Accounts.isLoggedIn(m_matrixId);
Q_EMIT isLoggedInChanged(); Q_EMIT isLoggedInChanged();
if (m_isLoggedIn) { if (m_isLoggedIn) {
return; return;

View File

@@ -28,11 +28,10 @@
#include "neochat-version.h" #include "neochat-version.h"
#include <Quotient/keyverificationsession.h> #include <accountregistry.h>
#include <Quotient/accountregistry.h> #include <networkaccessmanager.h>
#include <Quotient/networkaccessmanager.h> #include <room.h>
#include <Quotient/room.h> #include <util.h>
#include <Quotient/util.h>
#include "actionshandler.h" #include "actionshandler.h"
#include "blurhashimageprovider.h" #include "blurhashimageprovider.h"
@@ -50,7 +49,6 @@
#include "models/collapsestateproxymodel.h" #include "models/collapsestateproxymodel.h"
#include "models/customemojimodel.h" #include "models/customemojimodel.h"
#include "models/devicesmodel.h" #include "models/devicesmodel.h"
#include "models/devicesproxymodel.h"
#include "models/emojimodel.h" #include "models/emojimodel.h"
#include "models/emoticonfiltermodel.h" #include "models/emoticonfiltermodel.h"
#include "models/imagepacksmodel.h" #include "models/imagepacksmodel.h"
@@ -82,7 +80,7 @@
#include "spacehierarchycache.h" #include "spacehierarchycache.h"
#include "urlhelper.h" #include "urlhelper.h"
#include "windowcontroller.h" #include "windowcontroller.h"
#include <keyverificationsession.h>
#ifdef HAVE_COLORSCHEME #ifdef HAVE_COLORSCHEME
#include "colorschemer.h" #include "colorschemer.h"
#endif #endif
@@ -218,7 +216,7 @@ int main(int argc, char *argv[])
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "LoginHelper", login); qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "LoginHelper", login);
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "UrlHelper", &urlHelper); qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "UrlHelper", &urlHelper);
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "EmojiModel", &EmojiModel::instance()); qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "EmojiModel", &EmojiModel::instance());
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "AccountRegistry", &Controller::instance().accounts()); qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "AccountRegistry", &Quotient::Accounts);
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "SpaceHierarchyCache", &SpaceHierarchyCache::instance()); qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "SpaceHierarchyCache", &SpaceHierarchyCache::instance());
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "CustomEmojiModel", &CustomEmojiModel::instance()); qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "CustomEmojiModel", &CustomEmojiModel::instance());
qmlRegisterType<ActionsHandler>("org.kde.neochat", 1, 0, "ActionsHandler"); qmlRegisterType<ActionsHandler>("org.kde.neochat", 1, 0, "ActionsHandler");
@@ -238,7 +236,6 @@ int main(int argc, char *argv[])
qmlRegisterType<SortFilterRoomListModel>("org.kde.neochat", 1, 0, "SortFilterRoomListModel"); qmlRegisterType<SortFilterRoomListModel>("org.kde.neochat", 1, 0, "SortFilterRoomListModel");
qmlRegisterType<SortFilterSpaceListModel>("org.kde.neochat", 1, 0, "SortFilterSpaceListModel"); qmlRegisterType<SortFilterSpaceListModel>("org.kde.neochat", 1, 0, "SortFilterSpaceListModel");
qmlRegisterType<DevicesModel>("org.kde.neochat", 1, 0, "DevicesModel"); qmlRegisterType<DevicesModel>("org.kde.neochat", 1, 0, "DevicesModel");
qmlRegisterType<DevicesProxyModel>("org.kde.neochat", 1, 0, "DevicesProxyModel");
qmlRegisterType<LinkPreviewer>("org.kde.neochat", 1, 0, "LinkPreviewer"); qmlRegisterType<LinkPreviewer>("org.kde.neochat", 1, 0, "LinkPreviewer");
qmlRegisterType<CompletionModel>("org.kde.neochat", 1, 0, "CompletionModel"); qmlRegisterType<CompletionModel>("org.kde.neochat", 1, 0, "CompletionModel");
qmlRegisterType<StateModel>("org.kde.neochat", 1, 0, "StateModel"); qmlRegisterType<StateModel>("org.kde.neochat", 1, 0, "StateModel");

View File

@@ -13,7 +13,7 @@
#include <KLocalizedString> #include <KLocalizedString>
#include "controller.h" #include "controller.h"
#include <Quotient/connection.h> #include <connection.h>
using namespace Quotient; using namespace Quotient;
@@ -32,17 +32,11 @@ ThumbnailResponse::ThumbnailResponse(QString id, QSize size)
requestedSize.setWidth(100); requestedSize.setWidth(100);
} }
if (mediaId.count('/') != 1) { if (mediaId.count('/') != 1) {
if (mediaId.startsWith(QLatin1Char('/'))) { errorStr = i18n("Media id '%1' doesn't follow server/mediaId pattern", mediaId);
mediaId = mediaId.mid(1); Q_EMIT finished();
} else { return;
errorStr = i18n("Media id '%1' doesn't follow server/mediaId pattern", mediaId);
Q_EMIT finished();
return;
}
} }
mediaId = mediaId.split(QLatin1Char('?'))[0];
QImage cachedImage; QImage cachedImage;
if (cachedImage.load(localFile)) { if (cachedImage.load(localFile)) {
image = cachedImage; image = cachedImage;

View File

@@ -6,7 +6,7 @@
#include <QQuickAsyncImageProvider> #include <QQuickAsyncImageProvider>
#include <Quotient/jobs/mediathumbnailjob.h> #include <jobs/mediathumbnailjob.h>
#include <QReadWriteLock> #include <QReadWriteLock>
@@ -26,7 +26,7 @@ class ThumbnailResponse : public QQuickImageResponse
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ThumbnailResponse(QString mediaId, QSize requestedSize); ThumbnailResponse(QString mediaId, QSize requestedSize);
~ThumbnailResponse() override = default; ~ThumbnailResponse() override = default;
private Q_SLOTS: private Q_SLOTS:
@@ -34,7 +34,7 @@ private Q_SLOTS:
void prepareResult(); void prepareResult();
private: private:
QString mediaId; const QString mediaId;
QSize requestedSize; QSize requestedSize;
const QString localFile; const QString localFile;
Quotient::MediaThumbnailJob *job = nullptr; Quotient::MediaThumbnailJob *job = nullptr;

View File

@@ -3,7 +3,7 @@
#include "accountemoticonmodel.h" #include "accountemoticonmodel.h"
#include <Quotient/csapi/content-repo.h> #include <csapi/content-repo.h>
#include <qcoro/qcorosignal.h> #include <qcoro/qcorosignal.h>
using namespace Quotient; using namespace Quotient;

View File

@@ -4,14 +4,12 @@
#pragma once #pragma once
#include "events/imagepackevent.h" #include "events/imagepackevent.h"
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QCoroTask> #include <QCoroTask>
#include <QObject> #include <QObject>
#include <QPointer> #include <QPointer>
#include <QVector> #include <QVector>
#include <connection.h>
#include <Quotient/connection.h>
class ImagePacksModel; class ImagePacksModel;

View File

@@ -6,8 +6,8 @@
#include "controller.h" #include "controller.h"
#include "neochatroom.h" #include "neochatroom.h"
#include "roommanager.h" #include "roommanager.h"
#include <Quotient/events/roommemberevent.h> #include <events/roommemberevent.h>
#include <Quotient/events/roompowerlevelsevent.h> #include <events/roompowerlevelsevent.h>
#include <KLocalizedString> #include <KLocalizedString>
@@ -436,10 +436,7 @@ QVector<ActionsModel::Action> actions{
Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("<user> is already banned from this room.", "%1 is already banned from this room.", text)); Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("<user> is already banned from this room.", "%1 is already banned from this room.", text));
return QString(); return QString();
} }
auto plEvent = room->currentState().get<RoomPowerLevelsEvent>(); auto plEvent = room->getCurrentState<RoomPowerLevelsEvent>();
if (!plEvent) {
return QString();
}
if (plEvent->ban() > plEvent->powerLevelForUser(room->localUser()->id())) { if (plEvent->ban() > plEvent->powerLevelForUser(room->localUser()->id())) {
Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to ban users from this room.")); Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to ban users from this room."));
return QString(); return QString();
@@ -469,10 +466,7 @@ QVector<ActionsModel::Action> actions{
Q_EMIT room->showMessage(NeoChatRoom::Error, i18nc("'<text>' does not look like a matrix id.", "'%1' does not look like a matrix id.", text)); Q_EMIT room->showMessage(NeoChatRoom::Error, i18nc("'<text>' does not look like a matrix id.", "'%1' does not look like a matrix id.", text));
return QString(); return QString();
} }
auto plEvent = room->currentState().get<RoomPowerLevelsEvent>(); auto plEvent = room->getCurrentState<RoomPowerLevelsEvent>();
if (!plEvent) {
return QString();
}
if (plEvent->ban() > plEvent->powerLevelForUser(room->localUser()->id())) { if (plEvent->ban() > plEvent->powerLevelForUser(room->localUser()->id())) {
Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to unban users from this room.")); Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to unban users from this room."));
return QString(); return QString();
@@ -512,10 +506,7 @@ QVector<ActionsModel::Action> actions{
Q_EMIT room->showMessage(NeoChatRoom::Error, i18nc("<username> is not in this room", "%1 is not in this room.", parts[0])); Q_EMIT room->showMessage(NeoChatRoom::Error, i18nc("<username> is not in this room", "%1 is not in this room.", parts[0]));
return QString(); return QString();
} }
auto plEvent = room->currentState().get<RoomPowerLevelsEvent>(); auto plEvent = room->getCurrentState<RoomPowerLevelsEvent>();
if (!plEvent) {
return QString();
}
auto kick = plEvent->kick(); auto kick = plEvent->kick();
if (plEvent->powerLevelForUser(room->localUser()->id()) < kick) { if (plEvent->powerLevelForUser(room->localUser()->id()) < kick) {
Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to kick users from this room.")); Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to kick users from this room."));

View File

@@ -5,7 +5,7 @@
#include <KLazyLocalizedString> #include <KLazyLocalizedString>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <Quotient/events/roommessageevent.h> #include <events/roommessageevent.h>
class NeoChatRoom; class NeoChatRoom;

View File

@@ -53,54 +53,54 @@ QVariant CompletionModel::data(const QModelIndex &index, int role) const
} }
auto filterIndex = m_filterModel->index(index.row(), 0); auto filterIndex = m_filterModel->index(index.row(), 0);
if (m_autoCompletionType == User) { if (m_autoCompletionType == User) {
if (role == DisplayNameRole) { if (role == Text) {
return m_filterModel->data(filterIndex, UserListModel::DisplayNameRole); return m_filterModel->data(filterIndex, UserListModel::DisplayNameRole);
} }
if (role == SubtitleRole) { if (role == Subtitle) {
return m_filterModel->data(filterIndex, UserListModel::UserIdRole); return m_filterModel->data(filterIndex, UserListModel::UserIdRole);
} }
if (role == IconNameRole) { if (role == Icon) {
return m_filterModel->data(filterIndex, UserListModel::AvatarRole); return m_filterModel->data(filterIndex, UserListModel::AvatarRole);
} }
} }
if (m_autoCompletionType == Command) { if (m_autoCompletionType == Command) {
if (role == DisplayNameRole) { if (role == Text) {
return m_filterModel->data(filterIndex, ActionsModel::Prefix).toString() + QStringLiteral(" ") return m_filterModel->data(filterIndex, ActionsModel::Prefix).toString() + QStringLiteral(" ")
+ m_filterModel->data(filterIndex, ActionsModel::Parameters).toString(); + m_filterModel->data(filterIndex, ActionsModel::Parameters).toString();
} }
if (role == SubtitleRole) { if (role == Subtitle) {
return m_filterModel->data(filterIndex, ActionsModel::Description); return m_filterModel->data(filterIndex, ActionsModel::Description);
} }
if (role == IconNameRole) { if (role == Icon) {
return QStringLiteral("invalid"); return QStringLiteral("invalid");
} }
if (role == ReplacedTextRole) { if (role == ReplacedText) {
return m_filterModel->data(filterIndex, ActionsModel::Prefix); return m_filterModel->data(filterIndex, ActionsModel::Prefix);
} }
} }
if (m_autoCompletionType == Room) { if (m_autoCompletionType == Room) {
if (role == DisplayNameRole) { if (role == Text) {
return m_filterModel->data(filterIndex, RoomListModel::DisplayNameRole); return m_filterModel->data(filterIndex, RoomListModel::DisplayNameRole);
} }
if (role == SubtitleRole) { if (role == Subtitle) {
return m_filterModel->data(filterIndex, RoomListModel::CanonicalAliasRole); return m_filterModel->data(filterIndex, RoomListModel::CanonicalAliasRole);
} }
if (role == IconNameRole) { if (role == Icon) {
return m_filterModel->data(filterIndex, RoomListModel::AvatarRole); return m_filterModel->data(filterIndex, RoomListModel::AvatarRole);
} }
} }
if (m_autoCompletionType == Emoji) { if (m_autoCompletionType == Emoji) {
if (role == DisplayNameRole) { if (role == Text) {
return m_filterModel->data(filterIndex, CustomEmojiModel::DisplayRole); return m_filterModel->data(filterIndex, CustomEmojiModel::DisplayRole);
} }
if (role == IconNameRole) { if (role == Icon) {
return m_filterModel->data(filterIndex, CustomEmojiModel::MxcUrl); return m_filterModel->data(filterIndex, CustomEmojiModel::MxcUrl);
} }
if (role == ReplacedTextRole) { if (role == ReplacedText) {
return m_filterModel->data(filterIndex, CustomEmojiModel::ReplacedTextRole); return m_filterModel->data(filterIndex, CustomEmojiModel::ReplacedTextRole);
} }
if (role == SubtitleRole) { if (role == Subtitle) {
return m_filterModel->data(filterIndex, EmojiModel::DescriptionRole); return m_filterModel->data(filterIndex, EmojiModel::DescriptionRole);
} }
} }
@@ -111,10 +111,10 @@ QVariant CompletionModel::data(const QModelIndex &index, int role) const
QHash<int, QByteArray> CompletionModel::roleNames() const QHash<int, QByteArray> CompletionModel::roleNames() const
{ {
return { return {
{DisplayNameRole, "displayName"}, {Text, "text"},
{SubtitleRole, "subtitle"}, {Subtitle, "subtitle"},
{IconNameRole, "iconName"}, {Icon, "icon"},
{ReplacedTextRole, "replacedText"}, {ReplacedText, "replacedText"},
}; };
} }

View File

@@ -64,14 +64,14 @@ public:
* @brief Defines the model roles. * @brief Defines the model roles.
*/ */
enum Roles { enum Roles {
DisplayNameRole = Qt::DisplayRole, /**< The main text to show. */ Text = Qt::DisplayRole, /**< The main text to show. */
SubtitleRole, /**< The subtitle text to show. */ Subtitle, /**< The subtitle text to show. */
IconNameRole, /**< The icon to show. */ Icon, /**< The icon to show. */
ReplacedTextRole, /**< The text to replace the input text with for the completion. */ ReplacedText, /**< The text to replace the input text with for the completion. */
}; };
Q_ENUM(Roles) Q_ENUM(Roles)
explicit CompletionModel(QObject *parent = nullptr); CompletionModel(QObject *parent = nullptr);
/** /**
* @brief Get the given role value at the given index. * @brief Get the given role value at the given index.

View File

@@ -9,9 +9,10 @@
#include "controller.h" #include "controller.h"
#include "emojimodel.h" #include "emojimodel.h"
#include <Quotient/connection.h> #include <connection.h>
#include <Quotient/csapi/account-data.h> #include <csapi/account-data.h>
#include <Quotient/csapi/content-repo.h> #include <csapi/content-repo.h>
#include <events/eventcontent.h>
using namespace Quotient; using namespace Quotient;

View File

@@ -3,19 +3,23 @@
#include "devicesmodel.h" #include "devicesmodel.h"
#include <csapi/device_management.h>
#include "controller.h" #include "controller.h"
#include <connection.h>
#include <KLocalizedString> #include <user.h>
#include <Quotient/csapi/device_management.h>
#include <Quotient/connection.h>
#include <Quotient/user.h>
using namespace Quotient; using namespace Quotient;
DevicesModel::DevicesModel(QObject *parent) DevicesModel::DevicesModel(QObject *parent)
: QAbstractListModel(parent) : QAbstractListModel(parent)
{ {
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [this]() {
DevicesModel::fetchDevices();
Q_EMIT connectionChanged();
});
fetchDevices();
} }
void DevicesModel::fetchDevices() void DevicesModel::fetchDevices()
@@ -26,7 +30,6 @@ void DevicesModel::fetchDevices()
beginResetModel(); beginResetModel();
m_devices = job->devices(); m_devices = job->devices();
endResetModel(); endResetModel();
Q_EMIT countChanged();
}); });
} }
} }
@@ -37,33 +40,16 @@ QVariant DevicesModel::data(const QModelIndex &index, int role) const
return {}; return {};
} }
const auto &device = m_devices[index.row()];
switch (role) { switch (role) {
case Id: case Id:
return device.deviceId; return m_devices[index.row()].deviceId;
case DisplayName: case DisplayName:
return device.displayName; return m_devices[index.row()].displayName;
case LastIp: case LastIp:
return device.lastSeenIp; return m_devices[index.row()].lastSeenIp;
case LastTimestamp: case LastTimestamp:
if (device.lastSeenTs) { if (m_devices[index.row()].lastSeenTs)
return *device.lastSeenTs; return *m_devices[index.row()].lastSeenTs;
} else {
return false;
}
case Type:
if (device.deviceId == m_connection->deviceId()) {
return This;
}
if (!m_connection->isKnownE2eeCapableDevice(m_connection->userId(), device.deviceId)) {
return Unencrypted;
}
if (m_connection->isVerifiedDevice(m_connection->userId(), device.deviceId)) {
return Verified;
} else {
return Unverified;
}
} }
return {}; return {};
} }
@@ -76,21 +62,11 @@ int DevicesModel::rowCount(const QModelIndex &parent) const
QHash<int, QByteArray> DevicesModel::roleNames() const QHash<int, QByteArray> DevicesModel::roleNames() const
{ {
return { return {{Id, "id"}, {DisplayName, "displayName"}, {LastIp, "lastIp"}, {LastTimestamp, "lastTimestamp"}};
{Id, "id"},
{DisplayName, "displayName"},
{LastIp, "lastIp"},
{LastTimestamp, "lastTimestamp"},
{Type, "type"},
};
} }
void DevicesModel::logout(const QString &deviceId, const QString &password) void DevicesModel::logout(int index, const QString &password)
{ {
int index;
for (index = 0; m_devices[index].deviceId != deviceId; index++)
;
auto job = Controller::instance().activeConnection()->callApi<NeochatDeleteDeviceJob>(m_devices[index].deviceId); auto job = Controller::instance().activeConnection()->callApi<NeochatDeleteDeviceJob>(m_devices[index].deviceId);
connect(job, &BaseJob::result, this, [this, job, password, index] { connect(job, &BaseJob::result, this, [this, job, password, index] {
@@ -98,7 +74,6 @@ void DevicesModel::logout(const QString &deviceId, const QString &password)
beginRemoveRows(QModelIndex(), index, index); beginRemoveRows(QModelIndex(), index, index);
m_devices.remove(index); m_devices.remove(index);
endRemoveRows(); endRemoveRows();
Q_EMIT countChanged();
}; };
if (job->error() != BaseJob::Success) { if (job->error() != BaseJob::Success) {
QJsonObject replyData = job->jsonData(); QJsonObject replyData = job->jsonData();
@@ -116,11 +91,8 @@ void DevicesModel::logout(const QString &deviceId, const QString &password)
}); });
} }
void DevicesModel::setName(const QString &deviceId, const QString &name) void DevicesModel::setName(int index, const QString &name)
{ {
int index;
for (index = 0; m_devices[index].deviceId != deviceId; index++);
auto job = Controller::instance().activeConnection()->callApi<UpdateDeviceJob>(m_devices[index].deviceId, name); auto job = Controller::instance().activeConnection()->callApi<UpdateDeviceJob>(m_devices[index].deviceId, name);
QString oldName = m_devices[index].displayName; QString oldName = m_devices[index].displayName;
beginResetModel(); beginResetModel();
@@ -135,27 +107,7 @@ void DevicesModel::setName(const QString &deviceId, const QString &name)
Connection *DevicesModel::connection() const Connection *DevicesModel::connection() const
{ {
return m_connection; return Controller::instance().activeConnection();
}
void DevicesModel::setConnection(Connection *connection)
{
if (m_connection) {
disconnect(m_connection, nullptr, this, nullptr);
}
m_connection = connection;
Q_EMIT connectionChanged();
fetchDevices();
connect(m_connection, &Connection::sessionVerified, this, [this](const QString &userId, const QString &deviceId) {
Q_UNUSED(deviceId);
if (userId == Controller::instance().activeConnection()->userId()) {
fetchDevices();
}
});
connect(m_connection, &Connection::finishedQueryingKeys, this, [this]() {
fetchDevices();
});
} }
#include "moc_devicesmodel.cpp" #include "moc_devicesmodel.cpp"

View File

@@ -4,9 +4,8 @@
#pragma once #pragma once
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QPointer>
#include <Quotient/csapi/definitions/client_device.h> #include <csapi/definitions/client_device.h>
namespace Quotient namespace Quotient
{ {
@@ -29,7 +28,7 @@ class DevicesModel : public QAbstractListModel
/** /**
* @brief The current connection that the model is getting its devices from. * @brief The current connection that the model is getting its devices from.
*/ */
Q_PROPERTY(Quotient::Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged REQUIRED) Q_PROPERTY(Quotient::Connection *connection READ connection NOTIFY connectionChanged)
public: public:
/** /**
@@ -40,17 +39,10 @@ public:
DisplayName, /**< Display name set by the user for this device. */ DisplayName, /**< Display name set by the user for this device. */
LastIp, /**< The IP address where this device was last seen. */ LastIp, /**< The IP address where this device was last seen. */
LastTimestamp, /**< The timestamp when this devices was last seen. */ LastTimestamp, /**< The timestamp when this devices was last seen. */
Type, /**< The category to sort this device into. */
}; };
Q_ENUM(Roles) Q_ENUM(Roles)
enum DeviceType { DevicesModel(QObject *parent = nullptr);
This,
Verified,
Unverified,
Unencrypted,
};
Q_ENUM(DeviceType);
/** /**
* @brief Get the given role value at the given index. * @brief Get the given role value at the given index.
@@ -74,27 +66,21 @@ public:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
/** /**
* @brief Logout the device with the given id. * @brief Logout the device at the given index.
*/ */
Q_INVOKABLE void logout(const QString &deviceId, const QString &password); Q_INVOKABLE void logout(int index, const QString &password);
/** /**
* @brief Set the display name of the device with the given id. * @brief Set the display name of the device at the given index.
*/ */
Q_INVOKABLE void setName(const QString &deviceId, const QString &name); Q_INVOKABLE void setName(int index, const QString &name);
explicit DevicesModel(QObject *parent = nullptr); Quotient::Connection *connection() const;
[[nodiscard]] Quotient::Connection *connection() const;
void setConnection(Quotient::Connection *connection);
Q_SIGNALS: Q_SIGNALS:
void connectionChanged(); void connectionChanged();
void countChanged();
private: private:
void fetchDevices(); void fetchDevices();
QVector<Quotient::Device> m_devices; QVector<Quotient::Device> m_devices;
QPointer<Quotient::Connection> m_connection;
}; };

View File

@@ -1,30 +0,0 @@
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "devicesproxymodel.h"
#include "devicesmodel.h"
int DevicesProxyModel::type() const
{
return m_type;
}
void DevicesProxyModel::setType(int type)
{
m_type = type;
Q_EMIT typeChanged();
}
bool DevicesProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
Q_UNUSED(source_parent)
return sourceModel()->data(sourceModel()->index(source_row, 0), DevicesModel::Type).toInt() == m_type;
}
DevicesProxyModel::DevicesProxyModel(QObject *parent)
: QSortFilterProxyModel(parent)
, m_type(0)
{
setSortRole(DevicesModel::LastTimestamp);
sort(0, Qt::DescendingOrder);
}
#include "moc_devicesproxymodel.cpp"

View File

@@ -1,25 +0,0 @@
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QSortFilterProxyModel>
class DevicesProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(int type READ type WRITE setType NOTIFY typeChanged);
public:
DevicesProxyModel(QObject *parent = nullptr);
[[nodiscard]] bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
void setType(int type);
[[nodiscard]] int type() const;
Q_SIGNALS:
void typeChanged();
private:
int m_type;
};

View File

@@ -1,112 +0,0 @@
// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include "keywordnotificationrulemodel.h"
#include "controller.h"
#include "notificationsmanager.h"
#include <QDebug>
#include <Quotient/connection.h>
#include <Quotient/converters.h>
#include <Quotient/csapi/definitions/push_ruleset.h>
#include <Quotient/csapi/pushrules.h>
#include <Quotient/jobs/basejob.h>
KeywordNotificationRuleModel::KeywordNotificationRuleModel(QObject *parent)
: QAbstractListModel(parent)
{
if (Controller::instance().activeConnection()) {
controllerConnectionChanged();
}
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &KeywordNotificationRuleModel::controllerConnectionChanged);
}
void KeywordNotificationRuleModel::controllerConnectionChanged()
{
connect(Controller::instance().activeConnection(), &Quotient::Connection::accountDataChanged, this, &KeywordNotificationRuleModel::updateNotificationRules);
updateNotificationRules("m.push_rules");
}
void KeywordNotificationRuleModel::updateNotificationRules(const QString &type)
{
if (type != "m.push_rules") {
return;
}
const QJsonObject ruleDataJson = Controller::instance().activeConnection()->accountDataJson("m.push_rules");
const Quotient::PushRuleset ruleData = Quotient::fromJson<Quotient::PushRuleset>(ruleDataJson["global"].toObject());
const QVector<Quotient::PushRule> contentRules = ruleData.content;
beginResetModel();
m_notificationRules.clear();
for (const auto &i : contentRules) {
if (!m_notificationRules.contains(i.ruleId) && i.ruleId[0] != '.') {
m_notificationRules.append(i.ruleId);
}
}
endResetModel();
}
QVariant KeywordNotificationRuleModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return {};
}
if (index.row() >= m_notificationRules.count()) {
qDebug() << "KeywordNotificationRuleModel, something's wrong: index.row() >= m_notificationRules.count()";
return {};
}
if (role == NameRole) {
return m_notificationRules.at(index.row());
}
return {};
}
int KeywordNotificationRuleModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_notificationRules.count();
}
void KeywordNotificationRuleModel::addKeyword(const QString &keyword)
{
if (m_notificationRules.count() == 0) {
NotificationsManager::instance().initializeKeywordNotificationAction();
}
const QVector<QVariant> actions = NotificationsManager::instance().getKeywordNotificationActions();
auto job = Controller::instance()
.activeConnection()
->callApi<Quotient::SetPushRuleJob>("global", "content", keyword, actions, "", "", QVector<Quotient::PushCondition>(), keyword);
connect(job, &Quotient::BaseJob::success, this, [this, keyword]() {
beginInsertRows(QModelIndex(), m_notificationRules.count(), m_notificationRules.count());
m_notificationRules.append(keyword);
endInsertRows();
});
}
void KeywordNotificationRuleModel::removeKeywordAtIndex(int index)
{
auto job = Controller::instance().activeConnection()->callApi<Quotient::DeletePushRuleJob>("global", "content", m_notificationRules[index]);
connect(job, &Quotient::BaseJob::success, this, [this, index]() {
beginRemoveRows(QModelIndex(), index, index);
m_notificationRules.removeAt(index);
endRemoveRows();
if (m_notificationRules.count() == 0) {
NotificationsManager::instance().deactivateKeywordNotificationAction();
}
});
}
QHash<int, QByteArray> KeywordNotificationRuleModel::roleNames() const
{
return {{NameRole, QByteArrayLiteral("name")}};
}
#include "moc_keywordnotificationrulemodel.cpp"

View File

@@ -1,66 +0,0 @@
// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#pragma once
#include <Quotient/csapi/definitions/push_rule.h>
#include <QAbstractListModel>
/**
* @class KeywordNotificationRuleModel
*
* This class defines the model for managing notification push rule keywords.
*/
class KeywordNotificationRuleModel : public QAbstractListModel
{
Q_OBJECT
public:
/**
* @brief Defines the model roles.
*/
enum EventRoles {
NameRole = Qt::DisplayRole, /**< The push rule keyword. */
};
KeywordNotificationRuleModel(QObject *parent = nullptr);
/**
* @brief Get the given role value at the given index.
*
* @sa QAbstractItemModel::data
*/
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
/**
* @brief Number of rows in the model.
*
* @sa QAbstractItemModel::rowCount
*/
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
/**
* @brief Returns a mapping from Role enum values to role names.
*
* @sa EventRoles, QAbstractItemModel::roleNames()
*/
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
/**
* @brief Add a new keyword to the model.
*/
Q_INVOKABLE void addKeyword(const QString &keyword);
/**
* @brief Remove a keyword from the model.
*/
Q_INVOKABLE void removeKeywordAtIndex(int index);
private Q_SLOTS:
void controllerConnectionChanged();
void updateNotificationRules(const QString &type);
private:
QList<QString> m_notificationRules;
};

View File

@@ -4,7 +4,7 @@
#include "livelocationsmodel.h" #include "livelocationsmodel.h"
#include <Quotient/events/roommessageevent.h> #include <events/roommessageevent.h>
#include <QDebug> #include <QDebug>

View File

@@ -110,7 +110,6 @@ QVariant LocationsModel::data(const QModelIndex &index, int roleName) const
int LocationsModel::rowCount(const QModelIndex &parent) const int LocationsModel::rowCount(const QModelIndex &parent) const
{ {
Q_UNUSED(parent);
return m_locations.size(); return m_locations.size();
} }

View File

@@ -9,7 +9,7 @@
#include "neochatroom.h" #include "neochatroom.h"
#include <Quotient/events/roommessageevent.h> #include <events/roommessageevent.h>
class LocationsModel : public QAbstractListModel class LocationsModel : public QAbstractListModel
{ {

View File

@@ -3,7 +3,7 @@
#include "mediamessagefiltermodel.h" #include "mediamessagefiltermodel.h"
#include "models/messageeventmodel.h" #include "models/messageeventmodel.h"
#include <Quotient/room.h> #include <room.h>
MediaMessageFilterModel::MediaMessageFilterModel(QObject *parent) MediaMessageFilterModel::MediaMessageFilterModel(QObject *parent)
: QSortFilterProxyModel(parent) : QSortFilterProxyModel(parent)

View File

@@ -31,7 +31,7 @@ public:
}; };
Q_ENUM(Roles) Q_ENUM(Roles)
explicit MediaMessageFilterModel(QObject *parent = nullptr); MediaMessageFilterModel(QObject *parent = nullptr);
/** /**
* @brief Custom filter to show only image and video messages. * @brief Custom filter to show only image and video messages.

View File

@@ -5,18 +5,17 @@
#include "messageeventmodel_logging.h" #include "messageeventmodel_logging.h"
#include "neochatconfig.h" #include "neochatconfig.h"
#include <connection.h>
#include <Quotient/connection.h> #include <events/reactionevent.h>
#include <Quotient/csapi/rooms.h> #include <events/redactionevent.h>
#include <Quotient/events/reactionevent.h> #include <events/roomavatarevent.h>
#include <Quotient/events/redactionevent.h> #include <events/roommemberevent.h>
#include <Quotient/events/roomavatarevent.h> #include <events/simplestateevents.h>
#include <Quotient/events/roommemberevent.h> #include <qt_connection_util.h>
#include <Quotient/events/simplestateevents.h> #include <user.h>
#include <Quotient/user.h>
#include "events/pollevent.h" #include "events/pollevent.h"
#include <Quotient/events/stickerevent.h> #include "events/stickerevent.h"
#include <QDebug> #include <QDebug>
#include <QGuiApplication> #include <QGuiApplication>
@@ -228,7 +227,7 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
beginRemoveRows({}, i, i); beginRemoveRows({}, i, i);
}); });
connect(m_currentRoom, &Room::pendingEventDiscarded, this, &MessageEventModel::endRemoveRows); connect(m_currentRoom, &Room::pendingEventDiscarded, this, &MessageEventModel::endRemoveRows);
connect(m_currentRoom, &Room::fullyReadMarkerMoved, this, [this](const QString &fromEventId, const QString &toEventId) { connect(m_currentRoom, &Room::readMarkerMoved, this, [this](const QString &fromEventId, const QString &toEventId) {
Q_UNUSED(fromEventId); Q_UNUSED(fromEventId);
moveReadMarker(toEventId); moveReadMarker(toEventId);
}); });
@@ -609,7 +608,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
return EventStatus::Hidden; return EventStatus::Hidden;
} }
if (evt.isStateEvent() && static_cast<const StateEvent &>(evt).repeatsState()) { if (evt.isStateEvent() && static_cast<const StateEventBase &>(evt).repeatsState()) {
return EventStatus::Hidden; return EventStatus::Hidden;
} }
@@ -1053,7 +1052,7 @@ void MessageEventModel::createReactionModelForEvent(const Quotient::RoomMessageE
return; return;
} }
auto eventId = event->id(); auto eventId = event->id();
const auto &annotations = m_currentRoom->relatedEvents(eventId, EventRelation::AnnotationType); const auto &annotations = m_currentRoom->relatedEvents(eventId, EventRelation::Annotation());
if (annotations.isEmpty()) { if (annotations.isEmpty()) {
if (m_reactionModels.contains(eventId)) { if (m_reactionModels.contains(eventId)) {
delete m_reactionModels[eventId]; delete m_reactionModels[eventId];
@@ -1068,7 +1067,7 @@ void MessageEventModel::createReactionModelForEvent(const Quotient::RoomMessageE
continue; continue;
} }
if (const auto &e = eventCast<const ReactionEvent>(a)) { if (const auto &e = eventCast<const ReactionEvent>(a)) {
reactions[e->key()].append(static_cast<NeoChatUser *>(m_currentRoom->user(e->senderId()))); reactions[e->relation().key].append(static_cast<NeoChatUser *>(m_currentRoom->user(e->senderId())));
} }
} }

View File

@@ -16,7 +16,7 @@ class MessageFilterModel : public QSortFilterProxyModel
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit MessageFilterModel(QObject *parent = nullptr); MessageFilterModel(QObject *parent = nullptr);
/** /**
* @brief Custom filter function to remove hidden messages. * @brief Custom filter function to remove hidden messages.

View File

@@ -3,7 +3,7 @@
#include "publicroomlistmodel.h" #include "publicroomlistmodel.h"
#include <Quotient/connection.h> #include <connection.h>
using namespace Quotient; using namespace Quotient;

View File

@@ -6,7 +6,7 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QObject> #include <QObject>
#include <Quotient/csapi/list_public_rooms.h> #include <csapi/list_public_rooms.h>
namespace Quotient namespace Quotient
{ {
@@ -64,7 +64,7 @@ public:
IsJoinedRole, /**< Whether the local user has joined the room. */ IsJoinedRole, /**< Whether the local user has joined the room. */
}; };
explicit PublicRoomListModel(QObject *parent = nullptr); PublicRoomListModel(QObject *parent = nullptr);
/** /**
* @brief Get the given role value at the given index. * @brief Get the given role value at the given index.

View File

@@ -5,11 +5,12 @@
#include <QDebug> #include <QDebug>
#include <Quotient/connection.h> #include <connection.h>
#include <Quotient/converters.h> #include <converters.h>
#include <Quotient/csapi/definitions/push_ruleset.h> #include <csapi/definitions/push_ruleset.h>
#include <Quotient/csapi/pushrules.h> #include <csapi/pushrules.h>
#include <Quotient/jobs/basejob.h> #include <jobs/basejob.h>
#include <qobjectdefs.h>
#include "controller.h" #include "controller.h"
#include "neochatconfig.h" #include "neochatconfig.h"

View File

@@ -5,7 +5,7 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <Quotient/csapi/definitions/push_rule.h> #include <csapi/definitions/push_rule.h>
#include "notificationsmanager.h" #include "notificationsmanager.h"
@@ -172,7 +172,7 @@ public:
}; };
Q_ENUM(EventRoles) Q_ENUM(EventRoles)
explicit PushRuleModel(QObject *parent = nullptr); PushRuleModel(QObject *parent = nullptr);
[[nodiscard]] PushNotificationAction::Action defaultState() const; [[nodiscard]] PushNotificationAction::Action defaultState() const;
void setDefaultState(PushNotificationAction::Action defaultState); void setDefaultState(PushNotificationAction::Action defaultState);

View File

@@ -36,7 +36,7 @@ public:
HasLocalUser, /**< Whether the local user is in the list of authors. */ HasLocalUser, /**< Whether the local user is in the list of authors. */
}; };
explicit ReactionModel(QObject *parent = nullptr, QList<Reaction> reactions = {}, NeoChatUser *localUser = nullptr); ReactionModel(QObject *parent = nullptr, QList<Reaction> reactions = {}, NeoChatUser *localUser = nullptr);
/** /**
* @brief Get the given role value at the given index. * @brief Get the given role value at the given index.

View File

@@ -8,8 +8,7 @@
#include "neochatroom.h" #include "neochatroom.h"
#include "roommanager.h" #include "roommanager.h"
#include "spacehierarchycache.h" #include "spacehierarchycache.h"
#include "user.h"
#include <Quotient/user.h>
#include <QDebug> #include <QDebug>
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0) #if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
@@ -156,7 +155,7 @@ void RoomListModel::connectRoomSignals(NeoChatRoom *room)
connect(room, &Room::displaynameChanged, this, [this, room] { connect(room, &Room::displaynameChanged, this, [this, room] {
refresh(room, {DisplayNameRole}); refresh(room, {DisplayNameRole});
}); });
connect(room, &Room::unreadStatsChanged, this, [this, room] { connect(room, &Room::unreadMessagesChanged, this, [this, room] {
refresh(room, {NotificationCountRole, HighlightCountRole}); refresh(room, {NotificationCountRole, HighlightCountRole});
}); });
connect(room, &Room::notificationCountChanged, this, [this, room] { connect(room, &Room::notificationCountChanged, this, [this, room] {
@@ -338,7 +337,7 @@ QVariant RoomListModel::data(const QModelIndex &index, int role) const
if (role == AvatarImageRole) { if (role == AvatarImageRole) {
return room->avatar(128); return room->avatar(128);
} }
if (role == RoomIdRole) { if (role == IdRole) {
return room->id(); return room->id();
} }
if (role == IsSpaceRole) { if (role == IsSpaceRole) {
@@ -379,7 +378,7 @@ QHash<int, QByteArray> RoomListModel::roleNames() const
roles[CategoryVisibleRole] = "categoryVisible"; roles[CategoryVisibleRole] = "categoryVisible";
roles[SubtitleTextRole] = "subtitleText"; roles[SubtitleTextRole] = "subtitleText";
roles[IsSpaceRole] = "isSpace"; roles[IsSpaceRole] = "isSpace";
roles[RoomIdRole] = "roomId"; roles[IdRole] = "id";
roles[IsChildSpaceRole] = "isChildSpace"; roles[IsChildSpaceRole] = "isChildSpace";
return roles; return roles;
} }

View File

@@ -3,7 +3,7 @@
#pragma once #pragma once
#include <Quotient/events/roomevent.h> #include <events/roomevent.h>
#include <QAbstractListModel> #include <QAbstractListModel>
@@ -72,7 +72,7 @@ public:
CategoryVisibleRole, /**< If the room's category is visible. */ CategoryVisibleRole, /**< If the room's category is visible. */
SubtitleTextRole, /**< The text to show as the room subtitle. */ SubtitleTextRole, /**< The text to show as the room subtitle. */
AvatarImageRole, /**< The room avatar as an image. */ AvatarImageRole, /**< The room avatar as an image. */
RoomIdRole, /**< The room matrix ID. */ IdRole, /**< The room matrix ID. */
IsSpaceRole, /**< Whether the room is a space. */ IsSpaceRole, /**< Whether the room is a space. */
IsChildSpaceRole, /**< Whether this space is a child of a different space. */ IsChildSpaceRole, /**< Whether this space is a child of a different space. */
}; };

View File

@@ -2,15 +2,12 @@
// SPDX-License-Identifier: LGPL-2.0-or-later // SPDX-License-Identifier: LGPL-2.0-or-later
#include "searchmodel.h" #include "searchmodel.h"
#include "events/stickerevent.h"
#include "messageeventmodel.h" #include "messageeventmodel.h"
#include "neochatroom.h" #include "neochatroom.h"
#include "neochatuser.h" #include "neochatuser.h"
#include <Quotient/events/stickerevent.h>
#include <KLocalizedString> #include <KLocalizedString>
#include <connection.h>
#include <Quotient/connection.h>
using namespace Quotient; using namespace Quotient;

View File

@@ -6,7 +6,7 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QString> #include <QString>
#include <Quotient/csapi/search.h> #include <csapi/search.h>
namespace Quotient namespace Quotient
{ {

View File

@@ -5,7 +5,7 @@
#include "controller.h" #include "controller.h"
#include <Quotient/connection.h> #include <connection.h>
#include <QDebug> #include <QDebug>

View File

@@ -3,7 +3,7 @@
#pragma once #pragma once
#include <Quotient/csapi/list_public_rooms.h> #include <csapi/list_public_rooms.h>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QPointer> #include <QPointer>

View File

@@ -87,8 +87,7 @@ bool SortFilterRoomListModel::filterAcceptsRow(int source_row, const QModelIndex
return acceptRoom; return acceptRoom;
} else { } else {
const auto &rooms = SpaceHierarchyCache::instance().getRoomListForSpace(m_activeSpaceId, false); const auto &rooms = SpaceHierarchyCache::instance().getRoomListForSpace(m_activeSpaceId, false);
return std::find(rooms.begin(), rooms.end(), sourceModel()->data(sourceModel()->index(source_row, 0), RoomListModel::RoomIdRole).toString()) return std::find(rooms.begin(), rooms.end(), sourceModel()->data(sourceModel()->index(source_row, 0), RoomListModel::IdRole).toString()) != rooms.end()
!= rooms.end()
&& acceptRoom; && acceptRoom;
} }
} }

View File

@@ -8,7 +8,7 @@
SortFilterSpaceListModel::SortFilterSpaceListModel(QObject *parent) SortFilterSpaceListModel::SortFilterSpaceListModel(QObject *parent)
: QSortFilterProxyModel{parent} : QSortFilterProxyModel{parent}
{ {
setSortRole(RoomListModel::RoomIdRole); setSortRole(RoomListModel::IdRole);
sort(0); sort(0);
invalidateFilter(); invalidateFilter();
connect(this, &QAbstractProxyModel::sourceModelChanged, this, [this]() { connect(this, &QAbstractProxyModel::sourceModelChanged, this, [this]() {
@@ -33,8 +33,8 @@ bool SortFilterSpaceListModel::filterAcceptsRow(int source_row, const QModelInde
bool SortFilterSpaceListModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const bool SortFilterSpaceListModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{ {
const auto idLeft = sourceModel()->data(source_left, RoomListModel::RoomIdRole).toString(); const auto idLeft = sourceModel()->data(source_left, RoomListModel::IdRole).toString();
const auto idRight = sourceModel()->data(source_right, RoomListModel::RoomIdRole).toString(); const auto idRight = sourceModel()->data(source_right, RoomListModel::IdRole).toString();
return idLeft < idRight; return idLeft < idRight;
} }

View File

@@ -3,8 +3,8 @@
#include "userdirectorylistmodel.h" #include "userdirectorylistmodel.h"
#include <Quotient/connection.h> #include <connection.h>
#include <Quotient/room.h> #include <room.h>
using namespace Quotient; using namespace Quotient;
@@ -144,7 +144,7 @@ QVariant UserDirectoryListModel::data(const QModelIndex &index, int role) const
auto avatarUrl = user.avatarUrl; auto avatarUrl = user.avatarUrl;
if (avatarUrl.isEmpty()) { if (avatarUrl.isEmpty()) {
return QString(); return "";
} }
return avatarUrl.url().remove(0, 6); return avatarUrl.url().remove(0, 6);
} }
@@ -153,7 +153,7 @@ QVariant UserDirectoryListModel::data(const QModelIndex &index, int role) const
} }
if (role == DirectChatsRole) { if (role == DirectChatsRole) {
if (!m_connection) { if (!m_connection) {
return QStringList(); return {};
}; };
auto userObj = m_connection->user(user.userId); auto userObj = m_connection->user(user.userId);
@@ -165,8 +165,6 @@ QVariant UserDirectoryListModel::data(const QModelIndex &index, int role) const
return QVariant::fromValue(directChatsForUser); return QVariant::fromValue(directChatsForUser);
} }
} }
return QStringList();
} }
return {}; return {};

View File

@@ -6,7 +6,7 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QObject> #include <QObject>
#include <Quotient/csapi/users.h> #include <csapi/users.h>
namespace Quotient namespace Quotient
{ {

View File

@@ -3,8 +3,8 @@
#include "userlistmodel.h" #include "userlistmodel.h"
#include <Quotient/connection.h> #include <connection.h>
#include <Quotient/events/roompowerlevelsevent.h> #include <events/roompowerlevelsevent.h>
#include "neochatroom.h" #include "neochatroom.h"
@@ -78,11 +78,8 @@ QVariant UserListModel::data(const QModelIndex &index, int role) const
return QVariant::fromValue(user); return QVariant::fromValue(user);
} }
if (role == PowerLevelRole) { if (role == PowerLevelRole) {
auto plEvent = m_currentRoom->currentState().get<RoomPowerLevelsEvent>(); auto pl = m_currentRoom->getCurrentState<RoomPowerLevelsEvent>();
if (!plEvent) { return pl->powerLevelForUser(user->id());
return 0;
}
return plEvent->powerLevelForUser(user->id());
} }
if (role == PowerLevelStringRole) { if (role == PowerLevelStringRole) {
auto pl = m_currentRoom->currentState().get<RoomPowerLevelsEvent>(); auto pl = m_currentRoom->currentState().get<RoomPowerLevelsEvent>();

View File

@@ -3,8 +3,6 @@
#pragma once #pragma once
#include <Quotient/room.h>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QObject> #include <QObject>
#include <QPointer> #include <QPointer>

View File

@@ -33,6 +33,7 @@ Name[ro]=NeoChat
Name[ru]=NeoChat Name[ru]=NeoChat
Name[sk]=NeoChat Name[sk]=NeoChat
Name[sl]=NeoChat Name[sl]=NeoChat
Name[sv]=NeoChat
Name[ta]=நியோச்சாட் Name[ta]=நியோச்சாட்
Name[tr]=NeoChat Name[tr]=NeoChat
Name[uk]=NeoChat Name[uk]=NeoChat
@@ -72,6 +73,7 @@ Comment[ro]=Client pentru Matrix, protocolul de comunicare descentralizată
Comment[ru]=Клиент для Matrix — децентрализованного коммуникационного протокола Comment[ru]=Клиент для Matrix — децентрализованного коммуникационного протокола
Comment[sk]=Klient pre matrix, decentralizovaný komunikačný protokol Comment[sk]=Klient pre matrix, decentralizovaný komunikačný protokol
Comment[sl]=Odjemalec za decentralizirani komunikacijski protokol matrix Comment[sl]=Odjemalec za decentralizirani komunikacijski protokol matrix
Comment[sv]=En klient för matrix, det decentraliserade kommunikationsprotokollet
Comment[tr]=Merkezi olmayan iletişim protokolü Matrix için bir istemci Comment[tr]=Merkezi olmayan iletişim protokolü Matrix için bir istemci
Comment[uk]=Клієнт matrix, децентралізованого протоколу обміну даними Comment[uk]=Клієнт matrix, децентралізованого протоколу обміну даними
Comment[x-test]=xxA client for matrix, the decentralized communication protocolxx Comment[x-test]=xxA client for matrix, the decentralized communication protocolxx
@@ -112,6 +114,7 @@ Name[ro]=Mesaj nou
Name[ru]=Новое сообщение Name[ru]=Новое сообщение
Name[sk]=Nová správa Name[sk]=Nová správa
Name[sl]=Novo sporočilo Name[sl]=Novo sporočilo
Name[sv]=Nytt meddelande
Name[ta]=புதிய செய்தி Name[ta]=புதிய செய்தி
Name[tr]=Yeni ileti Name[tr]=Yeni ileti
Name[uk]=Нове повідомлення Name[uk]=Нове повідомлення
@@ -149,6 +152,7 @@ Comment[ro]=Este un mesaj nou
Comment[ru]=Доступно новое сообщение Comment[ru]=Доступно новое сообщение
Comment[sk]=Je nová správa Comment[sk]=Je nová správa
Comment[sl]=Prišlo je novo sporočilo Comment[sl]=Prišlo je novo sporočilo
Comment[sv]=Det finns ett nytt meddelande
Comment[ta]=ஒரு புதிய செய்தி உள்ளது Comment[ta]=ஒரு புதிய செய்தி உள்ளது
Comment[tr]=Yeni bir ileti var Comment[tr]=Yeni bir ileti var
Comment[uk]=Надійшло нове повідомлення Comment[uk]=Надійшло нове повідомлення
@@ -186,6 +190,7 @@ Name[pt]=Novo Convite
Name[pt_BR]=Novo convite Name[pt_BR]=Novo convite
Name[ru]=Новое приглашение Name[ru]=Новое приглашение
Name[sl]=Novo povabilo Name[sl]=Novo povabilo
Name[sv]=Ny inbjudan
Name[ta]=புதிய அழைப்பிதழ் Name[ta]=புதிய அழைப்பிதழ்
Name[tr]=Yeni Davet Name[tr]=Yeni Davet
Name[uk]=Нове запрошення Name[uk]=Нове запрошення
@@ -219,6 +224,7 @@ Comment[pt]=Existe um novo convite para uma sala
Comment[pt_BR]=Existe um novo convite para uma sala Comment[pt_BR]=Existe um novo convite para uma sala
Comment[ru]=Доступно новое приглашение в комнату Comment[ru]=Доступно новое приглашение в комнату
Comment[sl]=Tam je novo povabilo v sobo Comment[sl]=Tam je novo povabilo v sobo
Comment[sv]=Det finns en ny inbjudan till ett rum
Comment[ta]=ஓர் அரங்கிற்கான புதிய அழைப்பிதழ் உள்ளது Comment[ta]=ஓர் அரங்கிற்கான புதிய அழைப்பிதழ் உள்ளது
Comment[tr]=Bir odaya yeni bir davetiye var Comment[tr]=Bir odaya yeni bir davetiye var
Comment[uk]=У кімнаті нове запрошення Comment[uk]=У кімнаті нове запрошення

View File

@@ -12,33 +12,35 @@
#include <QMediaMetaData> #include <QMediaMetaData>
#include <QMediaPlayer> #include <QMediaPlayer>
#include <Quotient/jobs/basejob.h> #include <jobs/basejob.h>
#include <qcoro/qcorosignal.h> #include <qcoro/qcorosignal.h>
#include <Quotient/connection.h> #include <connection.h>
#include <Quotient/csapi/account-data.h> #include <csapi/account-data.h>
#include <Quotient/csapi/directory.h> #include <csapi/directory.h>
#include <Quotient/csapi/pushrules.h> #include <csapi/event_context.h>
#include <Quotient/csapi/redaction.h> #include <csapi/pushrules.h>
#include <Quotient/csapi/report_content.h> #include <csapi/redaction.h>
#include <Quotient/csapi/room_state.h> #include <csapi/report_content.h>
#include <Quotient/csapi/rooms.h> #include <csapi/room_state.h>
#include <Quotient/csapi/typing.h> #include <csapi/rooms.h>
#include <Quotient/events/encryptionevent.h> #include <csapi/typing.h>
#include <Quotient/events/reactionevent.h> #include <events/encryptionevent.h>
#include <Quotient/events/redactionevent.h> #include <events/reactionevent.h>
#include <Quotient/events/roomavatarevent.h> #include <events/redactionevent.h>
#include <Quotient/events/roomcanonicalaliasevent.h> #include <events/roomavatarevent.h>
#include <Quotient/events/roommemberevent.h> #include <events/roomcanonicalaliasevent.h>
#include <Quotient/events/roompowerlevelsevent.h> #include <events/roommemberevent.h>
#include <Quotient/events/simplestateevents.h> #include <events/roompowerlevelsevent.h>
#include <Quotient/events/stickerevent.h> #include <events/simplestateevents.h>
#include <Quotient/jobs/downloadfilejob.h> #include <jobs/downloadfilejob.h>
#include <Quotient/qt_connection_util.h>
#include <qt_connection_util.h>
#include "controller.h" #include "controller.h"
#include "events/joinrulesevent.h" #include "events/joinrulesevent.h"
#include "events/pollevent.h" #include "events/pollevent.h"
#include "events/stickerevent.h"
#include "filetransferpseudojob.h" #include "filetransferpseudojob.h"
#include "neochatconfig.h" #include "neochatconfig.h"
#include "notificationsmanager.h" #include "notificationsmanager.h"
@@ -97,9 +99,7 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
if (this->joinState() != JoinState::Invite) { if (this->joinState() != JoinState::Invite) {
return; return;
} }
auto roomMemberEvent = currentState().get<RoomMemberEvent>(localUser()->id()); const QString senderId = getCurrentState<RoomMemberEvent>(localUser()->id())->senderId();
Q_ASSERT(roomMemberEvent);
const QString senderId = roomMemberEvent->senderId();
QImage avatar_image; QImage avatar_image;
if (!user(senderId)->avatarUrl(this).isEmpty()) { if (!user(senderId)->avatarUrl(this).isEmpty()) {
avatar_image = user(senderId)->avatar(128, this); avatar_image = user(senderId)->avatar(128, this);
@@ -273,7 +273,7 @@ const RoomEvent *NeoChatRoom::lastEvent() const
continue; continue;
} }
} }
if (event->isStateEvent() && static_cast<const StateEvent &>(*event).repeatsState()) { if (event->isStateEvent() && static_cast<const StateEventBase &>(*event).repeatsState()) {
continue; continue;
} }
@@ -340,7 +340,7 @@ bool NeoChatRoom::lastEventIsSpoiler() const
QString NeoChatRoom::lastEventToString(Qt::TextFormat format, bool stripNewlines) const QString NeoChatRoom::lastEventToString(Qt::TextFormat format, bool stripNewlines) const
{ {
if (auto event = lastEvent()) { if (auto event = lastEvent()) {
return safeMemberName(event->senderId()) + (event->isStateEvent() ? QLatin1String(" ") : QLatin1String(": ")) return roomMembername(event->senderId()) + (event->isStateEvent() ? QLatin1String(" ") : QLatin1String(": "))
+ eventToString(*event, format, stripNewlines); + eventToString(*event, format, stripNewlines);
} }
return {}; return {};
@@ -359,7 +359,7 @@ void NeoChatRoom::checkForHighlights(const Quotient::TimelineItem &ti)
} }
if (auto *e = ti.viewAs<RoomMessageEvent>()) { if (auto *e = ti.viewAs<RoomMessageEvent>()) {
const auto &text = e->plainBody(); const auto &text = e->plainBody();
if (text.contains(localUserId) || text.contains(safeMemberName(localUserId))) { if (text.contains(localUserId) || text.contains(roomMembername(localUserId))) {
highlights.insert(e); highlights.insert(e);
} }
} }
@@ -382,7 +382,7 @@ void NeoChatRoom::onAddHistoricalTimelineEvents(rev_iter_t from)
void NeoChatRoom::onRedaction(const RoomEvent &prevEvent, const RoomEvent & /*after*/) void NeoChatRoom::onRedaction(const RoomEvent &prevEvent, const RoomEvent & /*after*/)
{ {
if (const auto &e = eventCast<const ReactionEvent>(&prevEvent)) { if (const auto &e = eventCast<const ReactionEvent>(&prevEvent)) {
if (auto relatedEventId = e->eventId(); !relatedEventId.isEmpty()) { if (auto relatedEventId = e->relation().eventId; !relatedEventId.isEmpty()) {
Q_EMIT updatedEvent(relatedEventId); Q_EMIT updatedEvent(relatedEventId);
} }
} }
@@ -531,7 +531,7 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
[this, prettyPrint](const RoomMemberEvent &e) { [this, prettyPrint](const RoomMemberEvent &e) {
// FIXME: Rewind to the name that was at the time of this event // FIXME: Rewind to the name that was at the time of this event
auto subjectName = this->htmlSafeMemberName(e.userId()); auto subjectName = this->htmlSafeMemberName(e.userId());
if (e.membership() == Membership::Leave) { if (e.membership() == MembershipType::Leave) {
if (e.prevContent() && e.prevContent()->displayName) { if (e.prevContent() && e.prevContent()->displayName) {
subjectName = sanitized(*e.prevContent()->displayName).toHtmlEscaped(); subjectName = sanitized(*e.prevContent()->displayName).toHtmlEscaped();
} }
@@ -544,7 +544,7 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
// The below code assumes senderName output in AuthorRole // The below code assumes senderName output in AuthorRole
switch (e.membership()) { switch (e.membership()) {
case Membership::Invite: case MembershipType::Invite:
if (e.repeatsState()) { if (e.repeatsState()) {
auto text = i18n("reinvited %1 to the room", subjectName); auto text = i18n("reinvited %1 to the room", subjectName);
if (!e.reason().isEmpty()) { if (!e.reason().isEmpty()) {
@@ -553,13 +553,13 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
return text; return text;
} }
Q_FALLTHROUGH(); Q_FALLTHROUGH();
case Membership::Join: { case MembershipType::Join: {
QString text{}; QString text{};
// Part 1: invites and joins // Part 1: invites and joins
if (e.repeatsState()) { if (e.repeatsState()) {
text = i18n("joined the room (repeated)"); text = i18n("joined the room (repeated)");
} else if (e.changesMembership()) { } else if (e.changesMembership()) {
text = e.membership() == Membership::Invite ? i18n("invited %1 to the room", subjectName) : i18n("joined the room"); text = e.membership() == MembershipType::Invite ? i18n("invited %1 to the room", subjectName) : i18n("joined the room");
} }
if (!text.isEmpty()) { if (!text.isEmpty()) {
if (!e.reason().isEmpty()) { if (!e.reason().isEmpty()) {
@@ -569,17 +569,17 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
} }
// Part 2: profile changes of joined members // Part 2: profile changes of joined members
if (e.isRename()) { if (e.isRename()) {
if (!e.newDisplayName()) { if (e.displayName().isEmpty()) {
text = i18nc("their refers to a singular user", "cleared their display name"); text = i18nc("their refers to a singular user", "cleared their display name");
} else { } else {
text = i18nc("their refers to a singular user", "changed their display name to %1", e.newDisplayName()->toHtmlEscaped()); text = i18nc("their refers to a singular user", "changed their display name to %1", e.displayName().toHtmlEscaped());
} }
} }
if (e.isAvatarUpdate()) { if (e.isAvatarUpdate()) {
if (!text.isEmpty()) { if (!text.isEmpty()) {
text += i18n(" and "); text += i18n(" and ");
} }
if (!e.newAvatarUrl()) { if (e.avatarUrl().isEmpty()) {
text += i18nc("their refers to a singular user", "cleared their avatar"); text += i18nc("their refers to a singular user", "cleared their avatar");
} else if (!e.prevContent()->avatarUrl) { } else if (!e.prevContent()->avatarUrl) {
text += i18n("set an avatar"); text += i18n("set an avatar");
@@ -592,18 +592,18 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
} }
return text; return text;
} }
case Membership::Leave: case MembershipType::Leave:
if (e.prevContent() && e.prevContent()->membership == Membership::Invite) { if (e.prevContent() && e.prevContent()->membership == MembershipType::Invite) {
return (e.senderId() != e.userId()) ? i18n("withdrew %1's invitation", subjectName) : i18n("rejected the invitation"); return (e.senderId() != e.userId()) ? i18n("withdrew %1's invitation", subjectName) : i18n("rejected the invitation");
} }
if (e.prevContent() && e.prevContent()->membership == Membership::Ban) { if (e.prevContent() && e.prevContent()->membership == MembershipType::Ban) {
return (e.senderId() != e.userId()) ? i18n("unbanned %1", subjectName) : i18n("self-unbanned"); return (e.senderId() != e.userId()) ? i18n("unbanned %1", subjectName) : i18n("self-unbanned");
} }
return (e.senderId() != e.userId()) return (e.senderId() != e.userId())
? i18n("has put %1 out of the room: %2", subjectName, e.contentJson()["reason"_ls].toString().toHtmlEscaped()) ? i18n("has put %1 out of the room: %2", subjectName, e.contentJson()["reason"_ls].toString().toHtmlEscaped())
: i18n("left the room"); : i18n("left the room");
case Membership::Ban: case MembershipType::Ban:
if (e.senderId() != e.userId()) { if (e.senderId() != e.userId()) {
if (e.reason().isEmpty()) { if (e.reason().isEmpty()) {
return i18n("banned %1 from the room", subjectName); return i18n("banned %1 from the room", subjectName);
@@ -613,7 +613,7 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
} else { } else {
return i18n("self-banned from the room"); return i18n("self-banned from the room");
} }
case Membership::Knock: { case MembershipType::Knock: {
QString reason(e.contentJson()["reason"_ls].toString().toHtmlEscaped()); QString reason(e.contentJson()["reason"_ls].toString().toHtmlEscaped());
return reason.isEmpty() ? i18n("requested an invite") : i18n("requested an invite with reason: %1", reason); return reason.isEmpty() ? i18n("requested an invite") : i18n("requested an invite with reason: %1", reason);
} }
@@ -647,7 +647,7 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
[](const RoomPowerLevelsEvent &) { [](const RoomPowerLevelsEvent &) {
return i18nc("'power level' means permission level", "changed the power levels for this room"); return i18nc("'power level' means permission level", "changed the power levels for this room");
}, },
[](const StateEvent &e) { [](const StateEventBase &e) {
if (e.matrixType() == QLatin1String("m.room.server_acl")) { if (e.matrixType() == QLatin1String("m.room.server_acl")) {
return i18n("changed the server access control lists for this room"); return i18n("changed the server access control lists for this room");
} }
@@ -686,25 +686,25 @@ QString NeoChatRoom::eventToGenericString(const RoomEvent &evt) const
}, },
[](const RoomMemberEvent &e) { [](const RoomMemberEvent &e) {
switch (e.membership()) { switch (e.membership()) {
case Membership::Invite: case MembershipType::Invite:
if (e.repeatsState()) { if (e.repeatsState()) {
return i18n("reinvited someone to the room"); return i18n("reinvited someone to the room");
} }
Q_FALLTHROUGH(); Q_FALLTHROUGH();
case Membership::Join: { case MembershipType::Join: {
QString text{}; QString text{};
// Part 1: invites and joins // Part 1: invites and joins
if (e.repeatsState()) { if (e.repeatsState()) {
text = i18n("joined the room (repeated)"); text = i18n("joined the room (repeated)");
} else if (e.changesMembership()) { } else if (e.changesMembership()) {
text = e.membership() == Membership::Invite ? i18n("invited someone to the room") : i18n("joined the room"); text = e.membership() == MembershipType::Invite ? i18n("invited someone to the room") : i18n("joined the room");
} }
if (!text.isEmpty()) { if (!text.isEmpty()) {
return text; return text;
} }
// Part 2: profile changes of joined members // Part 2: profile changes of joined members
if (e.isRename()) { if (e.isRename()) {
if (!e.newDisplayName()) { if (e.displayName().isEmpty()) {
text = i18nc("their refers to a singular user", "cleared their display name"); text = i18nc("their refers to a singular user", "cleared their display name");
} else { } else {
text = i18nc("their refers to a singular user", "changed their display name"); text = i18nc("their refers to a singular user", "changed their display name");
@@ -714,7 +714,7 @@ QString NeoChatRoom::eventToGenericString(const RoomEvent &evt) const
if (!text.isEmpty()) { if (!text.isEmpty()) {
text += i18n(" and "); text += i18n(" and ");
} }
if (!e.newAvatarUrl()) { if (e.avatarUrl().isEmpty()) {
text += i18nc("their refers to a singular user", "cleared their avatar"); text += i18nc("their refers to a singular user", "cleared their avatar");
} else if (!e.prevContent()->avatarUrl) { } else if (!e.prevContent()->avatarUrl) {
text += i18n("set an avatar"); text += i18n("set an avatar");
@@ -727,22 +727,22 @@ QString NeoChatRoom::eventToGenericString(const RoomEvent &evt) const
} }
return text; return text;
} }
case Membership::Leave: case MembershipType::Leave:
if (e.prevContent() && e.prevContent()->membership == Membership::Invite) { if (e.prevContent() && e.prevContent()->membership == MembershipType::Invite) {
return (e.senderId() != e.userId()) ? i18n("withdrew a user's invitation") : i18n("rejected the invitation"); return (e.senderId() != e.userId()) ? i18n("withdrew a user's invitation") : i18n("rejected the invitation");
} }
if (e.prevContent() && e.prevContent()->membership == Membership::Ban) { if (e.prevContent() && e.prevContent()->membership == MembershipType::Ban) {
return (e.senderId() != e.userId()) ? i18n("unbanned a user") : i18n("self-unbanned"); return (e.senderId() != e.userId()) ? i18n("unbanned a user") : i18n("self-unbanned");
} }
return (e.senderId() != e.userId()) ? i18n("put a user out of the room") : i18n("left the room"); return (e.senderId() != e.userId()) ? i18n("put a user out of the room") : i18n("left the room");
case Membership::Ban: case MembershipType::Ban:
if (e.senderId() != e.userId()) { if (e.senderId() != e.userId()) {
return i18n("banned a user from the room"); return i18n("banned a user from the room");
} else { } else {
return i18n("self-banned from the room"); return i18n("self-banned from the room");
} }
case Membership::Knock: { case MembershipType::Knock: {
return i18n("requested an invite"); return i18n("requested an invite");
} }
default:; default:;
@@ -770,7 +770,7 @@ QString NeoChatRoom::eventToGenericString(const RoomEvent &evt) const
[](const RoomPowerLevelsEvent &) { [](const RoomPowerLevelsEvent &) {
return i18nc("'power level' means permission level", "changed the power levels for this room"); return i18nc("'power level' means permission level", "changed the power levels for this room");
}, },
[](const StateEvent &e) { [](const StateEventBase &e) {
if (e.matrixType() == QLatin1String("m.room.server_acl")) { if (e.matrixType() == QLatin1String("m.room.server_acl")) {
return i18n("changed the server access control lists for this room"); return i18n("changed the server access control lists for this room");
} }
@@ -906,11 +906,11 @@ void NeoChatRoom::toggleReaction(const QString &eventId, const QString &reaction
QStringList redactEventIds; // What if there are multiple reaction events? QStringList redactEventIds; // What if there are multiple reaction events?
const auto &annotations = relatedEvents(evt, EventRelation::AnnotationType); const auto &annotations = relatedEvents(evt, EventRelation::Annotation());
if (!annotations.isEmpty()) { if (!annotations.isEmpty()) {
for (const auto &a : annotations) { for (const auto &a : annotations) {
if (auto e = eventCast<const ReactionEvent>(a)) { if (auto e = eventCast<const ReactionEvent>(a)) {
if (e->key() != reaction) { if (e->relation().key != reaction) {
continue; continue;
} }
@@ -938,10 +938,7 @@ bool NeoChatRoom::containsUser(const QString &userID) const
bool NeoChatRoom::canSendEvent(const QString &eventType) const bool NeoChatRoom::canSendEvent(const QString &eventType) const
{ {
auto plEvent = currentState().get<RoomPowerLevelsEvent>(); auto plEvent = getCurrentState<RoomPowerLevelsEvent>();
if (!plEvent) {
return false;
}
auto pl = plEvent->powerLevelForEvent(eventType); auto pl = plEvent->powerLevelForEvent(eventType);
auto currentPl = plEvent->powerLevelForUser(localUser()->id()); auto currentPl = plEvent->powerLevelForUser(localUser()->id());
@@ -950,10 +947,7 @@ bool NeoChatRoom::canSendEvent(const QString &eventType) const
bool NeoChatRoom::canSendState(const QString &eventType) const bool NeoChatRoom::canSendState(const QString &eventType) const
{ {
auto plEvent = currentState().get<RoomPowerLevelsEvent>(); auto plEvent = getCurrentState<RoomPowerLevelsEvent>();
if (!plEvent) {
return false;
}
auto pl = plEvent->powerLevelForState(eventType); auto pl = plEvent->powerLevelForState(eventType);
auto currentPl = plEvent->powerLevelForUser(localUser()->id()); auto currentPl = plEvent->powerLevelForUser(localUser()->id());
@@ -973,11 +967,7 @@ bool NeoChatRoom::isInvite() const
bool NeoChatRoom::isUserBanned(const QString &user) const bool NeoChatRoom::isUserBanned(const QString &user) const
{ {
auto roomMemberEvent = currentState().get<RoomMemberEvent>(user); return getCurrentState<RoomMemberEvent>(user)->membership() == MembershipType::Ban;
if (!roomMemberEvent) {
return false;
}
return roomMemberEvent->membership() == Membership::Ban;
} }
QString NeoChatRoom::htmlSafeDisplayName() const QString NeoChatRoom::htmlSafeDisplayName() const
@@ -992,11 +982,7 @@ void NeoChatRoom::deleteMessagesByUser(const QString &user, const QString &reaso
QString NeoChatRoom::joinRule() const QString NeoChatRoom::joinRule() const
{ {
auto joinRulesEvent = currentState().get<JoinRulesEvent>(); return getCurrentState<JoinRulesEvent>()->joinRule();
if (!joinRulesEvent) {
return {};
}
return joinRulesEvent->joinRule();
} }
void NeoChatRoom::setJoinRule(const QString &joinRule) void NeoChatRoom::setJoinRule(const QString &joinRule)
@@ -1130,10 +1116,7 @@ void NeoChatRoom::setUserPowerLevel(const QString &userID, const int &powerLevel
int NeoChatRoom::getUserPowerLevel(const QString &userId) const int NeoChatRoom::getUserPowerLevel(const QString &userId) const
{ {
auto powerLevelEvent = currentState().get<RoomPowerLevelsEvent>(); auto powerLevelEvent = getCurrentState<RoomPowerLevelsEvent>();
if (!powerLevelEvent) {
return 0;
}
return powerLevelEvent->powerLevelForUser(userId); return powerLevelEvent->powerLevelForUser(userId);
} }
@@ -1941,7 +1924,7 @@ QByteArray NeoChatRoom::roomAcountDataJson(const QString &eventType)
QUrl NeoChatRoom::avatarForMember(NeoChatUser *user) const QUrl NeoChatRoom::avatarForMember(NeoChatUser *user) const
{ {
const auto &url = memberAvatarUrl(user->id()); const auto &url = memberAvatarUrl(user->id());
if (url.isEmpty() || url.scheme() != "mxc"_ls) { if (url.isEmpty()) {
return {}; return {};
} }
auto avatar = connection()->makeMediaUrl(url); auto avatar = connection()->makeMediaUrl(url);

View File

@@ -3,7 +3,8 @@
#pragma once #pragma once
#include <Quotient/room.h> #include <qobjectdefs.h>
#include <room.h>
#include <QCache> #include <QCache>
#include <QObject> #include <QObject>

View File

@@ -7,7 +7,7 @@
#include <QJsonObject> #include <QJsonObject>
#include <QPalette> #include <QPalette>
#include <Quotient/connection.h> #include <connection.h>
using namespace Quotient; using namespace Quotient;

View File

@@ -5,7 +5,7 @@
#include <QObject> #include <QObject>
#include <Quotient/user.h> #include <user.h>
/** /**
* @class NeoChatUser * @class NeoChatUser
@@ -23,7 +23,7 @@ class NeoChatUser : public Quotient::User
*/ */
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
public: public:
explicit NeoChatUser(QString userId, Quotient::Connection *connection); NeoChatUser(QString userId, Quotient::Connection *connection);
public Q_SLOTS: public Q_SLOTS:
QColor color(); QColor color();

View File

@@ -11,11 +11,11 @@
#include <KNotification> #include <KNotification>
#include <KNotificationReplyAction> #include <KNotificationReplyAction>
#include <QPainter> #include <accountregistry.h>
#include <Quotient/accountregistry.h>
#include <Quotient/connection.h> #include <connection.h>
#include <Quotient/csapi/pushrules.h> #include <csapi/pushrules.h>
#include <Quotient/user.h> #include <user.h>
#include "controller.h" #include "controller.h"
#include "neochatconfig.h" #include "neochatconfig.h"
@@ -204,7 +204,7 @@ void NotificationsManager::postNotification(NeoChatRoom *room,
} }
notification->setText(notification->text() + '\n' + entry); notification->setText(notification->text() + '\n' + entry);
notification->setPixmap(createNotificationImage(icon, room)); notification->setPixmap(QPixmap::fromImage(icon));
notification->setDefaultAction(i18n("Open NeoChat in this room")); notification->setDefaultAction(i18n("Open NeoChat in this room"));
connect(notification, &KNotification::defaultActivated, this, [notification, room]() { connect(notification, &KNotification::defaultActivated, this, [notification, room]() {
@@ -213,7 +213,7 @@ void NotificationsManager::postNotification(NeoChatRoom *room,
return; return;
} }
if (room->localUser()->id() != Controller::instance().activeConnection()->userId()) { if (room->localUser()->id() != Controller::instance().activeConnection()->userId()) {
Controller::instance().setActiveConnection(Controller::instance().accounts().get(room->localUser()->id())); Controller::instance().setActiveConnection(Accounts.get(room->localUser()->id()));
} }
RoomManager::instance().enterRoom(room); RoomManager::instance().enterRoom(room);
}); });
@@ -240,7 +240,7 @@ void NotificationsManager::postInviteNotification(NeoChatRoom *room, const QStri
KNotification *notification = new KNotification("invite"); KNotification *notification = new KNotification("invite");
notification->setText(i18n("%1 invited you to a room", sender)); notification->setText(i18n("%1 invited you to a room", sender));
notification->setTitle(title); notification->setTitle(title);
notification->setPixmap(createNotificationImage(icon, nullptr)); notification->setPixmap(img);
notification->setFlags(KNotification::Persistent); notification->setFlags(KNotification::Persistent);
notification->setDefaultAction(i18n("Open this invitation in NeoChat")); notification->setDefaultAction(i18n("Open this invitation in NeoChat"));
connect(notification, &KNotification::defaultActivated, this, [notification, room]() { connect(notification, &KNotification::defaultActivated, this, [notification, room]() {
@@ -283,33 +283,4 @@ void NotificationsManager::clearInvitationNotification(const QString &roomId)
} }
} }
QPixmap NotificationsManager::createNotificationImage(const QImage &icon, NeoChatRoom *room)
{
// Handle avatars that are lopsided in one dimension
const int biggestDimension = std::max(icon.width(), icon.height());
const QRect imageRect{0, 0, biggestDimension, biggestDimension};
QImage roundedImage(imageRect.size(), QImage::Format_ARGB32);
roundedImage.fill(Qt::transparent);
QPainter painter(&roundedImage);
painter.setRenderHint(QPainter::Antialiasing);
QBrush brush(icon.scaledToHeight(biggestDimension));
painter.setBrush(brush);
painter.drawRoundedRect(imageRect, imageRect.width(), imageRect.height());
if (room != nullptr) {
const QImage roomAvatar = room->avatar(imageRect.width(), imageRect.height());
if (icon != roomAvatar) {
const QRect lowerQuarter{imageRect.center(), imageRect.size() / 2};
painter.setBrush(roomAvatar.scaled(lowerQuarter.size()));
painter.drawRoundedRect(lowerQuarter, lowerQuarter.width(), lowerQuarter.height());
}
}
return QPixmap::fromImage(roundedImage);
}
#include "moc_notificationsmanager.cpp" #include "moc_notificationsmanager.cpp"

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