Merge pull request #100 from Nheko-Reborn/file-encryption
Add file encryption / decryption support
This commit is contained in:
commit
9d9b214e4c
|
@ -31,8 +31,8 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||||
QT_PKG="59"
|
QT_PKG="59"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
wget https://cmake.org/files/v3.12/cmake-3.12.2-Linux-x86_64.sh
|
wget https://cmake.org/files/v3.15/cmake-3.15.5-Linux-x86_64.sh
|
||||||
sudo sh cmake-3.12.2-Linux-x86_64.sh --skip-license --prefix=/usr/local
|
sudo sh cmake-3.15.5-Linux-x86_64.sh --skip-license --prefix=/usr/local
|
||||||
|
|
||||||
mkdir -p build-libsodium
|
mkdir -p build-libsodium
|
||||||
( cd build-libsodium
|
( cd build-libsodium
|
||||||
|
|
|
@ -13,6 +13,9 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||||
|
|
||||||
sudo update-alternatives --set gcc "/usr/bin/${C_COMPILER}"
|
sudo update-alternatives --set gcc "/usr/bin/${C_COMPILER}"
|
||||||
sudo update-alternatives --set g++ "/usr/bin/${CXX_COMPILER}"
|
sudo update-alternatives --set g++ "/usr/bin/${CXX_COMPILER}"
|
||||||
|
|
||||||
|
export PATH="/usr/local/bin/:${PATH}"
|
||||||
|
cmake --version
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||||
|
@ -35,7 +38,8 @@ cmake --build .deps
|
||||||
# Build nheko
|
# Build nheko
|
||||||
cmake -GNinja -H. -Bbuild \
|
cmake -GNinja -H. -Bbuild \
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
-DCMAKE_INSTALL_PREFIX=.deps/usr
|
-DCMAKE_INSTALL_PREFIX=.deps/usr \
|
||||||
|
-DBUILD_SHARED_LIBS=ON # weird workaround, as the boost 1.70 cmake files seem to be broken?
|
||||||
cmake --build build
|
cmake --build build
|
||||||
|
|
||||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||||
|
|
|
@ -259,7 +259,7 @@ include(FeatureSummary)
|
||||||
set(Boost_USE_STATIC_LIBS OFF)
|
set(Boost_USE_STATIC_LIBS OFF)
|
||||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||||
set(Boost_USE_MULTITHREADED ON)
|
set(Boost_USE_MULTITHREADED ON)
|
||||||
find_package(Boost 1.66 REQUIRED
|
find_package(Boost 1.70 REQUIRED
|
||||||
COMPONENTS atomic
|
COMPONENTS atomic
|
||||||
chrono
|
chrono
|
||||||
date_time
|
date_time
|
||||||
|
@ -365,6 +365,7 @@ qt5_wrap_cpp(MOC_HEADERS
|
||||||
src/CommunitiesList.h
|
src/CommunitiesList.h
|
||||||
src/LoginPage.h
|
src/LoginPage.h
|
||||||
src/MainWindow.h
|
src/MainWindow.h
|
||||||
|
src/MxcImageProvider.h
|
||||||
src/InviteeItem.h
|
src/InviteeItem.h
|
||||||
src/QuickSwitcher.h
|
src/QuickSwitcher.h
|
||||||
src/RegisterPage.h
|
src/RegisterPage.h
|
||||||
|
|
|
@ -92,11 +92,11 @@ sudo port install nheko
|
||||||
- Qt5 (5.8 or greater). Qt 5.7 adds support for color font rendering with
|
- Qt5 (5.8 or greater). Qt 5.7 adds support for color font rendering with
|
||||||
Freetype, which is essential to properly support emoji, 5.8 adds some features
|
Freetype, which is essential to properly support emoji, 5.8 adds some features
|
||||||
to make interopability with Qml easier.
|
to make interopability with Qml easier.
|
||||||
- CMake 3.1 or greater.
|
- CMake 3.15 or greater. (Lower version may work, but may break boost linking)
|
||||||
- [mtxclient](https://github.com/Nheko-Reborn/mtxclient)
|
- [mtxclient](https://github.com/Nheko-Reborn/mtxclient)
|
||||||
- [LMDB](https://symas.com/lightning-memory-mapped-database/)
|
- [LMDB](https://symas.com/lightning-memory-mapped-database/)
|
||||||
- [cmark](https://github.com/commonmark/cmark)
|
- [cmark](https://github.com/commonmark/cmark)
|
||||||
- Boost 1.66 or greater.
|
- Boost 1.70 or greater.
|
||||||
- [libolm](https://git.matrix.org/git/olm)
|
- [libolm](https://git.matrix.org/git/olm)
|
||||||
- [libsodium](https://github.com/jedisct1/libsodium)
|
- [libsodium](https://github.com/jedisct1/libsodium)
|
||||||
- [spdlog](https://github.com/gabime/spdlog)
|
- [spdlog](https://github.com/gabime/spdlog)
|
||||||
|
|
|
@ -34,6 +34,7 @@ install:
|
||||||
lmdb:%PLATFORM%-windows
|
lmdb:%PLATFORM%-windows
|
||||||
openssl:%PLATFORM%-windows
|
openssl:%PLATFORM%-windows
|
||||||
zlib:%PLATFORM%-windows
|
zlib:%PLATFORM%-windows
|
||||||
|
- vcpkg upgrade --no-dry-run
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
# VERSION format: branch-master/branch-1.2
|
# VERSION format: branch-master/branch-1.2
|
||||||
|
|
|
@ -33,23 +33,23 @@ option(USE_BUNDLED_JSON "Use the bundled version of nlohmann json." ${USE_BUNDLE
|
||||||
option(MTX_STATIC "Compile / link bundled mtx client statically" OFF)
|
option(MTX_STATIC "Compile / link bundled mtx client statically" OFF)
|
||||||
|
|
||||||
if(USE_BUNDLED_BOOST)
|
if(USE_BUNDLED_BOOST)
|
||||||
# bundled boost is 1.68, which requires CMake 3.12 or greater.
|
# bundled boost is 1.70, which requires CMake 3.15 or greater.
|
||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
|
|
||||||
set(BOOST_URL
|
set(BOOST_URL
|
||||||
https://dl.bintray.com/boostorg/release/1.69.0/source/boost_1_69_0.tar.bz2)
|
https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.bz2)
|
||||||
set(BOOST_SHA256
|
set(BOOST_SHA256
|
||||||
8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406)
|
430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778)
|
||||||
|
|
||||||
set(
|
set(
|
||||||
MTXCLIENT_URL
|
MTXCLIENT_URL
|
||||||
https://github.com/Nheko-Reborn/mtxclient/archive/6eee767cc25a9db9f125843e584656cde1ebb6c5.tar.gz
|
https://github.com/Nheko-Reborn/mtxclient/archive/64182a84e35378113f7d3a80f3073894416480e7.zip
|
||||||
)
|
)
|
||||||
set(MTXCLIENT_HASH
|
set(MTXCLIENT_HASH
|
||||||
72fe77da4fed98b3cf069299f66092c820c900359a27ec26070175f9ad208a03)
|
c9973501920046f04c72983472451736343d00e7a40f4d4a12181191093a5fab)
|
||||||
set(
|
set(
|
||||||
TWEENY_URL
|
TWEENY_URL
|
||||||
https://github.com/mobius3/tweeny/archive/b94ce07cfb02a0eb8ac8aaf66137dabdaea857cf.tar.gz
|
https://github.com/mobius3/tweeny/archive/b94ce07cfb02a0eb8ac8aaf66137dabdaea857cf.tar.gz
|
||||||
|
|
|
@ -4,27 +4,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ChatPage</name>
|
<name>ChatPage</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/ChatPage.cpp" line="+330"/>
|
<location filename="../../src/ChatPage.cpp" line="+346"/>
|
||||||
<source>Failed to upload image. Please try again.</source>
|
<source>Failed to upload media. Please try again.</source>
|
||||||
<translation>Hochladen des Bildes fehlgeschlagen. Bitte versuche es erneut.</translation>
|
<translation>Medienupload fehlgeschlagen. Bitte versuche es erneut.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+45"/>
|
<location line="+389"/>
|
||||||
<source>Failed to upload file. Please try again.</source>
|
|
||||||
<translation>Hochladen der Datei fehlgeschlagen. Bitte versuche es erneut.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+43"/>
|
|
||||||
<source>Failed to upload audio. Please try again.</source>
|
|
||||||
<translation>Hochladen der Audiodatei fehlgeschlagen. Bitte versuche es erneut.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+42"/>
|
|
||||||
<source>Failed to upload video. Please try again.</source>
|
|
||||||
<translation>Hochladen der Videodatei fehlgeschlagen. Bitte versuche es erneut.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+393"/>
|
|
||||||
<source>Failed to restore OLM account. Please login again.</source>
|
<source>Failed to restore OLM account. Please login again.</source>
|
||||||
<translation>Wiederherstellung des OLM Accounts fehlgeschlagen. Bitte logge dich erneut ein.</translation>
|
<translation>Wiederherstellung des OLM Accounts fehlgeschlagen. Bitte logge dich erneut ein.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -194,6 +179,19 @@
|
||||||
<translation>OK</translation>
|
<translation>OK</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MessageDelegate</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/delegates/MessageDelegate.qml" line="+43"/>
|
||||||
|
<source>redacted</source>
|
||||||
|
<translation>gelöscht</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+6"/>
|
||||||
|
<source>Encryption enabled</source>
|
||||||
|
<translation>Verschlüsselung aktiviert</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Placeholder</name>
|
<name>Placeholder</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -210,14 +208,6 @@
|
||||||
<translation>Raum suchen…</translation>
|
<translation>Raum suchen…</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>Redacted</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../qml/delegates/Redacted.qml" line="+5"/>
|
|
||||||
<source>redacted</source>
|
|
||||||
<translation>gelöscht</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>RegisterPage</name>
|
<name>RegisterPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -354,13 +344,13 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TextInputWidget</name>
|
<name>TextInputWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/TextInputWidget.cpp" line="+507"/>
|
<location filename="../../src/TextInputWidget.cpp" line="+502"/>
|
||||||
<source>Send a file</source>
|
<source>Send a file</source>
|
||||||
<translation>Versende Datei</translation>
|
<translation>Versende Datei</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+13"/>
|
<location line="+13"/>
|
||||||
<location filename="../../src/TextInputWidget.h" line="+164"/>
|
<location filename="../../src/TextInputWidget.h" line="+161"/>
|
||||||
<source>Write a message...</source>
|
<source>Write a message...</source>
|
||||||
<translation>Schreibe eine Nachricht…</translation>
|
<translation>Schreibe eine Nachricht…</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -375,7 +365,7 @@
|
||||||
<translation>Emoji</translation>
|
<translation>Emoji</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+75"/>
|
<location line="+72"/>
|
||||||
<source>Select a file</source>
|
<source>Select a file</source>
|
||||||
<translation>Datei auswählen</translation>
|
<translation>Datei auswählen</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -393,7 +383,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineModel</name>
|
<name>TimelineModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/timeline/TimelineModel.cpp" line="+780"/>
|
<location filename="../../src/timeline/TimelineModel.cpp" line="+835"/>
|
||||||
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
||||||
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
||||||
<translation>-- verschlüsselter Event (keine Schlüssel zur Entschlüsselung gefunden) --</translation>
|
<translation>-- verschlüsselter Event (keine Schlüssel zur Entschlüsselung gefunden) --</translation>
|
||||||
|
@ -423,10 +413,30 @@
|
||||||
<translation>-- verschlüsselter Event (Unbekannter Eventtyp) --</translation>
|
<translation>-- verschlüsselter Event (Unbekannter Eventtyp) --</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+50"/>
|
<location line="+54"/>
|
||||||
<source>Message redaction failed: %1</source>
|
<source>Message redaction failed: %1</source>
|
||||||
<translation>Nachricht zurückziehen fehlgeschlagen: %1</translation>
|
<translation>Nachricht zurückziehen fehlgeschlagen: %1</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+453"/>
|
||||||
|
<source>Save image</source>
|
||||||
|
<translation>Bild speichern</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save video</source>
|
||||||
|
<translation>Video speichern</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save audio</source>
|
||||||
|
<translation>Audiodatei speichern</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save file</source>
|
||||||
|
<translation>Datei speichern</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineRow</name>
|
<name>TimelineRow</name>
|
||||||
|
@ -474,29 +484,6 @@
|
||||||
<translation>Kein Raum geöffnet</translation>
|
<translation>Kein Raum geöffnet</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>TimelineViewManager</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../../src/timeline/TimelineViewManager.cpp" line="+161"/>
|
|
||||||
<source>Save image</source>
|
|
||||||
<translation>Bild speichern</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save video</source>
|
|
||||||
<translation>Video speichern</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save audio</source>
|
|
||||||
<translation>Audiodatei speichern</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save file</source>
|
|
||||||
<translation>Datei speichern</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>TopRoomBar</name>
|
<name>TopRoomBar</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -4,27 +4,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ChatPage</name>
|
<name>ChatPage</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/ChatPage.cpp" line="+330"/>
|
<location filename="../../src/ChatPage.cpp" line="+346"/>
|
||||||
<source>Failed to upload image. Please try again.</source>
|
<source>Failed to upload media. Please try again.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+45"/>
|
<location line="+389"/>
|
||||||
<source>Failed to upload file. Please try again.</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+43"/>
|
|
||||||
<source>Failed to upload audio. Please try again.</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+42"/>
|
|
||||||
<source>Failed to upload video. Please try again.</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+393"/>
|
|
||||||
<source>Failed to restore OLM account. Please login again.</source>
|
<source>Failed to restore OLM account. Please login again.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -194,6 +179,19 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MessageDelegate</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/delegates/MessageDelegate.qml" line="+43"/>
|
||||||
|
<source>redacted</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+6"/>
|
||||||
|
<source>Encryption enabled</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Placeholder</name>
|
<name>Placeholder</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -210,14 +208,6 @@
|
||||||
<translation>Αναζήτηση συνομιλίας...</translation>
|
<translation>Αναζήτηση συνομιλίας...</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>Redacted</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../qml/delegates/Redacted.qml" line="+5"/>
|
|
||||||
<source>redacted</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>RegisterPage</name>
|
<name>RegisterPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -354,13 +344,13 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TextInputWidget</name>
|
<name>TextInputWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/TextInputWidget.cpp" line="+507"/>
|
<location filename="../../src/TextInputWidget.cpp" line="+502"/>
|
||||||
<source>Send a file</source>
|
<source>Send a file</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+13"/>
|
<location line="+13"/>
|
||||||
<location filename="../../src/TextInputWidget.h" line="+164"/>
|
<location filename="../../src/TextInputWidget.h" line="+161"/>
|
||||||
<source>Write a message...</source>
|
<source>Write a message...</source>
|
||||||
<translation>Γράψε ένα μήνυμα...</translation>
|
<translation>Γράψε ένα μήνυμα...</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -375,7 +365,7 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+75"/>
|
<location line="+72"/>
|
||||||
<source>Select a file</source>
|
<source>Select a file</source>
|
||||||
<translation>Διάλεξε ένα αρχείο</translation>
|
<translation>Διάλεξε ένα αρχείο</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -393,7 +383,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineModel</name>
|
<name>TimelineModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/timeline/TimelineModel.cpp" line="+780"/>
|
<location filename="../../src/timeline/TimelineModel.cpp" line="+835"/>
|
||||||
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
||||||
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
|
@ -423,10 +413,30 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+50"/>
|
<location line="+54"/>
|
||||||
<source>Message redaction failed: %1</source>
|
<source>Message redaction failed: %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+453"/>
|
||||||
|
<source>Save image</source>
|
||||||
|
<translation type="unfinished">Αποθήκευση Εικόνας</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save video</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save audio</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineRow</name>
|
<name>TimelineRow</name>
|
||||||
|
@ -474,29 +484,6 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>TimelineViewManager</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../../src/timeline/TimelineViewManager.cpp" line="+161"/>
|
|
||||||
<source>Save image</source>
|
|
||||||
<translation type="unfinished">Αποθήκευση Εικόνας</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save video</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save audio</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save file</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>TopRoomBar</name>
|
<name>TopRoomBar</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -4,27 +4,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ChatPage</name>
|
<name>ChatPage</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/ChatPage.cpp" line="+330"/>
|
<location filename="../../src/ChatPage.cpp" line="+346"/>
|
||||||
<source>Failed to upload image. Please try again.</source>
|
<source>Failed to upload media. Please try again.</source>
|
||||||
<translation>Failed to upload image. Please try again.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+45"/>
|
<location line="+389"/>
|
||||||
<source>Failed to upload file. Please try again.</source>
|
|
||||||
<translation>Failed to upload file. Please try again.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+43"/>
|
|
||||||
<source>Failed to upload audio. Please try again.</source>
|
|
||||||
<translation>Failed to upload audio. Please try again.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+42"/>
|
|
||||||
<source>Failed to upload video. Please try again.</source>
|
|
||||||
<translation>Failed to upload video. Please try again.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+393"/>
|
|
||||||
<source>Failed to restore OLM account. Please login again.</source>
|
<source>Failed to restore OLM account. Please login again.</source>
|
||||||
<translation>Failed to restore OLM account. Please login again.</translation>
|
<translation>Failed to restore OLM account. Please login again.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -194,6 +179,19 @@
|
||||||
<translation>OK</translation>
|
<translation>OK</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MessageDelegate</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/delegates/MessageDelegate.qml" line="+43"/>
|
||||||
|
<source>redacted</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+6"/>
|
||||||
|
<source>Encryption enabled</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Placeholder</name>
|
<name>Placeholder</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -210,14 +208,6 @@
|
||||||
<translation>Search for a room…</translation>
|
<translation>Search for a room…</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>Redacted</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../qml/delegates/Redacted.qml" line="+5"/>
|
|
||||||
<source>redacted</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>RegisterPage</name>
|
<name>RegisterPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -354,13 +344,13 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TextInputWidget</name>
|
<name>TextInputWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/TextInputWidget.cpp" line="+507"/>
|
<location filename="../../src/TextInputWidget.cpp" line="+502"/>
|
||||||
<source>Send a file</source>
|
<source>Send a file</source>
|
||||||
<translation>Send a file</translation>
|
<translation>Send a file</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+13"/>
|
<location line="+13"/>
|
||||||
<location filename="../../src/TextInputWidget.h" line="+164"/>
|
<location filename="../../src/TextInputWidget.h" line="+161"/>
|
||||||
<source>Write a message...</source>
|
<source>Write a message...</source>
|
||||||
<translation>Write a message…</translation>
|
<translation>Write a message…</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -375,7 +365,7 @@
|
||||||
<translation>Emoji</translation>
|
<translation>Emoji</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+75"/>
|
<location line="+72"/>
|
||||||
<source>Select a file</source>
|
<source>Select a file</source>
|
||||||
<translation>Select a file</translation>
|
<translation>Select a file</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -393,7 +383,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineModel</name>
|
<name>TimelineModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/timeline/TimelineModel.cpp" line="+780"/>
|
<location filename="../../src/timeline/TimelineModel.cpp" line="+835"/>
|
||||||
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
||||||
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
||||||
<translation type="unfinished">-- Encrypted Event (No keys found for decryption) --</translation>
|
<translation type="unfinished">-- Encrypted Event (No keys found for decryption) --</translation>
|
||||||
|
@ -423,10 +413,30 @@
|
||||||
<translation type="unfinished">-- Encrypted Event (Unknown event type) --</translation>
|
<translation type="unfinished">-- Encrypted Event (Unknown event type) --</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+50"/>
|
<location line="+54"/>
|
||||||
<source>Message redaction failed: %1</source>
|
<source>Message redaction failed: %1</source>
|
||||||
<translation type="unfinished">Message redaction failed: %1</translation>
|
<translation type="unfinished">Message redaction failed: %1</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+453"/>
|
||||||
|
<source>Save image</source>
|
||||||
|
<translation type="unfinished">Save image</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save video</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save audio</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineRow</name>
|
<name>TimelineRow</name>
|
||||||
|
@ -474,29 +484,6 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>TimelineViewManager</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../../src/timeline/TimelineViewManager.cpp" line="+161"/>
|
|
||||||
<source>Save image</source>
|
|
||||||
<translation type="unfinished">Save image</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save video</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save audio</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save file</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>TopRoomBar</name>
|
<name>TopRoomBar</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -4,27 +4,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ChatPage</name>
|
<name>ChatPage</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/ChatPage.cpp" line="+330"/>
|
<location filename="../../src/ChatPage.cpp" line="+346"/>
|
||||||
<source>Failed to upload image. Please try again.</source>
|
<source>Failed to upload media. Please try again.</source>
|
||||||
<translation>Kuvan lähettäminen epäonnistui. Ole hyvä ja yritä uudelleen.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+45"/>
|
<location line="+389"/>
|
||||||
<source>Failed to upload file. Please try again.</source>
|
|
||||||
<translation>Tiedoston lähettäminen epäonnistui. Ole hyvä ja yritä uudelleen.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+43"/>
|
|
||||||
<source>Failed to upload audio. Please try again.</source>
|
|
||||||
<translation>Äänitiedoston lähettäminen epäonnistui. Ole hyvä ja yritä uudelleen.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+42"/>
|
|
||||||
<source>Failed to upload video. Please try again.</source>
|
|
||||||
<translation>Videon lähettäminen epäonnistui. Ole hyvä ja yritä uudelleen.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+393"/>
|
|
||||||
<source>Failed to restore OLM account. Please login again.</source>
|
<source>Failed to restore OLM account. Please login again.</source>
|
||||||
<translation>OLM-tilin palauttaminen epäonnistui. Ole hyvä ja kirjaudu sisään uudelleen.</translation>
|
<translation>OLM-tilin palauttaminen epäonnistui. Ole hyvä ja kirjaudu sisään uudelleen.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -194,6 +179,19 @@
|
||||||
<translation>OK</translation>
|
<translation>OK</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MessageDelegate</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/delegates/MessageDelegate.qml" line="+43"/>
|
||||||
|
<source>redacted</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+6"/>
|
||||||
|
<source>Encryption enabled</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Placeholder</name>
|
<name>Placeholder</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -210,14 +208,6 @@
|
||||||
<translation>Etsi huonetta…</translation>
|
<translation>Etsi huonetta…</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>Redacted</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../qml/delegates/Redacted.qml" line="+5"/>
|
|
||||||
<source>redacted</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>RegisterPage</name>
|
<name>RegisterPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -354,13 +344,13 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TextInputWidget</name>
|
<name>TextInputWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/TextInputWidget.cpp" line="+507"/>
|
<location filename="../../src/TextInputWidget.cpp" line="+502"/>
|
||||||
<source>Send a file</source>
|
<source>Send a file</source>
|
||||||
<translation>Lähetä tiedosto</translation>
|
<translation>Lähetä tiedosto</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+13"/>
|
<location line="+13"/>
|
||||||
<location filename="../../src/TextInputWidget.h" line="+164"/>
|
<location filename="../../src/TextInputWidget.h" line="+161"/>
|
||||||
<source>Write a message...</source>
|
<source>Write a message...</source>
|
||||||
<translation>Kirjoita viesti…</translation>
|
<translation>Kirjoita viesti…</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -375,7 +365,7 @@
|
||||||
<translation>Emoji</translation>
|
<translation>Emoji</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+75"/>
|
<location line="+72"/>
|
||||||
<source>Select a file</source>
|
<source>Select a file</source>
|
||||||
<translation>Valitse tiedosto</translation>
|
<translation>Valitse tiedosto</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -393,7 +383,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineModel</name>
|
<name>TimelineModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/timeline/TimelineModel.cpp" line="+780"/>
|
<location filename="../../src/timeline/TimelineModel.cpp" line="+835"/>
|
||||||
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
||||||
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
||||||
<translation type="unfinished">-- Salattu viesti (salauksen purkuavaimia ei löydetty) --</translation>
|
<translation type="unfinished">-- Salattu viesti (salauksen purkuavaimia ei löydetty) --</translation>
|
||||||
|
@ -423,10 +413,30 @@
|
||||||
<translation type="unfinished">-- Salattu viesti (tuntematon viestityyppi) --</translation>
|
<translation type="unfinished">-- Salattu viesti (tuntematon viestityyppi) --</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+50"/>
|
<location line="+54"/>
|
||||||
<source>Message redaction failed: %1</source>
|
<source>Message redaction failed: %1</source>
|
||||||
<translation type="unfinished">Viestin poisto epäonnistui: %1</translation>
|
<translation type="unfinished">Viestin poisto epäonnistui: %1</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+453"/>
|
||||||
|
<source>Save image</source>
|
||||||
|
<translation type="unfinished">Tallenna kuva</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save video</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save audio</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineRow</name>
|
<name>TimelineRow</name>
|
||||||
|
@ -474,29 +484,6 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>TimelineViewManager</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../../src/timeline/TimelineViewManager.cpp" line="+161"/>
|
|
||||||
<source>Save image</source>
|
|
||||||
<translation type="unfinished">Tallenna kuva</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save video</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save audio</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save file</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>TopRoomBar</name>
|
<name>TopRoomBar</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -4,27 +4,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ChatPage</name>
|
<name>ChatPage</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/ChatPage.cpp" line="+330"/>
|
<location filename="../../src/ChatPage.cpp" line="+346"/>
|
||||||
<source>Failed to upload image. Please try again.</source>
|
<source>Failed to upload media. Please try again.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+45"/>
|
<location line="+389"/>
|
||||||
<source>Failed to upload file. Please try again.</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+43"/>
|
|
||||||
<source>Failed to upload audio. Please try again.</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+42"/>
|
|
||||||
<source>Failed to upload video. Please try again.</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+393"/>
|
|
||||||
<source>Failed to restore OLM account. Please login again.</source>
|
<source>Failed to restore OLM account. Please login again.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -194,6 +179,19 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MessageDelegate</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/delegates/MessageDelegate.qml" line="+43"/>
|
||||||
|
<source>redacted</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+6"/>
|
||||||
|
<source>Encryption enabled</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Placeholder</name>
|
<name>Placeholder</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -210,14 +208,6 @@
|
||||||
<translation>Chercher un salon…</translation>
|
<translation>Chercher un salon…</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>Redacted</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../qml/delegates/Redacted.qml" line="+5"/>
|
|
||||||
<source>redacted</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>RegisterPage</name>
|
<name>RegisterPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -355,13 +345,13 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TextInputWidget</name>
|
<name>TextInputWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/TextInputWidget.cpp" line="+507"/>
|
<location filename="../../src/TextInputWidget.cpp" line="+502"/>
|
||||||
<source>Send a file</source>
|
<source>Send a file</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+13"/>
|
<location line="+13"/>
|
||||||
<location filename="../../src/TextInputWidget.h" line="+164"/>
|
<location filename="../../src/TextInputWidget.h" line="+161"/>
|
||||||
<source>Write a message...</source>
|
<source>Write a message...</source>
|
||||||
<translation>Écrivez un message...</translation>
|
<translation>Écrivez un message...</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -376,7 +366,7 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+75"/>
|
<location line="+72"/>
|
||||||
<source>Select a file</source>
|
<source>Select a file</source>
|
||||||
<translation>Sélectionnez un fichier</translation>
|
<translation>Sélectionnez un fichier</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -394,7 +384,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineModel</name>
|
<name>TimelineModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/timeline/TimelineModel.cpp" line="+780"/>
|
<location filename="../../src/timeline/TimelineModel.cpp" line="+835"/>
|
||||||
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
||||||
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
|
@ -424,10 +414,30 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+50"/>
|
<location line="+54"/>
|
||||||
<source>Message redaction failed: %1</source>
|
<source>Message redaction failed: %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+453"/>
|
||||||
|
<source>Save image</source>
|
||||||
|
<translation type="unfinished">Enregistrer l'image</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save video</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save audio</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineRow</name>
|
<name>TimelineRow</name>
|
||||||
|
@ -475,29 +485,6 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>TimelineViewManager</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../../src/timeline/TimelineViewManager.cpp" line="+161"/>
|
|
||||||
<source>Save image</source>
|
|
||||||
<translation type="unfinished">Enregistrer l'image</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save video</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save audio</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save file</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>TopRoomBar</name>
|
<name>TopRoomBar</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -4,27 +4,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ChatPage</name>
|
<name>ChatPage</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/ChatPage.cpp" line="+330"/>
|
<location filename="../../src/ChatPage.cpp" line="+346"/>
|
||||||
<source>Failed to upload image. Please try again.</source>
|
<source>Failed to upload media. Please try again.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+45"/>
|
<location line="+389"/>
|
||||||
<source>Failed to upload file. Please try again.</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+43"/>
|
|
||||||
<source>Failed to upload audio. Please try again.</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+42"/>
|
|
||||||
<source>Failed to upload video. Please try again.</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+393"/>
|
|
||||||
<source>Failed to restore OLM account. Please login again.</source>
|
<source>Failed to restore OLM account. Please login again.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -194,6 +179,19 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MessageDelegate</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/delegates/MessageDelegate.qml" line="+43"/>
|
||||||
|
<source>redacted</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+6"/>
|
||||||
|
<source>Encryption enabled</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Placeholder</name>
|
<name>Placeholder</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -210,14 +208,6 @@
|
||||||
<translation>Zoek een kamer...</translation>
|
<translation>Zoek een kamer...</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>Redacted</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../qml/delegates/Redacted.qml" line="+5"/>
|
|
||||||
<source>redacted</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>RegisterPage</name>
|
<name>RegisterPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -354,13 +344,13 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TextInputWidget</name>
|
<name>TextInputWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/TextInputWidget.cpp" line="+507"/>
|
<location filename="../../src/TextInputWidget.cpp" line="+502"/>
|
||||||
<source>Send a file</source>
|
<source>Send a file</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+13"/>
|
<location line="+13"/>
|
||||||
<location filename="../../src/TextInputWidget.h" line="+164"/>
|
<location filename="../../src/TextInputWidget.h" line="+161"/>
|
||||||
<source>Write a message...</source>
|
<source>Write a message...</source>
|
||||||
<translation>Typ een bericht...</translation>
|
<translation>Typ een bericht...</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -375,7 +365,7 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+75"/>
|
<location line="+72"/>
|
||||||
<source>Select a file</source>
|
<source>Select a file</source>
|
||||||
<translation>Kies een bestand</translation>
|
<translation>Kies een bestand</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -393,7 +383,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineModel</name>
|
<name>TimelineModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/timeline/TimelineModel.cpp" line="+780"/>
|
<location filename="../../src/timeline/TimelineModel.cpp" line="+835"/>
|
||||||
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
||||||
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
|
@ -423,10 +413,30 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+50"/>
|
<location line="+54"/>
|
||||||
<source>Message redaction failed: %1</source>
|
<source>Message redaction failed: %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+453"/>
|
||||||
|
<source>Save image</source>
|
||||||
|
<translation type="unfinished">Afbeelding opslaan</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save video</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save audio</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineRow</name>
|
<name>TimelineRow</name>
|
||||||
|
@ -474,29 +484,6 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>TimelineViewManager</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../../src/timeline/TimelineViewManager.cpp" line="+161"/>
|
|
||||||
<source>Save image</source>
|
|
||||||
<translation type="unfinished">Afbeelding opslaan</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save video</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save audio</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save file</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>TopRoomBar</name>
|
<name>TopRoomBar</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -4,27 +4,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ChatPage</name>
|
<name>ChatPage</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/ChatPage.cpp" line="+330"/>
|
<location filename="../../src/ChatPage.cpp" line="+346"/>
|
||||||
<source>Failed to upload image. Please try again.</source>
|
<source>Failed to upload media. Please try again.</source>
|
||||||
<translation>Nie udało się wysłać obrazu. Spróbuj ponownie.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+45"/>
|
<location line="+389"/>
|
||||||
<source>Failed to upload file. Please try again.</source>
|
|
||||||
<translation>Nie udało się wysłać pliku. Spróbuj ponownie.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+43"/>
|
|
||||||
<source>Failed to upload audio. Please try again.</source>
|
|
||||||
<translation>Nie udało się wysłać pliku dźwiękowego. Spróbuj ponownie.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+42"/>
|
|
||||||
<source>Failed to upload video. Please try again.</source>
|
|
||||||
<translation>Nie udało się wysłać filmu. Spróbuj ponownie.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+393"/>
|
|
||||||
<source>Failed to restore OLM account. Please login again.</source>
|
<source>Failed to restore OLM account. Please login again.</source>
|
||||||
<translation>Nie udało się przywrócić konta OLM. Spróbuj zalogować się ponownie.</translation>
|
<translation>Nie udało się przywrócić konta OLM. Spróbuj zalogować się ponownie.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -194,6 +179,19 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MessageDelegate</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/delegates/MessageDelegate.qml" line="+43"/>
|
||||||
|
<source>redacted</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+6"/>
|
||||||
|
<source>Encryption enabled</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Placeholder</name>
|
<name>Placeholder</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -210,14 +208,6 @@
|
||||||
<translation>Wyszukaj pokoju…</translation>
|
<translation>Wyszukaj pokoju…</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>Redacted</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../qml/delegates/Redacted.qml" line="+5"/>
|
|
||||||
<source>redacted</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>RegisterPage</name>
|
<name>RegisterPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -354,13 +344,13 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TextInputWidget</name>
|
<name>TextInputWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/TextInputWidget.cpp" line="+507"/>
|
<location filename="../../src/TextInputWidget.cpp" line="+502"/>
|
||||||
<source>Send a file</source>
|
<source>Send a file</source>
|
||||||
<translation>Wyślij plik</translation>
|
<translation>Wyślij plik</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+13"/>
|
<location line="+13"/>
|
||||||
<location filename="../../src/TextInputWidget.h" line="+164"/>
|
<location filename="../../src/TextInputWidget.h" line="+161"/>
|
||||||
<source>Write a message...</source>
|
<source>Write a message...</source>
|
||||||
<translation>Napisz wiadomość…</translation>
|
<translation>Napisz wiadomość…</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -375,7 +365,7 @@
|
||||||
<translation>Emoji</translation>
|
<translation>Emoji</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+75"/>
|
<location line="+72"/>
|
||||||
<source>Select a file</source>
|
<source>Select a file</source>
|
||||||
<translation>Wybierz plik</translation>
|
<translation>Wybierz plik</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -393,7 +383,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineModel</name>
|
<name>TimelineModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/timeline/TimelineModel.cpp" line="+780"/>
|
<location filename="../../src/timeline/TimelineModel.cpp" line="+835"/>
|
||||||
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
||||||
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
|
@ -423,10 +413,30 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+50"/>
|
<location line="+54"/>
|
||||||
<source>Message redaction failed: %1</source>
|
<source>Message redaction failed: %1</source>
|
||||||
<translation type="unfinished">Redagowanie wiadomości nie powiodło się: %1</translation>
|
<translation type="unfinished">Redagowanie wiadomości nie powiodło się: %1</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+453"/>
|
||||||
|
<source>Save image</source>
|
||||||
|
<translation type="unfinished">Zapisz obraz</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save video</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save audio</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineRow</name>
|
<name>TimelineRow</name>
|
||||||
|
@ -474,29 +484,6 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>TimelineViewManager</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../../src/timeline/TimelineViewManager.cpp" line="+161"/>
|
|
||||||
<source>Save image</source>
|
|
||||||
<translation type="unfinished">Zapisz obraz</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save video</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save audio</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save file</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>TopRoomBar</name>
|
<name>TopRoomBar</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -4,27 +4,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ChatPage</name>
|
<name>ChatPage</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/ChatPage.cpp" line="+330"/>
|
<location filename="../../src/ChatPage.cpp" line="+346"/>
|
||||||
<source>Failed to upload image. Please try again.</source>
|
<source>Failed to upload media. Please try again.</source>
|
||||||
<translation>Не удалось загрузить изображение. Пожалуйста, попробуйте еще раз.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+45"/>
|
<location line="+389"/>
|
||||||
<source>Failed to upload file. Please try again.</source>
|
|
||||||
<translation>Не удалось загрузить файл. Пожалуйста, попробуйте еще раз.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+43"/>
|
|
||||||
<source>Failed to upload audio. Please try again.</source>
|
|
||||||
<translation>Не удалось загрузить аудио. Пожалуйста, попробуйте еще раз.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+42"/>
|
|
||||||
<source>Failed to upload video. Please try again.</source>
|
|
||||||
<translation>Не удалось загрузить видео. Пожалуйста, попробуйте еще раз.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+393"/>
|
|
||||||
<source>Failed to restore OLM account. Please login again.</source>
|
<source>Failed to restore OLM account. Please login again.</source>
|
||||||
<translation>Не удалось восстановить учетную запись OLM. Пожалуйста, войдите снова.</translation>
|
<translation>Не удалось восстановить учетную запись OLM. Пожалуйста, войдите снова.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -194,6 +179,19 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MessageDelegate</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/delegates/MessageDelegate.qml" line="+43"/>
|
||||||
|
<source>redacted</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+6"/>
|
||||||
|
<source>Encryption enabled</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Placeholder</name>
|
<name>Placeholder</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -210,14 +208,6 @@
|
||||||
<translation>Поиск комнаты...</translation>
|
<translation>Поиск комнаты...</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>Redacted</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../qml/delegates/Redacted.qml" line="+5"/>
|
|
||||||
<source>redacted</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>RegisterPage</name>
|
<name>RegisterPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -354,13 +344,13 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TextInputWidget</name>
|
<name>TextInputWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/TextInputWidget.cpp" line="+507"/>
|
<location filename="../../src/TextInputWidget.cpp" line="+502"/>
|
||||||
<source>Send a file</source>
|
<source>Send a file</source>
|
||||||
<translation>Отправить файл</translation>
|
<translation>Отправить файл</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+13"/>
|
<location line="+13"/>
|
||||||
<location filename="../../src/TextInputWidget.h" line="+164"/>
|
<location filename="../../src/TextInputWidget.h" line="+161"/>
|
||||||
<source>Write a message...</source>
|
<source>Write a message...</source>
|
||||||
<translation>Написать сообщение...</translation>
|
<translation>Написать сообщение...</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -375,7 +365,7 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+75"/>
|
<location line="+72"/>
|
||||||
<source>Select a file</source>
|
<source>Select a file</source>
|
||||||
<translation>Выберите файл</translation>
|
<translation>Выберите файл</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -393,7 +383,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineModel</name>
|
<name>TimelineModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/timeline/TimelineModel.cpp" line="+780"/>
|
<location filename="../../src/timeline/TimelineModel.cpp" line="+835"/>
|
||||||
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
||||||
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
|
@ -423,10 +413,30 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+50"/>
|
<location line="+54"/>
|
||||||
<source>Message redaction failed: %1</source>
|
<source>Message redaction failed: %1</source>
|
||||||
<translation type="unfinished">Ошибка редактирования сообщения: %1</translation>
|
<translation type="unfinished">Ошибка редактирования сообщения: %1</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+453"/>
|
||||||
|
<source>Save image</source>
|
||||||
|
<translation type="unfinished">Сохранить изображение</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save video</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save audio</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineRow</name>
|
<name>TimelineRow</name>
|
||||||
|
@ -474,29 +484,6 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>TimelineViewManager</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../../src/timeline/TimelineViewManager.cpp" line="+161"/>
|
|
||||||
<source>Save image</source>
|
|
||||||
<translation type="unfinished">Сохранить изображение</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save video</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save audio</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save file</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>TopRoomBar</name>
|
<name>TopRoomBar</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -4,27 +4,12 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ChatPage</name>
|
<name>ChatPage</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/ChatPage.cpp" line="+330"/>
|
<location filename="../../src/ChatPage.cpp" line="+346"/>
|
||||||
<source>Failed to upload image. Please try again.</source>
|
<source>Failed to upload media. Please try again.</source>
|
||||||
<translation>上传图像失败。请重试。</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+45"/>
|
<location line="+389"/>
|
||||||
<source>Failed to upload file. Please try again.</source>
|
|
||||||
<translation>上传文件失败,请重试。</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+43"/>
|
|
||||||
<source>Failed to upload audio. Please try again.</source>
|
|
||||||
<translation>上传音频失败。请重试。</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+42"/>
|
|
||||||
<source>Failed to upload video. Please try again.</source>
|
|
||||||
<translation>上传视频失败。请重试。</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+393"/>
|
|
||||||
<source>Failed to restore OLM account. Please login again.</source>
|
<source>Failed to restore OLM account. Please login again.</source>
|
||||||
<translation>恢复 OLM 账户失败。请重新登录。</translation>
|
<translation>恢复 OLM 账户失败。请重新登录。</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -194,6 +179,19 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MessageDelegate</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../qml/delegates/MessageDelegate.qml" line="+43"/>
|
||||||
|
<source>redacted</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+6"/>
|
||||||
|
<source>Encryption enabled</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Placeholder</name>
|
<name>Placeholder</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -210,14 +208,6 @@
|
||||||
<translation>寻找一个聊天室...</translation>
|
<translation>寻找一个聊天室...</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>Redacted</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../qml/delegates/Redacted.qml" line="+5"/>
|
|
||||||
<source>redacted</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>RegisterPage</name>
|
<name>RegisterPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -354,13 +344,13 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TextInputWidget</name>
|
<name>TextInputWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/TextInputWidget.cpp" line="+507"/>
|
<location filename="../../src/TextInputWidget.cpp" line="+502"/>
|
||||||
<source>Send a file</source>
|
<source>Send a file</source>
|
||||||
<translation>发送一个文件</translation>
|
<translation>发送一个文件</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+13"/>
|
<location line="+13"/>
|
||||||
<location filename="../../src/TextInputWidget.h" line="+164"/>
|
<location filename="../../src/TextInputWidget.h" line="+161"/>
|
||||||
<source>Write a message...</source>
|
<source>Write a message...</source>
|
||||||
<translation>写一条消息...</translation>
|
<translation>写一条消息...</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -375,7 +365,7 @@
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+75"/>
|
<location line="+72"/>
|
||||||
<source>Select a file</source>
|
<source>Select a file</source>
|
||||||
<translation>选择一个文件</translation>
|
<translation>选择一个文件</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -393,7 +383,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineModel</name>
|
<name>TimelineModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/timeline/TimelineModel.cpp" line="+780"/>
|
<location filename="../../src/timeline/TimelineModel.cpp" line="+835"/>
|
||||||
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
<source>-- Encrypted Event (No keys found for decryption) --</source>
|
||||||
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
<comment>Placeholder, when the message was not decrypted yet or can't be decrypted</comment>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
|
@ -423,10 +413,30 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location line="+50"/>
|
<location line="+54"/>
|
||||||
<source>Message redaction failed: %1</source>
|
<source>Message redaction failed: %1</source>
|
||||||
<translation type="unfinished">删除消息失败:%1</translation>
|
<translation type="unfinished">删除消息失败:%1</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+453"/>
|
||||||
|
<source>Save image</source>
|
||||||
|
<translation type="unfinished">保存图像</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save video</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save audio</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location line="+2"/>
|
||||||
|
<source>Save file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>TimelineRow</name>
|
<name>TimelineRow</name>
|
||||||
|
@ -474,29 +484,6 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>TimelineViewManager</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../../src/timeline/TimelineViewManager.cpp" line="+161"/>
|
|
||||||
<source>Save image</source>
|
|
||||||
<translation type="unfinished">保存图像</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save video</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save audio</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location line="+2"/>
|
|
||||||
<source>Save file</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>TopRoomBar</name>
|
<name>TopRoomBar</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -97,7 +97,7 @@ RowLayout {
|
||||||
MenuItem {
|
MenuItem {
|
||||||
visible: model.type == MtxEvent.ImageMessage || model.type == MtxEvent.VideoMessage || model.type == MtxEvent.AudioMessage || model.type == MtxEvent.FileMessage || model.type == MtxEvent.Sticker
|
visible: model.type == MtxEvent.ImageMessage || model.type == MtxEvent.VideoMessage || model.type == MtxEvent.AudioMessage || model.type == MtxEvent.FileMessage || model.type == MtxEvent.Sticker
|
||||||
text: qsTr("Save as")
|
text: qsTr("Save as")
|
||||||
onTriggered: timelineManager.saveMedia(model.url, model.filename, model.mimetype, model.type)
|
onTriggered: timelineManager.timeline.saveMedia(model.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: timelineManager.saveMedia(model.url, model.filename, model.mimetype, model.type)
|
onClicked: timelineManager.timeline.saveMedia(model.id)
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ Item {
|
||||||
MouseArea {
|
MouseArea {
|
||||||
enabled: model.type == MtxEvent.ImageMessage
|
enabled: model.type == MtxEvent.ImageMessage
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: timelineManager.openImageOverlay(model.url, model.filename, model.mimetype, model.type)
|
onClicked: timelineManager.openImageOverlay(model.url, model.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
switch (button.state) {
|
switch (button.state) {
|
||||||
case "": timelineManager.cacheMedia(model.url, model.mimetype); break;
|
case "": timelineManager.timeline.cacheMedia(model.id); break;
|
||||||
case "stopped":
|
case "stopped":
|
||||||
media.play(); console.log("play");
|
media.play(); console.log("play");
|
||||||
button.state = "playing"
|
button.state = "playing"
|
||||||
|
@ -118,7 +118,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: timelineManager
|
target: timelineManager.timeline
|
||||||
onMediaCached: {
|
onMediaCached: {
|
||||||
if (mxcUrl == model.url) {
|
if (mxcUrl == model.url) {
|
||||||
media.source = "file://" + cacheUrl
|
media.source = "file://" + cacheUrl
|
||||||
|
|
196
src/ChatPage.cpp
196
src/ChatPage.cpp
|
@ -54,6 +54,8 @@ constexpr int CHECK_CONNECTIVITY_INTERVAL = 15'000;
|
||||||
constexpr int RETRY_TIMEOUT = 5'000;
|
constexpr int RETRY_TIMEOUT = 5'000;
|
||||||
constexpr size_t MAX_ONETIME_KEYS = 50;
|
constexpr size_t MAX_ONETIME_KEYS = 50;
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(boost::optional<mtx::crypto::EncryptedFile>)
|
||||||
|
|
||||||
ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, isConnected_(true)
|
, isConnected_(true)
|
||||||
|
@ -62,6 +64,9 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
{
|
{
|
||||||
setObjectName("chatPage");
|
setObjectName("chatPage");
|
||||||
|
|
||||||
|
qRegisterMetaType<boost::optional<mtx::crypto::EncryptedFile>>(
|
||||||
|
"boost::optional<mtx::crypto::EncryptedFile>");
|
||||||
|
|
||||||
topLayout_ = new QHBoxLayout(this);
|
topLayout_ = new QHBoxLayout(this);
|
||||||
topLayout_->setSpacing(0);
|
topLayout_->setSpacing(0);
|
||||||
topLayout_->setMargin(0);
|
topLayout_->setMargin(0);
|
||||||
|
@ -299,9 +304,9 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
|
|
||||||
connect(
|
connect(
|
||||||
text_input_,
|
text_input_,
|
||||||
&TextInputWidget::uploadImage,
|
&TextInputWidget::uploadMedia,
|
||||||
this,
|
this,
|
||||||
[this](QSharedPointer<QIODevice> dev, const QString &fn) {
|
[this](QSharedPointer<QIODevice> dev, QString mimeClass, const QString &fn) {
|
||||||
QMimeDatabase db;
|
QMimeDatabase db;
|
||||||
QMimeType mime = db.mimeTypeForData(dev.data());
|
QMimeType mime = db.mimeTypeForData(dev.data());
|
||||||
|
|
||||||
|
@ -313,7 +318,16 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
|
|
||||||
auto bin = dev->peek(dev->size());
|
auto bin = dev->peek(dev->size());
|
||||||
auto payload = std::string(bin.data(), bin.size());
|
auto payload = std::string(bin.data(), bin.size());
|
||||||
auto dimensions = QImageReader(dev.data()).size();
|
boost::optional<mtx::crypto::EncryptedFile> encryptedFile;
|
||||||
|
if (cache::client()->isRoomEncrypted(current_room_.toStdString())) {
|
||||||
|
mtx::crypto::BinaryBuf buf;
|
||||||
|
std::tie(buf, encryptedFile) = mtx::crypto::encrypt_file(payload);
|
||||||
|
payload = mtx::crypto::to_string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize dimensions;
|
||||||
|
if (mimeClass == "image")
|
||||||
|
dimensions = QImageReader(dev.data()).size();
|
||||||
|
|
||||||
http::client()->upload(
|
http::client()->upload(
|
||||||
payload,
|
payload,
|
||||||
|
@ -322,193 +336,61 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
[this,
|
[this,
|
||||||
room_id = current_room_,
|
room_id = current_room_,
|
||||||
filename = fn,
|
filename = fn,
|
||||||
|
encryptedFile,
|
||||||
|
mimeClass,
|
||||||
mime = mime.name(),
|
mime = mime.name(),
|
||||||
size = payload.size(),
|
size = payload.size(),
|
||||||
dimensions](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) {
|
dimensions](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
emit uploadFailed(
|
emit uploadFailed(
|
||||||
tr("Failed to upload image. Please try again."));
|
tr("Failed to upload media. Please try again."));
|
||||||
nhlog::net()->warn("failed to upload image: {} {} ({})",
|
nhlog::net()->warn("failed to upload media: {} {} ({})",
|
||||||
err->matrix_error.error,
|
err->matrix_error.error,
|
||||||
to_string(err->matrix_error.errcode),
|
to_string(err->matrix_error.errcode),
|
||||||
static_cast<int>(err->status_code));
|
static_cast<int>(err->status_code));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit imageUploaded(room_id,
|
emit mediaUploaded(room_id,
|
||||||
filename,
|
filename,
|
||||||
|
encryptedFile,
|
||||||
QString::fromStdString(res.content_uri),
|
QString::fromStdString(res.content_uri),
|
||||||
|
mimeClass,
|
||||||
mime,
|
mime,
|
||||||
size,
|
size,
|
||||||
dimensions);
|
dimensions);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(text_input_,
|
|
||||||
&TextInputWidget::uploadFile,
|
|
||||||
this,
|
|
||||||
[this](QSharedPointer<QIODevice> dev, const QString &fn) {
|
|
||||||
QMimeDatabase db;
|
|
||||||
QMimeType mime = db.mimeTypeForData(dev.data());
|
|
||||||
|
|
||||||
if (!dev->open(QIODevice::ReadOnly)) {
|
|
||||||
emit uploadFailed(
|
|
||||||
QString("Error while reading media: %1").arg(dev->errorString()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bin = dev->readAll();
|
|
||||||
auto payload = std::string(bin.data(), bin.size());
|
|
||||||
|
|
||||||
http::client()->upload(
|
|
||||||
payload,
|
|
||||||
mime.name().toStdString(),
|
|
||||||
QFileInfo(fn).fileName().toStdString(),
|
|
||||||
[this,
|
|
||||||
room_id = current_room_,
|
|
||||||
filename = fn,
|
|
||||||
mime = mime.name(),
|
|
||||||
size = payload.size()](const mtx::responses::ContentURI &res,
|
|
||||||
mtx::http::RequestErr err) {
|
|
||||||
if (err) {
|
|
||||||
emit uploadFailed(
|
|
||||||
tr("Failed to upload file. Please try again."));
|
|
||||||
nhlog::net()->warn("failed to upload file: {} ({})",
|
|
||||||
err->matrix_error.error,
|
|
||||||
static_cast<int>(err->status_code));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit fileUploaded(room_id,
|
|
||||||
filename,
|
|
||||||
QString::fromStdString(res.content_uri),
|
|
||||||
mime,
|
|
||||||
size);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(text_input_,
|
|
||||||
&TextInputWidget::uploadAudio,
|
|
||||||
this,
|
|
||||||
[this](QSharedPointer<QIODevice> dev, const QString &fn) {
|
|
||||||
QMimeDatabase db;
|
|
||||||
QMimeType mime = db.mimeTypeForData(dev.data());
|
|
||||||
|
|
||||||
if (!dev->open(QIODevice::ReadOnly)) {
|
|
||||||
emit uploadFailed(
|
|
||||||
QString("Error while reading media: %1").arg(dev->errorString()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bin = dev->readAll();
|
|
||||||
auto payload = std::string(bin.data(), bin.size());
|
|
||||||
|
|
||||||
http::client()->upload(
|
|
||||||
payload,
|
|
||||||
mime.name().toStdString(),
|
|
||||||
QFileInfo(fn).fileName().toStdString(),
|
|
||||||
[this,
|
|
||||||
room_id = current_room_,
|
|
||||||
filename = fn,
|
|
||||||
mime = mime.name(),
|
|
||||||
size = payload.size()](const mtx::responses::ContentURI &res,
|
|
||||||
mtx::http::RequestErr err) {
|
|
||||||
if (err) {
|
|
||||||
emit uploadFailed(
|
|
||||||
tr("Failed to upload audio. Please try again."));
|
|
||||||
nhlog::net()->warn("failed to upload audio: {} ({})",
|
|
||||||
err->matrix_error.error,
|
|
||||||
static_cast<int>(err->status_code));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit audioUploaded(room_id,
|
|
||||||
filename,
|
|
||||||
QString::fromStdString(res.content_uri),
|
|
||||||
mime,
|
|
||||||
size);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
connect(text_input_,
|
|
||||||
&TextInputWidget::uploadVideo,
|
|
||||||
this,
|
|
||||||
[this](QSharedPointer<QIODevice> dev, const QString &fn) {
|
|
||||||
QMimeDatabase db;
|
|
||||||
QMimeType mime = db.mimeTypeForData(dev.data());
|
|
||||||
|
|
||||||
if (!dev->open(QIODevice::ReadOnly)) {
|
|
||||||
emit uploadFailed(
|
|
||||||
QString("Error while reading media: %1").arg(dev->errorString()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bin = dev->readAll();
|
|
||||||
auto payload = std::string(bin.data(), bin.size());
|
|
||||||
|
|
||||||
http::client()->upload(
|
|
||||||
payload,
|
|
||||||
mime.name().toStdString(),
|
|
||||||
QFileInfo(fn).fileName().toStdString(),
|
|
||||||
[this,
|
|
||||||
room_id = current_room_,
|
|
||||||
filename = fn,
|
|
||||||
mime = mime.name(),
|
|
||||||
size = payload.size()](const mtx::responses::ContentURI &res,
|
|
||||||
mtx::http::RequestErr err) {
|
|
||||||
if (err) {
|
|
||||||
emit uploadFailed(
|
|
||||||
tr("Failed to upload video. Please try again."));
|
|
||||||
nhlog::net()->warn("failed to upload video: {} ({})",
|
|
||||||
err->matrix_error.error,
|
|
||||||
static_cast<int>(err->status_code));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit videoUploaded(room_id,
|
|
||||||
filename,
|
|
||||||
QString::fromStdString(res.content_uri),
|
|
||||||
mime,
|
|
||||||
size);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(this, &ChatPage::uploadFailed, this, [this](const QString &msg) {
|
connect(this, &ChatPage::uploadFailed, this, [this](const QString &msg) {
|
||||||
text_input_->hideUploadSpinner();
|
text_input_->hideUploadSpinner();
|
||||||
emit showNotification(msg);
|
emit showNotification(msg);
|
||||||
});
|
});
|
||||||
connect(this,
|
connect(this,
|
||||||
&ChatPage::imageUploaded,
|
&ChatPage::mediaUploaded,
|
||||||
this,
|
this,
|
||||||
[this](QString roomid,
|
[this](QString roomid,
|
||||||
QString filename,
|
QString filename,
|
||||||
|
boost::optional<mtx::crypto::EncryptedFile> encryptedFile,
|
||||||
QString url,
|
QString url,
|
||||||
|
QString mimeClass,
|
||||||
QString mime,
|
QString mime,
|
||||||
qint64 dsize,
|
qint64 dsize,
|
||||||
QSize dimensions) {
|
QSize dimensions) {
|
||||||
text_input_->hideUploadSpinner();
|
text_input_->hideUploadSpinner();
|
||||||
|
|
||||||
|
if (mimeClass == "image")
|
||||||
view_manager_->queueImageMessage(
|
view_manager_->queueImageMessage(
|
||||||
roomid, filename, url, mime, dsize, dimensions);
|
roomid, filename, encryptedFile, url, mime, dsize, dimensions);
|
||||||
});
|
else if (mimeClass == "audio")
|
||||||
connect(this,
|
view_manager_->queueAudioMessage(
|
||||||
&ChatPage::fileUploaded,
|
roomid, filename, encryptedFile, url, mime, dsize);
|
||||||
this,
|
else if (mimeClass == "video")
|
||||||
[this](QString roomid, QString filename, QString url, QString mime, qint64 dsize) {
|
view_manager_->queueVideoMessage(
|
||||||
text_input_->hideUploadSpinner();
|
roomid, filename, encryptedFile, url, mime, dsize);
|
||||||
view_manager_->queueFileMessage(roomid, filename, url, mime, dsize);
|
else
|
||||||
});
|
view_manager_->queueFileMessage(
|
||||||
connect(this,
|
roomid, filename, encryptedFile, url, mime, dsize);
|
||||||
&ChatPage::audioUploaded,
|
|
||||||
this,
|
|
||||||
[this](QString roomid, QString filename, QString url, QString mime, qint64 dsize) {
|
|
||||||
text_input_->hideUploadSpinner();
|
|
||||||
view_manager_->queueAudioMessage(roomid, filename, url, mime, dsize);
|
|
||||||
});
|
|
||||||
connect(this,
|
|
||||||
&ChatPage::videoUploaded,
|
|
||||||
this,
|
|
||||||
[this](QString roomid, QString filename, QString url, QString mime, qint64 dsize) {
|
|
||||||
text_input_->hideUploadSpinner();
|
|
||||||
view_manager_->queueVideoMessage(roomid, filename, url, mime, dsize);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(room_list_, &RoomList::roomAvatarChanged, this, &ChatPage::updateTopBarAvatar);
|
connect(room_list_, &RoomList::roomAvatarChanged, this, &ChatPage::updateTopBarAvatar);
|
||||||
|
|
|
@ -18,7 +18,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
|
#include <mtx/common.hpp>
|
||||||
#include <mtx/responses.hpp>
|
#include <mtx/responses.hpp>
|
||||||
|
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
|
@ -94,27 +96,14 @@ signals:
|
||||||
const QPoint widgetPos);
|
const QPoint widgetPos);
|
||||||
|
|
||||||
void uploadFailed(const QString &msg);
|
void uploadFailed(const QString &msg);
|
||||||
void imageUploaded(const QString &roomid,
|
void mediaUploaded(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
const boost::optional<mtx::crypto::EncryptedFile> &file,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
|
const QString &mimeClass,
|
||||||
const QString &mime,
|
const QString &mime,
|
||||||
qint64 dsize,
|
qint64 dsize,
|
||||||
const QSize &dimensions);
|
const QSize &dimensions);
|
||||||
void fileUploaded(const QString &roomid,
|
|
||||||
const QString &filename,
|
|
||||||
const QString &url,
|
|
||||||
const QString &mime,
|
|
||||||
qint64 dsize);
|
|
||||||
void audioUploaded(const QString &roomid,
|
|
||||||
const QString &filename,
|
|
||||||
const QString &url,
|
|
||||||
const QString &mime,
|
|
||||||
qint64 dsize);
|
|
||||||
void videoUploaded(const QString &roomid,
|
|
||||||
const QString &filename,
|
|
||||||
const QString &url,
|
|
||||||
const QString &mime,
|
|
||||||
qint64 dsize);
|
|
||||||
|
|
||||||
void contentLoaded();
|
void contentLoaded();
|
||||||
void closing();
|
void closing();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
void
|
void
|
||||||
MxcImageResponse::run()
|
MxcImageResponse::run()
|
||||||
{
|
{
|
||||||
if (m_requestedSize.isValid()) {
|
if (m_requestedSize.isValid() && !m_encryptionInfo) {
|
||||||
QString fileName = QString("%1_%2x%3_crop")
|
QString fileName = QString("%1_%2x%3_crop")
|
||||||
.arg(m_id)
|
.arg(m_id)
|
||||||
.arg(m_requestedSize.width())
|
.arg(m_requestedSize.width())
|
||||||
|
@ -65,7 +65,12 @@ MxcImageResponse::run()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = QByteArray(res.data(), res.size());
|
auto temp = res;
|
||||||
|
if (m_encryptionInfo)
|
||||||
|
temp = mtx::crypto::to_string(
|
||||||
|
mtx::crypto::decrypt_file(temp, m_encryptionInfo.value()));
|
||||||
|
|
||||||
|
auto data = QByteArray(temp.data(), temp.size());
|
||||||
m_image.loadFromData(data);
|
m_image.loadFromData(data);
|
||||||
m_image.setText("original filename",
|
m_image.setText("original filename",
|
||||||
QString::fromStdString(originalFilename));
|
QString::fromStdString(originalFilename));
|
||||||
|
|
|
@ -6,14 +6,21 @@
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
|
|
||||||
|
#include <mtx/common.hpp>
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
class MxcImageResponse
|
class MxcImageResponse
|
||||||
: public QQuickImageResponse
|
: public QQuickImageResponse
|
||||||
, public QRunnable
|
, public QRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MxcImageResponse(const QString &id, const QSize &requestedSize)
|
MxcImageResponse(const QString &id,
|
||||||
|
const QSize &requestedSize,
|
||||||
|
boost::optional<mtx::crypto::EncryptedFile> encryptionInfo)
|
||||||
: m_id(id)
|
: m_id(id)
|
||||||
, m_requestedSize(requestedSize)
|
, m_requestedSize(requestedSize)
|
||||||
|
, m_encryptionInfo(encryptionInfo)
|
||||||
{
|
{
|
||||||
setAutoDelete(false);
|
setAutoDelete(false);
|
||||||
}
|
}
|
||||||
|
@ -29,19 +36,34 @@ public:
|
||||||
QString m_id, m_error;
|
QString m_id, m_error;
|
||||||
QSize m_requestedSize;
|
QSize m_requestedSize;
|
||||||
QImage m_image;
|
QImage m_image;
|
||||||
|
boost::optional<mtx::crypto::EncryptedFile> m_encryptionInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MxcImageProvider : public QQuickAsyncImageProvider
|
class MxcImageProvider
|
||||||
|
: public QObject
|
||||||
|
, public QQuickAsyncImageProvider
|
||||||
{
|
{
|
||||||
public:
|
Q_OBJECT
|
||||||
|
public slots:
|
||||||
QQuickImageResponse *requestImageResponse(const QString &id,
|
QQuickImageResponse *requestImageResponse(const QString &id,
|
||||||
const QSize &requestedSize) override
|
const QSize &requestedSize) override
|
||||||
{
|
{
|
||||||
MxcImageResponse *response = new MxcImageResponse(id, requestedSize);
|
boost::optional<mtx::crypto::EncryptedFile> info;
|
||||||
|
auto temp = infos.find("mxc://" + id);
|
||||||
|
if (temp != infos.end())
|
||||||
|
info = *temp;
|
||||||
|
|
||||||
|
MxcImageResponse *response = new MxcImageResponse(id, requestedSize, info);
|
||||||
pool.start(response);
|
pool.start(response);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addEncryptionInfo(mtx::crypto::EncryptedFile info)
|
||||||
|
{
|
||||||
|
infos.insert(QString::fromStdString(info.url), info);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QThreadPool pool;
|
QThreadPool pool;
|
||||||
|
QHash<QString, mtx::crypto::EncryptedFile> infos;
|
||||||
};
|
};
|
||||||
|
|
|
@ -458,21 +458,16 @@ FilteredTextEdit::textChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FilteredTextEdit::uploadData(const QByteArray data, const QString &media, const QString &filename)
|
FilteredTextEdit::uploadData(const QByteArray data,
|
||||||
|
const QString &mediaType,
|
||||||
|
const QString &filename)
|
||||||
{
|
{
|
||||||
QSharedPointer<QBuffer> buffer{new QBuffer{this}};
|
QSharedPointer<QBuffer> buffer{new QBuffer{this}};
|
||||||
buffer->setData(data);
|
buffer->setData(data);
|
||||||
|
|
||||||
emit startedUpload();
|
emit startedUpload();
|
||||||
|
|
||||||
if (media == "image")
|
emit media(buffer, mediaType, filename);
|
||||||
emit image(buffer, filename);
|
|
||||||
else if (media == "audio")
|
|
||||||
emit audio(buffer, filename);
|
|
||||||
else if (media == "video")
|
|
||||||
emit video(buffer, filename);
|
|
||||||
else
|
|
||||||
emit file(buffer, filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -580,10 +575,7 @@ TextInputWidget::TextInputWidget(QWidget *parent)
|
||||||
connect(input_, &FilteredTextEdit::message, this, &TextInputWidget::sendTextMessage);
|
connect(input_, &FilteredTextEdit::message, this, &TextInputWidget::sendTextMessage);
|
||||||
connect(input_, &FilteredTextEdit::reply, this, &TextInputWidget::sendReplyMessage);
|
connect(input_, &FilteredTextEdit::reply, this, &TextInputWidget::sendReplyMessage);
|
||||||
connect(input_, &FilteredTextEdit::command, this, &TextInputWidget::command);
|
connect(input_, &FilteredTextEdit::command, this, &TextInputWidget::command);
|
||||||
connect(input_, &FilteredTextEdit::image, this, &TextInputWidget::uploadImage);
|
connect(input_, &FilteredTextEdit::media, this, &TextInputWidget::uploadMedia);
|
||||||
connect(input_, &FilteredTextEdit::audio, this, &TextInputWidget::uploadAudio);
|
|
||||||
connect(input_, &FilteredTextEdit::video, this, &TextInputWidget::uploadVideo);
|
|
||||||
connect(input_, &FilteredTextEdit::file, this, &TextInputWidget::uploadFile);
|
|
||||||
connect(emojiBtn_,
|
connect(emojiBtn_,
|
||||||
SIGNAL(emojiSelected(const QString &)),
|
SIGNAL(emojiSelected(const QString &)),
|
||||||
this,
|
this,
|
||||||
|
@ -642,14 +634,8 @@ TextInputWidget::openFileSelection()
|
||||||
const auto format = mime.name().split("/")[0];
|
const auto format = mime.name().split("/")[0];
|
||||||
|
|
||||||
QSharedPointer<QFile> file{new QFile{fileName, this}};
|
QSharedPointer<QFile> file{new QFile{fileName, this}};
|
||||||
if (format == "image")
|
|
||||||
emit uploadImage(file, fileName);
|
emit uploadMedia(file, format, fileName);
|
||||||
else if (format == "audio")
|
|
||||||
emit uploadAudio(file, fileName);
|
|
||||||
else if (format == "video")
|
|
||||||
emit uploadVideo(file, fileName);
|
|
||||||
else
|
|
||||||
emit uploadFile(file, fileName);
|
|
||||||
|
|
||||||
showUploadSpinner();
|
showUploadSpinner();
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,10 +63,7 @@ signals:
|
||||||
void message(QString);
|
void message(QString);
|
||||||
void reply(QString, const RelatedInfo &);
|
void reply(QString, const RelatedInfo &);
|
||||||
void command(QString name, QString args);
|
void command(QString name, QString args);
|
||||||
void image(QSharedPointer<QIODevice> data, const QString &filename);
|
void media(QSharedPointer<QIODevice> data, QString mimeClass, const QString &filename);
|
||||||
void audio(QSharedPointer<QIODevice> data, const QString &filename);
|
|
||||||
void video(QSharedPointer<QIODevice> data, const QString &filename);
|
|
||||||
void file(QSharedPointer<QIODevice> data, const QString &filename);
|
|
||||||
|
|
||||||
//! Trigger the suggestion popup.
|
//! Trigger the suggestion popup.
|
||||||
void showSuggestions(const QString &query);
|
void showSuggestions(const QString &query);
|
||||||
|
@ -179,10 +176,9 @@ signals:
|
||||||
void sendEmoteMessage(QString msg);
|
void sendEmoteMessage(QString msg);
|
||||||
void heightChanged(int height);
|
void heightChanged(int height);
|
||||||
|
|
||||||
void uploadImage(const QSharedPointer<QIODevice> data, const QString &filename);
|
void uploadMedia(const QSharedPointer<QIODevice> data,
|
||||||
void uploadFile(const QSharedPointer<QIODevice> data, const QString &filename);
|
QString mimeClass,
|
||||||
void uploadAudio(const QSharedPointer<QIODevice> data, const QString &filename);
|
const QString &filename);
|
||||||
void uploadVideo(const QSharedPointer<QIODevice> data, const QString &filename);
|
|
||||||
|
|
||||||
void sendJoinRoomRequest(const QString &room);
|
void sendJoinRoomRequest(const QString &room);
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,15 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMimeDatabase>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include "ChatPage.h"
|
#include "ChatPage.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
#include "MxcImageProvider.h"
|
||||||
#include "Olm.h"
|
#include "Olm.h"
|
||||||
#include "TimelineViewManager.h"
|
#include "TimelineViewManager.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
@ -88,17 +92,42 @@ eventFormattedBody(const mtx::events::RoomEvent<T> &e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
boost::optional<mtx::crypto::EncryptedFile>
|
||||||
|
eventEncryptionInfo(const mtx::events::Event<T> &)
|
||||||
|
{
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
auto
|
||||||
|
eventEncryptionInfo(const mtx::events::RoomEvent<T> &e) -> std::enable_if_t<
|
||||||
|
std::is_same<decltype(e.content.file), boost::optional<mtx::crypto::EncryptedFile>>::value,
|
||||||
|
boost::optional<mtx::crypto::EncryptedFile>>
|
||||||
|
{
|
||||||
|
return e.content.file;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
QString
|
QString
|
||||||
eventUrl(const mtx::events::Event<T> &)
|
eventUrl(const mtx::events::Event<T> &)
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
eventUrl(const mtx::events::StateEvent<mtx::events::state::Avatar> &e)
|
||||||
|
{
|
||||||
|
return QString::fromStdString(e.content.url);
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
auto
|
auto
|
||||||
eventUrl(const mtx::events::RoomEvent<T> &e)
|
eventUrl(const mtx::events::RoomEvent<T> &e)
|
||||||
-> std::enable_if_t<std::is_same<decltype(e.content.url), std::string>::value, QString>
|
-> std::enable_if_t<std::is_same<decltype(e.content.url), std::string>::value, QString>
|
||||||
{
|
{
|
||||||
|
if (e.content.file)
|
||||||
|
return QString::fromStdString(e.content.file->url);
|
||||||
return QString::fromStdString(e.content.url);
|
return QString::fromStdString(e.content.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,6 +673,19 @@ TimelineModel::internalAddEvents(
|
||||||
continue; // don't insert redaction into timeline
|
continue; // don't insert redaction into timeline
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auto event =
|
||||||
|
boost::get<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(&e)) {
|
||||||
|
auto temp = decryptEvent(*event).event;
|
||||||
|
auto encInfo = boost::apply_visitor(
|
||||||
|
[](const auto &ev) -> boost::optional<mtx::crypto::EncryptedFile> {
|
||||||
|
return eventEncryptionInfo(ev);
|
||||||
|
},
|
||||||
|
temp);
|
||||||
|
|
||||||
|
if (encInfo)
|
||||||
|
emit newEncryptedImage(encInfo.value());
|
||||||
|
}
|
||||||
|
|
||||||
this->events.insert(id, e);
|
this->events.insert(id, e);
|
||||||
ids.push_back(id);
|
ids.push_back(id);
|
||||||
}
|
}
|
||||||
|
@ -1342,3 +1384,158 @@ TimelineModel::addPendingMessage(mtx::events::collections::TimelineEvents event)
|
||||||
if (!isProcessingPending)
|
if (!isProcessingPending)
|
||||||
emit nextPendingMessage();
|
emit nextPendingMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineModel::saveMedia(QString eventId) const
|
||||||
|
{
|
||||||
|
mtx::events::collections::TimelineEvents event = events.value(eventId);
|
||||||
|
|
||||||
|
if (auto e = boost::get<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(&event)) {
|
||||||
|
event = decryptEvent(*e).event;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString mxcUrl =
|
||||||
|
boost::apply_visitor([](const auto &e) -> QString { return eventUrl(e); }, event);
|
||||||
|
QString originalFilename =
|
||||||
|
boost::apply_visitor([](const auto &e) -> QString { return eventFilename(e); }, event);
|
||||||
|
QString mimeType =
|
||||||
|
boost::apply_visitor([](const auto &e) -> QString { return eventMimeType(e); }, event);
|
||||||
|
|
||||||
|
using EncF = boost::optional<mtx::crypto::EncryptedFile>;
|
||||||
|
EncF encryptionInfo =
|
||||||
|
boost::apply_visitor([](const auto &e) -> EncF { return eventEncryptionInfo(e); }, event);
|
||||||
|
|
||||||
|
qml_mtx_events::EventType eventType = boost::apply_visitor(
|
||||||
|
[](const auto &e) -> qml_mtx_events::EventType { return toRoomEventType(e); }, event);
|
||||||
|
|
||||||
|
QString dialogTitle;
|
||||||
|
if (eventType == qml_mtx_events::EventType::ImageMessage) {
|
||||||
|
dialogTitle = tr("Save image");
|
||||||
|
} else if (eventType == qml_mtx_events::EventType::VideoMessage) {
|
||||||
|
dialogTitle = tr("Save video");
|
||||||
|
} else if (eventType == qml_mtx_events::EventType::AudioMessage) {
|
||||||
|
dialogTitle = tr("Save audio");
|
||||||
|
} else {
|
||||||
|
dialogTitle = tr("Save file");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString filterString = QMimeDatabase().mimeTypeForName(mimeType).filterString();
|
||||||
|
|
||||||
|
auto filename = QFileDialog::getSaveFileName(
|
||||||
|
manager_->getWidget(), dialogTitle, originalFilename, filterString);
|
||||||
|
|
||||||
|
if (filename.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto url = mxcUrl.toStdString();
|
||||||
|
|
||||||
|
http::client()->download(
|
||||||
|
url,
|
||||||
|
[filename, url, encryptionInfo](const std::string &data,
|
||||||
|
const std::string &,
|
||||||
|
const std::string &,
|
||||||
|
mtx::http::RequestErr err) {
|
||||||
|
if (err) {
|
||||||
|
nhlog::net()->warn("failed to retrieve image {}: {} {}",
|
||||||
|
url,
|
||||||
|
err->matrix_error.error,
|
||||||
|
static_cast<int>(err->status_code));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto temp = data;
|
||||||
|
if (encryptionInfo)
|
||||||
|
temp = mtx::crypto::to_string(
|
||||||
|
mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
|
||||||
|
|
||||||
|
QFile file(filename);
|
||||||
|
|
||||||
|
if (!file.open(QIODevice::WriteOnly))
|
||||||
|
return;
|
||||||
|
|
||||||
|
file.write(QByteArray(temp.data(), (int)temp.size()));
|
||||||
|
file.close();
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
nhlog::ui()->warn("Error while saving file to: {}", e.what());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineModel::cacheMedia(QString eventId)
|
||||||
|
{
|
||||||
|
mtx::events::collections::TimelineEvents event = events.value(eventId);
|
||||||
|
|
||||||
|
if (auto e = boost::get<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(&event)) {
|
||||||
|
event = decryptEvent(*e).event;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString mxcUrl =
|
||||||
|
boost::apply_visitor([](const auto &e) -> QString { return eventUrl(e); }, event);
|
||||||
|
QString mimeType =
|
||||||
|
boost::apply_visitor([](const auto &e) -> QString { return eventMimeType(e); }, event);
|
||||||
|
|
||||||
|
using EncF = boost::optional<mtx::crypto::EncryptedFile>;
|
||||||
|
EncF encryptionInfo =
|
||||||
|
boost::apply_visitor([](const auto &e) -> EncF { return eventEncryptionInfo(e); }, event);
|
||||||
|
|
||||||
|
// If the message is a link to a non mxcUrl, don't download it
|
||||||
|
if (!mxcUrl.startsWith("mxc://")) {
|
||||||
|
emit mediaCached(mxcUrl, mxcUrl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
|
||||||
|
|
||||||
|
const auto url = mxcUrl.toStdString();
|
||||||
|
QFileInfo filename(QString("%1/media_cache/%2.%3")
|
||||||
|
.arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
|
||||||
|
.arg(QString(mxcUrl).remove("mxc://"))
|
||||||
|
.arg(suffix));
|
||||||
|
if (QDir::cleanPath(filename.path()) != filename.path()) {
|
||||||
|
nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir().mkpath(filename.path());
|
||||||
|
|
||||||
|
if (filename.isReadable()) {
|
||||||
|
emit mediaCached(mxcUrl, filename.filePath());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
http::client()->download(
|
||||||
|
url,
|
||||||
|
[this, mxcUrl, filename, url, encryptionInfo](const std::string &data,
|
||||||
|
const std::string &,
|
||||||
|
const std::string &,
|
||||||
|
mtx::http::RequestErr err) {
|
||||||
|
if (err) {
|
||||||
|
nhlog::net()->warn("failed to retrieve image {}: {} {}",
|
||||||
|
url,
|
||||||
|
err->matrix_error.error,
|
||||||
|
static_cast<int>(err->status_code));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto temp = data;
|
||||||
|
if (encryptionInfo)
|
||||||
|
temp = mtx::crypto::to_string(
|
||||||
|
mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
|
||||||
|
|
||||||
|
QFile file(filename.filePath());
|
||||||
|
|
||||||
|
if (!file.open(QIODevice::WriteOnly))
|
||||||
|
return;
|
||||||
|
|
||||||
|
file.write(QByteArray(temp.data(), temp.size()));
|
||||||
|
file.close();
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
nhlog::ui()->warn("Error while saving file to: {}", e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
emit mediaCached(mxcUrl, filename.filePath());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
|
#include <mtx/common.hpp>
|
||||||
#include <mtx/responses.hpp>
|
#include <mtx/responses.hpp>
|
||||||
|
|
||||||
#include "Cache.h"
|
#include "Cache.h"
|
||||||
|
@ -159,6 +160,8 @@ public:
|
||||||
Q_INVOKABLE void redactEvent(QString id);
|
Q_INVOKABLE void redactEvent(QString id);
|
||||||
Q_INVOKABLE int idToIndex(QString id) const;
|
Q_INVOKABLE int idToIndex(QString id) const;
|
||||||
Q_INVOKABLE QString indexToId(int index) const;
|
Q_INVOKABLE QString indexToId(int index) const;
|
||||||
|
Q_INVOKABLE void cacheMedia(QString eventId);
|
||||||
|
Q_INVOKABLE void saveMedia(QString eventId) const;
|
||||||
|
|
||||||
void addEvents(const mtx::responses::Timeline &events);
|
void addEvents(const mtx::responses::Timeline &events);
|
||||||
template<class T>
|
template<class T>
|
||||||
|
@ -185,6 +188,8 @@ signals:
|
||||||
void eventRedacted(QString id);
|
void eventRedacted(QString id);
|
||||||
void nextPendingMessage();
|
void nextPendingMessage();
|
||||||
void newMessageToSend(mtx::events::collections::TimelineEvents event);
|
void newMessageToSend(mtx::events::collections::TimelineEvents event);
|
||||||
|
void mediaCached(QString mxcUrl, QString cacheUrl);
|
||||||
|
void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DecryptionResult decryptEvent(
|
DecryptionResult decryptEvent(
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
#include "TimelineViewManager.h"
|
#include "TimelineViewManager.h"
|
||||||
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QMimeDatabase>
|
|
||||||
#include <QPalette>
|
#include <QPalette>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
#include <QStandardPaths>
|
|
||||||
|
|
||||||
#include "ChatPage.h"
|
#include "ChatPage.h"
|
||||||
#include "ColorImageProvider.h"
|
#include "ColorImageProvider.h"
|
||||||
|
@ -105,9 +102,14 @@ TimelineViewManager::sync(const mtx::responses::Rooms &rooms)
|
||||||
void
|
void
|
||||||
TimelineViewManager::addRoom(const QString &room_id)
|
TimelineViewManager::addRoom(const QString &room_id)
|
||||||
{
|
{
|
||||||
if (!models.contains(room_id))
|
if (!models.contains(room_id)) {
|
||||||
models.insert(room_id,
|
QSharedPointer<TimelineModel> newRoom(new TimelineModel(this, room_id));
|
||||||
QSharedPointer<TimelineModel>(new TimelineModel(this, room_id)));
|
connect(newRoom.data(),
|
||||||
|
&TimelineModel::newEncryptedImage,
|
||||||
|
imgProvider,
|
||||||
|
&MxcImageProvider::addEncryptionInfo);
|
||||||
|
models.insert(room_id, std::move(newRoom));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -124,17 +126,11 @@ TimelineViewManager::setHistoryView(const QString &room_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::openImageOverlay(QString mxcUrl,
|
TimelineViewManager::openImageOverlay(QString mxcUrl, QString eventId) const
|
||||||
QString originalFilename,
|
|
||||||
QString mimeType,
|
|
||||||
qml_mtx_events::EventType eventType) const
|
|
||||||
{
|
{
|
||||||
QQuickImageResponse *imgResponse =
|
QQuickImageResponse *imgResponse =
|
||||||
imgProvider->requestImageResponse(mxcUrl.remove("mxc://"), QSize());
|
imgProvider->requestImageResponse(mxcUrl.remove("mxc://"), QSize());
|
||||||
connect(imgResponse,
|
connect(imgResponse, &QQuickImageResponse::finished, this, [this, eventId, imgResponse]() {
|
||||||
&QQuickImageResponse::finished,
|
|
||||||
this,
|
|
||||||
[this, mxcUrl, originalFilename, mimeType, eventType, imgResponse]() {
|
|
||||||
if (!imgResponse->errorString().isEmpty()) {
|
if (!imgResponse->errorString().isEmpty()) {
|
||||||
nhlog::ui()->error("Error when retrieving image for overlay: {}",
|
nhlog::ui()->error("Error when retrieving image for overlay: {}",
|
||||||
imgResponse->errorString().toStdString());
|
imgResponse->errorString().toStdString());
|
||||||
|
@ -144,128 +140,12 @@ TimelineViewManager::openImageOverlay(QString mxcUrl,
|
||||||
|
|
||||||
auto imgDialog = new dialogs::ImageOverlay(pixmap);
|
auto imgDialog = new dialogs::ImageOverlay(pixmap);
|
||||||
imgDialog->show();
|
imgDialog->show();
|
||||||
connect(imgDialog,
|
connect(imgDialog, &dialogs::ImageOverlay::saving, timeline_, [this, eventId]() {
|
||||||
&dialogs::ImageOverlay::saving,
|
timeline_->saveMedia(eventId);
|
||||||
this,
|
|
||||||
[this, mxcUrl, originalFilename, mimeType, eventType]() {
|
|
||||||
saveMedia(mxcUrl, originalFilename, mimeType, eventType);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
TimelineViewManager::saveMedia(QString mxcUrl,
|
|
||||||
QString originalFilename,
|
|
||||||
QString mimeType,
|
|
||||||
qml_mtx_events::EventType eventType) const
|
|
||||||
{
|
|
||||||
QString dialogTitle;
|
|
||||||
if (eventType == qml_mtx_events::EventType::ImageMessage) {
|
|
||||||
dialogTitle = tr("Save image");
|
|
||||||
} else if (eventType == qml_mtx_events::EventType::VideoMessage) {
|
|
||||||
dialogTitle = tr("Save video");
|
|
||||||
} else if (eventType == qml_mtx_events::EventType::AudioMessage) {
|
|
||||||
dialogTitle = tr("Save audio");
|
|
||||||
} else {
|
|
||||||
dialogTitle = tr("Save file");
|
|
||||||
}
|
|
||||||
|
|
||||||
QString filterString = QMimeDatabase().mimeTypeForName(mimeType).filterString();
|
|
||||||
|
|
||||||
auto filename =
|
|
||||||
QFileDialog::getSaveFileName(container, dialogTitle, originalFilename, filterString);
|
|
||||||
|
|
||||||
if (filename.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto url = mxcUrl.toStdString();
|
|
||||||
|
|
||||||
http::client()->download(
|
|
||||||
url,
|
|
||||||
[filename, url](const std::string &data,
|
|
||||||
const std::string &,
|
|
||||||
const std::string &,
|
|
||||||
mtx::http::RequestErr err) {
|
|
||||||
if (err) {
|
|
||||||
nhlog::net()->warn("failed to retrieve image {}: {} {}",
|
|
||||||
url,
|
|
||||||
err->matrix_error.error,
|
|
||||||
static_cast<int>(err->status_code));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
QFile file(filename);
|
|
||||||
|
|
||||||
if (!file.open(QIODevice::WriteOnly))
|
|
||||||
return;
|
|
||||||
|
|
||||||
file.write(QByteArray(data.data(), (int)data.size()));
|
|
||||||
file.close();
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
nhlog::ui()->warn("Error while saving file to: {}", e.what());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TimelineViewManager::cacheMedia(QString mxcUrl, QString mimeType)
|
|
||||||
{
|
|
||||||
// If the message is a link to a non mxcUrl, don't download it
|
|
||||||
if (!mxcUrl.startsWith("mxc://")) {
|
|
||||||
emit mediaCached(mxcUrl, mxcUrl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
|
|
||||||
|
|
||||||
const auto url = mxcUrl.toStdString();
|
|
||||||
QFileInfo filename(QString("%1/media_cache/%2.%3")
|
|
||||||
.arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
|
|
||||||
.arg(QString(mxcUrl).remove("mxc://"))
|
|
||||||
.arg(suffix));
|
|
||||||
if (QDir::cleanPath(filename.path()) != filename.path()) {
|
|
||||||
nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDir().mkpath(filename.path());
|
|
||||||
|
|
||||||
if (filename.isReadable()) {
|
|
||||||
emit mediaCached(mxcUrl, filename.filePath());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
http::client()->download(
|
|
||||||
url,
|
|
||||||
[this, mxcUrl, filename, url](const std::string &data,
|
|
||||||
const std::string &,
|
|
||||||
const std::string &,
|
|
||||||
mtx::http::RequestErr err) {
|
|
||||||
if (err) {
|
|
||||||
nhlog::net()->warn("failed to retrieve image {}: {} {}",
|
|
||||||
url,
|
|
||||||
err->matrix_error.error,
|
|
||||||
static_cast<int>(err->status_code));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
QFile file(filename.filePath());
|
|
||||||
|
|
||||||
if (!file.open(QIODevice::WriteOnly))
|
|
||||||
return;
|
|
||||||
|
|
||||||
file.write(QByteArray(data.data(), data.size()));
|
|
||||||
file.close();
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
nhlog::ui()->warn("Error while saving file to: {}", e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
emit mediaCached(mxcUrl, filename.filePath());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::updateReadReceipts(const QString &room_id,
|
TimelineViewManager::updateReadReceipts(const QString &room_id,
|
||||||
const std::vector<QString> &event_ids)
|
const std::vector<QString> &event_ids)
|
||||||
|
@ -342,6 +222,7 @@ TimelineViewManager::queueEmoteMessage(const QString &msg)
|
||||||
void
|
void
|
||||||
TimelineViewManager::queueImageMessage(const QString &roomid,
|
TimelineViewManager::queueImageMessage(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
const boost::optional<mtx::crypto::EncryptedFile> &file,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &mime,
|
const QString &mime,
|
||||||
uint64_t dsize,
|
uint64_t dsize,
|
||||||
|
@ -354,12 +235,15 @@ TimelineViewManager::queueImageMessage(const QString &roomid,
|
||||||
image.url = url.toStdString();
|
image.url = url.toStdString();
|
||||||
image.info.h = dimensions.height();
|
image.info.h = dimensions.height();
|
||||||
image.info.w = dimensions.width();
|
image.info.w = dimensions.width();
|
||||||
|
image.file = file;
|
||||||
models.value(roomid)->sendMessage(image);
|
models.value(roomid)->sendMessage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::queueFileMessage(const QString &roomid,
|
TimelineViewManager::queueFileMessage(
|
||||||
|
const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
const boost::optional<mtx::crypto::EncryptedFile> &encryptedFile,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &mime,
|
const QString &mime,
|
||||||
uint64_t dsize)
|
uint64_t dsize)
|
||||||
|
@ -369,12 +253,14 @@ TimelineViewManager::queueFileMessage(const QString &roomid,
|
||||||
file.info.size = dsize;
|
file.info.size = dsize;
|
||||||
file.body = filename.toStdString();
|
file.body = filename.toStdString();
|
||||||
file.url = url.toStdString();
|
file.url = url.toStdString();
|
||||||
|
file.file = encryptedFile;
|
||||||
models.value(roomid)->sendMessage(file);
|
models.value(roomid)->sendMessage(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::queueAudioMessage(const QString &roomid,
|
TimelineViewManager::queueAudioMessage(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
const boost::optional<mtx::crypto::EncryptedFile> &file,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &mime,
|
const QString &mime,
|
||||||
uint64_t dsize)
|
uint64_t dsize)
|
||||||
|
@ -384,12 +270,14 @@ TimelineViewManager::queueAudioMessage(const QString &roomid,
|
||||||
audio.info.size = dsize;
|
audio.info.size = dsize;
|
||||||
audio.body = filename.toStdString();
|
audio.body = filename.toStdString();
|
||||||
audio.url = url.toStdString();
|
audio.url = url.toStdString();
|
||||||
|
audio.file = file;
|
||||||
models.value(roomid)->sendMessage(audio);
|
models.value(roomid)->sendMessage(audio);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::queueVideoMessage(const QString &roomid,
|
TimelineViewManager::queueVideoMessage(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
const boost::optional<mtx::crypto::EncryptedFile> &file,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &mime,
|
const QString &mime,
|
||||||
uint64_t dsize)
|
uint64_t dsize)
|
||||||
|
@ -399,5 +287,6 @@ TimelineViewManager::queueVideoMessage(const QString &roomid,
|
||||||
video.info.size = dsize;
|
video.info.size = dsize;
|
||||||
video.body = filename.toStdString();
|
video.body = filename.toStdString();
|
||||||
video.url = url.toStdString();
|
video.url = url.toStdString();
|
||||||
|
video.file = file;
|
||||||
models.value(roomid)->sendMessage(video);
|
models.value(roomid)->sendMessage(video);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <mtx/common.hpp>
|
||||||
#include <mtx/responses.hpp>
|
#include <mtx/responses.hpp>
|
||||||
|
|
||||||
#include "Cache.h"
|
#include "Cache.h"
|
||||||
|
@ -35,38 +36,13 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE TimelineModel *activeTimeline() const { return timeline_; }
|
Q_INVOKABLE TimelineModel *activeTimeline() const { return timeline_; }
|
||||||
Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; }
|
Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; }
|
||||||
void openImageOverlay(QString mxcUrl,
|
Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId) const;
|
||||||
QString originalFilename,
|
|
||||||
QString mimeType,
|
|
||||||
qml_mtx_events::EventType eventType) const;
|
|
||||||
void saveMedia(QString mxcUrl,
|
|
||||||
QString originalFilename,
|
|
||||||
QString mimeType,
|
|
||||||
qml_mtx_events::EventType eventType) const;
|
|
||||||
Q_INVOKABLE void cacheMedia(QString mxcUrl, QString mimeType);
|
|
||||||
// Qml can only pass enum as int
|
|
||||||
Q_INVOKABLE void openImageOverlay(QString mxcUrl,
|
|
||||||
QString originalFilename,
|
|
||||||
QString mimeType,
|
|
||||||
int eventType) const
|
|
||||||
{
|
|
||||||
openImageOverlay(
|
|
||||||
mxcUrl, originalFilename, mimeType, (qml_mtx_events::EventType)eventType);
|
|
||||||
}
|
|
||||||
Q_INVOKABLE void saveMedia(QString mxcUrl,
|
|
||||||
QString originalFilename,
|
|
||||||
QString mimeType,
|
|
||||||
int eventType) const
|
|
||||||
{
|
|
||||||
saveMedia(mxcUrl, originalFilename, mimeType, (qml_mtx_events::EventType)eventType);
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void clearRoomMessageCount(QString roomid);
|
void clearRoomMessageCount(QString roomid);
|
||||||
void updateRoomsLastMessage(QString roomid, const DescInfo &info);
|
void updateRoomsLastMessage(QString roomid, const DescInfo &info);
|
||||||
void activeTimelineChanged(TimelineModel *timeline);
|
void activeTimelineChanged(TimelineModel *timeline);
|
||||||
void initialSyncChanged(bool isInitialSync);
|
void initialSyncChanged(bool isInitialSync);
|
||||||
void mediaCached(QString mxcUrl, QString cacheUrl);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
|
void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
|
||||||
|
@ -80,22 +56,26 @@ public slots:
|
||||||
void queueEmoteMessage(const QString &msg);
|
void queueEmoteMessage(const QString &msg);
|
||||||
void queueImageMessage(const QString &roomid,
|
void queueImageMessage(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
const boost::optional<mtx::crypto::EncryptedFile> &file,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &mime,
|
const QString &mime,
|
||||||
uint64_t dsize,
|
uint64_t dsize,
|
||||||
const QSize &dimensions);
|
const QSize &dimensions);
|
||||||
void queueFileMessage(const QString &roomid,
|
void queueFileMessage(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
const boost::optional<mtx::crypto::EncryptedFile> &file,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &mime,
|
const QString &mime,
|
||||||
uint64_t dsize);
|
uint64_t dsize);
|
||||||
void queueAudioMessage(const QString &roomid,
|
void queueAudioMessage(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
const boost::optional<mtx::crypto::EncryptedFile> &file,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &mime,
|
const QString &mime,
|
||||||
uint64_t dsize);
|
uint64_t dsize);
|
||||||
void queueVideoMessage(const QString &roomid,
|
void queueVideoMessage(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
const boost::optional<mtx::crypto::EncryptedFile> &file,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &mime,
|
const QString &mime,
|
||||||
uint64_t dsize);
|
uint64_t dsize);
|
||||||
|
|
Loading…
Reference in New Issue