Merge branch '0.7.0-dev' of ssh://github.com/Nheko-Reborn/nheko into 0.7.0-dev

This commit is contained in:
Joseph Donofry 2020-01-28 19:20:51 -05:00
commit d6d4076d36
No known key found for this signature in database
GPG Key ID: E8A1D78EF044B0CB
44 changed files with 2100 additions and 1216 deletions

View File

@ -3,9 +3,6 @@
set -ex set -ex
if [ "$TRAVIS_OS_NAME" = "osx" ]; then if [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew tap nlohmann/json
brew install --with-cmake nlohmann_json
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
sudo python get-pip.py sudo python get-pip.py
@ -25,11 +22,4 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
wget https://cmake.org/files/v3.15/cmake-3.15.5-Linux-x86_64.sh wget https://cmake.org/files/v3.15/cmake-3.15.5-Linux-x86_64.sh
sudo sh cmake-3.15.5-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
( cd build-libsodium
curl -L https://download.libsodium.org/libsodium/releases/libsodium-1.0.17.tar.gz -o libsodium-1.0.17.tar.gz
tar xfz libsodium-1.0.17.tar.gz
cd libsodium-1.0.17/
./configure && make && sudo make install )
fi fi

View File

@ -19,19 +19,32 @@ if [ "$TRAVIS_OS_NAME" = "osx" ]; then
export CMAKE_PREFIX_PATH=/usr/local/opt/qt5 export CMAKE_PREFIX_PATH=/usr/local/opt/qt5
fi fi
# Build & install dependencies mkdir -p .deps/usr .hunter
cmake -GNinja -Hdeps -B.deps \
-DUSE_BUNDLED_BOOST="${USE_BUNDLED_BOOST}" \
-DUSE_BUNDLED_CMARK="${USE_BUNDLED_CMARK}" \
-DUSE_BUNDLED_JSON="${USE_BUNDLED_JSON}" \
-DMTX_STATIC="${MTX_STATIC:-OFF}"
cmake --build .deps
# Build nheko # Build nheko
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
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? -DHUNTER_ROOT=".hunter" \
-DHUNTER_ENABLED=ON -DBUILD_SHARED_LIBS=OFF \
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DHUNTER_CONFIGURATION_TYPES=RelWithDebInfo \
-DUSE_BUNDLED_OPENSSL=OFF \
-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl \
-DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include \
-DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 \
-DCI_BUILD=ON
else
cmake -GNinja -H. -Bbuild \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_INSTALL_PREFIX=.deps/usr \
-DHUNTER_ROOT=".hunter" \
-DHUNTER_ENABLED=ON -DBUILD_SHARED_LIBS=OFF \
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DHUNTER_CONFIGURATION_TYPES=RelWithDebInfo \
-DUSE_BUNDLED_OPENSSL=OFF \
-DCI_BUILD=ON
fi
cmake --build build cmake --build build
if [ "$TRAVIS_OS_NAME" = "osx" ]; then if [ "$TRAVIS_OS_NAME" = "osx" ]; then

View File

@ -13,7 +13,7 @@ notifications:
cache: cache:
directories: directories:
- .deps - .hunter
matrix: matrix:
include: include:
@ -23,21 +23,12 @@ matrix:
osx_image: xcode10.2 osx_image: xcode10.2
env: env:
- DEPLOYMENT=1 - DEPLOYMENT=1
- USE_BUNDLED_BOOST=0
- USE_BUNDLED_CMARK=0
- USE_BUNDLED_JSON=0
- MTX_STATIC=1
addons: addons:
homebrew: homebrew:
taps: nlohmann/json taps: nlohmann/json
packages: packages:
- boost
- clang-format - clang-format
- cmake - cmake
- cmark
- icu4c
- libsodium
- lmdb
- ninja - ninja
- openssl - openssl
- qt5 - qt5
@ -48,9 +39,6 @@ matrix:
- CC=gcc-7 - CC=gcc-7
- QT_PKG=512 - QT_PKG=512
- DEPLOYMENT=1 - DEPLOYMENT=1
- USE_BUNDLED_BOOST=1
- USE_BUNDLED_CMARK=1
- USE_BUNDLED_JSON=1
addons: addons:
apt: apt:
sources: sources:
@ -73,9 +61,6 @@ matrix:
- CXX=g++-8 - CXX=g++-8
- CC=gcc-8 - CC=gcc-8
- QT_PKG=59 - QT_PKG=59
- USE_BUNDLED_BOOST=1
- USE_BUNDLED_CMARK=1
- USE_BUNDLED_JSON=1
addons: addons:
apt: apt:
sources: sources:
@ -98,9 +83,6 @@ matrix:
- CXX=clang++-6.0 - CXX=clang++-6.0
- CC=clang-6.0 - CC=clang-6.0
- QT_PKG=59 - QT_PKG=59
- USE_BUNDLED_BOOST=1
- USE_BUNDLED_CMARK=1
- USE_BUNDLED_JSON=1
addons: addons:
apt: apt:
sources: sources:

View File

@ -1,17 +1,83 @@
cmake_minimum_required(VERSION 3.11) cmake_minimum_required(VERSION 3.13)
option(APPVEYOR_BUILD "Build on appveyor" OFF) option(APPVEYOR_BUILD "Build on appveyor" OFF)
option(CI_BUILD "Set when building in CI. Enables -Werror where possible" OFF)
option(ASAN "Compile with address sanitizers" OFF) option(ASAN "Compile with address sanitizers" OFF)
option(QML_DEBUGGING "Enable qml debugging" OFF) option(QML_DEBUGGING "Enable qml debugging" OFF)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) set(
CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/toolchain.cmake"
CACHE
FILEPATH "Default toolchain"
)
option(HUNTER_ENABLED "Enable Hunter package manager" OFF)
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.244.tar.gz"
SHA1 "2c0f491fd0b80f7b09e3d21adb97237161ef9835"
LOCAL
)
option(USE_BUNDLED_BOOST "Use the bundled version of Boost." ${HUNTER_ENABLED})
option(USE_BUNDLED_SPDLOG "Use the bundled version of spdlog."
${HUNTER_ENABLED})
option(USE_BUNDLED_OLM "Use the bundled version of libolm." ${HUNTER_ENABLED})
option(USE_BUNDLED_GTEST "Use the bundled version of Google Test."
${HUNTER_ENABLED})
option(USE_BUNDLED_CMARK "Use the bundled version of cmark."
${HUNTER_ENABLED})
option(USE_BUNDLED_JSON "Use the bundled version of nlohmann json."
${HUNTER_ENABLED})
option(USE_BUNDLED_OPENSSL "Use the bundled version of OpenSSL."
${HUNTER_ENABLED})
option(USE_BUNDLED_MTXCLIENT "Use the bundled version of the Matrix Client library." ${HUNTER_ENABLED})
option(USE_BUNDLED_SODIUM "Use the bundled version of libsodium."
${HUNTER_ENABLED})
option(USE_BUNDLED_ZLIB "Use the bundled version of zlib."
${HUNTER_ENABLED})
option(USE_BUNDLED_LMDB "Use the bundled version of lmdb."
${HUNTER_ENABLED})
option(USE_BUNDLED_LMDBXX "Use the bundled version of lmdb++."
${HUNTER_ENABLED})
option(USE_BUNDLED_TWEENY "Use the bundled version of tweeny."
${HUNTER_ENABLED})
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
if(${CMAKE_VERSION} VERSION_LESS "3.14.0")
message("Adding FetchContent_MakeAvailable")
# from cmakes sources
macro(FetchContent_MakeAvailable)
foreach(contentName IN ITEMS ${ARGV})
string(TOLOWER ${contentName} contentNameLower)
FetchContent_GetProperties(${contentName})
if(NOT ${contentNameLower}_POPULATED)
FetchContent_Populate(${contentName})
# Only try to call add_subdirectory() if the populated content
# can be treated that way. Protecting the call with the check
# allows this function to be used for projects that just want
# to ensure the content exists, such as to provide content at
# a known location.
if(EXISTS ${${contentNameLower}_SOURCE_DIR}/CMakeLists.txt)
add_subdirectory(${${contentNameLower}_SOURCE_DIR}
${${contentNameLower}_BINARY_DIR})
endif()
endif()
endforeach()
endmacro()
endif()
include(GNUInstallDirs) include(GNUInstallDirs)
# Include Qt basic functions # Include Qt basic functions
include(QtCommon) include(QtCommon)
project(nheko LANGUAGES C CXX) project(nheko LANGUAGES CXX C)
set(CPACK_PACKAGE_VERSION_MAJOR "0") set(CPACK_PACKAGE_VERSION_MAJOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "7") set(CPACK_PACKAGE_VERSION_MINOR "7")
set(CPACK_PACKAGE_VERSION_PATCH "0") set(CPACK_PACKAGE_VERSION_PATCH "0")
@ -30,10 +96,6 @@ set(IDENTIFIER "com.github.mujx.nheko")
add_project_meta(META_FILES_TO_INCLUDE) add_project_meta(META_FILES_TO_INCLUDE)
if(APPLE)
set(OPENSSL_ROOT_DIR /usr/local/opt/openssl)
endif()
if(NOT MSVC AND NOT APPLE) if(NOT MSVC AND NOT APPLE)
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
@ -62,7 +124,14 @@ endif()
# #
# LMDB # LMDB
# #
include(LMDB) #include(LMDB)
if(USE_BUNDLED_LMDB)
hunter_add_package(lmdb)
find_package(liblmdb CONFIG REQUIRED)
else()
include(FindPkgConfig)
pkg_search_module(lmdb REQUIRED IMPORTED_TARGET lmdb)
endif()
# #
# Discover Qt dependencies. # Discover Qt dependencies.
@ -76,21 +145,12 @@ if (APPLE)
endif(APPLE) endif(APPLE)
if (Qt5Widgets_FOUND) if (Qt5Widgets_FOUND)
if (Qt5Widgets_VERSION VERSION_LESS 5.7.0) if (Qt5Widgets_VERSION VERSION_LESS 5.9.0)
message(STATUS "Qt version ${Qt5Widgets_VERSION}") message(STATUS "Qt version ${Qt5Widgets_VERSION}")
message(WARNING "Minimum supported Qt5 version is 5.7!") message(WARNING "Minimum supported Qt5 version is 5.9!")
endif() endif()
endif(Qt5Widgets_FOUND) endif(Qt5Widgets_FOUND)
#
# Set up compiler flags.
#
if (NOT MSVC)
set(CMAKE_C_COMPILER gcc)
endif(NOT MSVC)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(NOT MSVC) if(NOT MSVC)
set( set(
@ -98,7 +158,6 @@ if(NOT MSVC)
"${CMAKE_CXX_FLAGS} \ "${CMAKE_CXX_FLAGS} \
-Wall \ -Wall \
-Wextra \ -Wextra \
-Werror \
-pipe \ -pipe \
-pedantic \ -pedantic \
-fsized-deallocation \ -fsized-deallocation \
@ -247,63 +306,118 @@ set(SRC_FILES
src/UserSettingsPage.cpp src/UserSettingsPage.cpp
src/WelcomePage.cpp src/WelcomePage.cpp
src/main.cpp src/main.cpp
) )
# ExternalProject dependencies
set(EXTERNAL_PROJECT_DEPS "")
include(FeatureSummary) include(FeatureSummary)
set(Boost_USE_STATIC_LIBS OFF) if(USE_BUNDLED_BOOST)
set(Boost_USE_STATIC_RUNTIME OFF) hunter_add_package(Boost COMPONENTS iostreams system thread)
set(Boost_USE_MULTITHREADED ON) endif()
find_package(Boost 1.70 REQUIRED find_package(Boost 1.70 REQUIRED
COMPONENTS atomic COMPONENTS iostreams
chrono
date_time
iostreams
random
regex
system system
thread) thread)
if(USE_BUNDLED_ZLIB)
hunter_add_package(ZLIB)
endif()
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
if(USE_BUNDLED_OPENSSL)
hunter_add_package(OpenSSL)
endif()
find_package(OpenSSL REQUIRED) find_package(OpenSSL REQUIRED)
find_package(MatrixClient 0.3.0 REQUIRED) if(USE_BUNDLED_MTXCLIENT)
find_package(Olm 2 REQUIRED) include(FetchContent)
set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "")
set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
FetchContent_Declare(
MatrixClient
GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
GIT_TAG 03b5008a05f895e91e3968de7b68db50f6c41b2a
)
FetchContent_MakeAvailable(MatrixClient)
else()
find_package(MatrixClient 0.3.0 REQUIRED)
endif()
if(USE_BUNDLED_OLM)
include(FetchContent)
set(OLM_TESTS OFF CACHE INTERNAL "")
FetchContent_Declare(
Olm
GIT_REPOSITORY https://gitlab.matrix.org/matrix-org/olm.git
GIT_TAG 3.1.4
)
FetchContent_MakeAvailable(Olm)
else()
find_package(Olm 3)
set_package_properties(Olm PROPERTIES
DESCRIPTION "An implementation of the Double Ratchet cryptographic ratchet"
URL "https://git.matrix.org/git/olm/about/"
TYPE REQUIRED
)
endif()
if(USE_BUNDLED_SPDLOG)
hunter_add_package(spdlog)
endif()
find_package(spdlog 1.0.0 CONFIG REQUIRED) find_package(spdlog 1.0.0 CONFIG REQUIRED)
find_package(cmark REQUIRED)
if(USE_BUNDLED_CMARK)
include(FetchContent)
FetchContent_Declare(
cmark
GIT_REPOSITORY https://github.com/commonmark/cmark.git
GIT_TAG 242e277a661ec7e51f34dcaf86c1925d550b1498 #0.29.0 << doesn't work with fetch content yet
CMAKE_ARGS "CMARK_STATIC=ON CMARK_SHARED=OFF CMARK_TESTS=OFF CMARK_TESTS=OFF"
)
FetchContent_MakeAvailable(cmark)
if (MSVC)
add_library(cmark::cmark ALIAS libcmark)
else()
add_library(cmark::cmark ALIAS libcmark_static)
endif()
else()
find_package(cmark REQUIRED)
endif()
if(USE_BUNDLED_JSON)
hunter_add_package(nlohmann_json)
endif()
find_package(nlohmann_json 3.2.0) find_package(nlohmann_json 3.2.0)
set_package_properties(nlohmann_json PROPERTIES set_package_properties(nlohmann_json PROPERTIES
DESCRIPTION "JSON for Modern C++, a C++11 header-only JSON class" DESCRIPTION "JSON for Modern C++, a C++11 header-only JSON class"
URL "https://nlohmann.github.io/json/" URL "https://nlohmann.github.io/json/"
TYPE REQUIRED TYPE REQUIRED
) )
if(NOT LMDBXX_INCLUDE_DIR) if(USE_BUNDLED_LMDBXX)
hunter_add_package(lmdbxx)
find_package(lmdbxx CONFIG REQUIRED)
else()
if(NOT LMDBXX_INCLUDE_DIR)
find_path(LMDBXX_INCLUDE_DIR find_path(LMDBXX_INCLUDE_DIR
NAMES lmdb++.h NAMES lmdb++.h
PATHS /usr/include PATHS /usr/include
/usr/local/include /usr/local/include
$ENV{LIB_DIR}/include $ENV{LIB_DIR}/include
$ENV{LIB_DIR}/include/lmdbxx) $ENV{LIB_DIR}/include/lmdbxx)
endif()
add_library(lmdbxx INTERFACE)
target_include_directories(lmdbxx INTERFACE ${LMDBXX_INCLUDE_DIR})
add_library(lmdbxx::lmdbxx ALIAS lmdbxx)
endif() endif()
include_directories(SYSTEM ${LMDBXX_INCLUDE_DIR})
if(NOT TWEENY_INCLUDE_DIR) if(USE_BUNDLED_TWEENY)
find_path(TWEENY_INCLUDE_DIR include(FetchContent)
NAMES tweeny/tweeny.h FetchContent_Declare(
PATHS /usr/include/ Tweeny
/usr/local/include/ GIT_REPOSITORY https://github.com/mobius3/tweeny.git
$ENV{LIB_DIR}/include/ GIT_TAG 6a5033372fe53c4c731c66c8a2d56261746cd85c #v3 <- v3 has unfixed warnings
$ENV{LIB_DIR}/include/tweeny) )
FetchContent_MakeAvailable(Tweeny)
else()
find_package(Tweeny REQUIRED)
endif() endif()
include_directories(SYSTEM ${TWEENY_INCLUDE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/src)
include_directories(${Boost_INCLUDE_DIRS})
# local inclue directory
include_directories(includes)
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
@ -381,7 +495,7 @@ qt5_wrap_cpp(MOC_HEADERS
src/UserInfoWidget.h src/UserInfoWidget.h
src/UserSettingsPage.h src/UserSettingsPage.h
src/WelcomePage.h src/WelcomePage.h
) )
# #
# Bundle translations. # Bundle translations.
@ -389,26 +503,6 @@ qt5_wrap_cpp(MOC_HEADERS
include(Translations) include(Translations)
set(TRANSLATION_DEPS ${LANG_QRC} ${QRC} ${QM_SRC}) set(TRANSLATION_DEPS ${LANG_QRC} ${QRC} ${QM_SRC})
set(COMMON_LIBS
MatrixClient::MatrixClient
${Boost_LIBRARIES}
cmark::cmark
Qt5::Widgets
Qt5::Svg
Qt5::Concurrent
Qt5::Multimedia
Qt5::Qml
Qt5::QuickControls2
Qt5::QuickWidgets
nlohmann_json::nlohmann_json
spdlog::spdlog)
if(APPVEYOR_BUILD)
set(NHEKO_LIBS ${COMMON_LIBS} lmdb)
else()
set(NHEKO_LIBS ${COMMON_LIBS} ${LMDB_LIBRARY})
endif()
if (APPLE) if (APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Foundation -framework Cocoa") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Foundation -framework Cocoa")
set(SRC_FILES ${SRC_FILES} src/notifications/ManagerMac.mm src/emoji/MacHelper.mm) set(SRC_FILES ${SRC_FILES} src/notifications/ManagerMac.mm src/emoji/MacHelper.mm)
@ -439,24 +533,54 @@ if(ASAN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined")
endif() endif()
add_executable (nheko ${OS_BUNDLE} ${NHEKO_DEPS})
if(APPLE) if(APPLE)
add_executable (nheko ${OS_BUNDLE} ${NHEKO_DEPS}) target_link_libraries (nheko PRIVATE Qt5::MacExtras)
target_link_libraries (nheko ${NHEKO_LIBS} Qt5::MacExtras)
elseif(WIN32) elseif(WIN32)
add_executable (nheko ${OS_BUNDLE} ${ICON_FILE} ${NHEKO_DEPS})
target_compile_definitions(nheko PRIVATE WIN32_LEAN_AND_MEAN) target_compile_definitions(nheko PRIVATE WIN32_LEAN_AND_MEAN)
target_link_libraries (nheko ${NTDLIB} ${NHEKO_LIBS} Qt5::WinMain) target_link_libraries (nheko PRIVATE ${NTDLIB} Qt5::WinMain)
else() else()
add_executable (nheko ${OS_BUNDLE} ${NHEKO_DEPS}) target_link_libraries (nheko PRIVATE Qt5::DBus)
target_link_libraries (nheko ${NHEKO_LIBS} Qt5::DBus)
endif() endif()
target_include_directories(nheko PRIVATE src includes)
target_link_libraries(nheko PRIVATE
MatrixClient::MatrixClient
Boost::iostreams
Boost::system
Boost::thread
cmark::cmark
spdlog::spdlog
Qt5::Widgets
Qt5::Svg
Qt5::Concurrent
Qt5::Multimedia
Qt5::Qml
Qt5::QuickControls2
Qt5::QuickWidgets
nlohmann_json::nlohmann_json
lmdbxx::lmdbxx
tweeny)
if(USE_BUNDLED_LMDB)
target_link_libraries(nheko PRIVATE liblmdb::lmdb)
if(MSVC)
target_link_libraries(nheko PRIVATE ntdll)
endif()
else()
target_link_libraries(nheko PRIVATE PkgConfig::lmdb)
endif()
if(QML_DEBUGGING) if(QML_DEBUGGING)
target_compile_definitions(nheko PRIVATE QML_DEBUGGING) target_compile_definitions(nheko PRIVATE QML_DEBUGGING)
endif() endif()
if(EXTERNAL_PROJECT_DEPS)
add_dependencies(nheko ${EXTERNAL_PROJECT_DEPS}) if(NOT MSVC)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug" OR CI_BUILD)
target_compile_options(nheko PRIVATE "-Werror")
endif()
endif() endif()
set_target_properties(nheko PROPERTIES SKIP_BUILD_RPATH TRUE) set_target_properties(nheko PROPERTIES SKIP_BUILD_RPATH TRUE)

108
README.md
View File

@ -19,18 +19,20 @@ Help us with translations so as many people as possible will be able to use nhek
### Note regarding End-to-End encryption ### Note regarding End-to-End encryption
Currently the implementation is at best a **proof of concept** and it should only be used for Currently the implementation is at best a **proof of concept** and it should only be used for
testing purposes. testing purposes. Most importantly, it is missing device verification, so while your messages
and media are encrypted, nheko doesn't verify who gets the messages.
## Features ## Features
Most of the features you would expect from a chat application are missing right now Most of the features you would expect from a chat application are missing right now
but we are getting close to a more feature complete client. but we are getting close to a more feature complete client.
Specifically there is support for: Specifically there is support for:
- E2E encryption (text messages only: attachments are currently sent unencrypted). - E2E encryption.
- User registration. - User registration.
- Creating, joining & leaving rooms. - Creating, joining & leaving rooms.
- Sending & receiving invites. - Sending & receiving invites.
- Sending & receiving files and emoji (inline widgets for images, audio and file messages). - Sending & receiving files and emoji (inline widgets for images, audio and file messages).
- Replies with text, images and other media (and actually render them as inline widgets).
- Typing notifications. - Typing notifications.
- Username auto-completion. - Username auto-completion.
- Message & mention notifications. - Message & mention notifications.
@ -61,7 +63,7 @@ sudo dnf install nheko
#### Gentoo Linux #### Gentoo Linux
```bash ```bash
sudo layman -a matrix sudo eselect repository enable matrix
sudo emerge -a nheko sudo emerge -a nheko
``` ```
@ -105,6 +107,27 @@ sudo port install nheko
- GCC 7 (tested on Travis CI) - GCC 7 (tested on Travis CI)
- MSVC 19.13 (tested on AppVeyor) - MSVC 19.13 (tested on AppVeyor)
Nheko can use bundled version for most of those libraries automatically, if the versions in your distro are too old.
To use them, you can enable the hunter integration by passing `-DHUNTER_ENABLED=ON`.
It is probably wise to link those dependencies statically by passing `-DBUILD_SHARED_LIBS=OFF`
You can select which bundled dependencies you want to use py passing various `-DUSE_BUNDLED_*` flags. By default all dependencies are bundled *if* you enable hunter.
The bundle flags are currently:
- USE_BUNDLED_BOOST
- USE_BUNDLED_SPDLOG
- USE_BUNDLED_OLM
- USE_BUNDLED_GTEST
- USE_BUNDLED_CMARK
- USE_BUNDLED_JSON
- USE_BUNDLED_OPENSSL
- USE_BUNDLED_MTXCLIENT
- USE_BUNDLED_SODIUM
- USE_BUNDLED_ZLIB
- USE_BUNDLED_LMDB
- USE_BUNDLED_LMDBXX
- USE_BUNDLED_TWEENY
#### Linux #### Linux
If you don't want to install any external dependencies, you can generate an AppImage locally using docker. If you don't want to install any external dependencies, you can generate an AppImage locally using docker.
@ -145,6 +168,17 @@ sudo apt-get update
sudo apt-get install -y g++-7 qt59base qt59svg qt59tools qt59multimedia cmake liblmdb-dev libsodium-dev sudo apt-get install -y g++-7 qt59base qt59svg qt59tools qt59multimedia cmake liblmdb-dev libsodium-dev
``` ```
##### Debian Buster (or higher probably)
(User report, not sure if all of those are needed)
```bash
sudo apt install cmake gcc make automake liblmdb-dev libsodium-dev \
qt5-default libssl-dev libqt5multimedia5-plugins libqt5multimediagsttools5 libqt5multimediaquick5 libqt5svg5-dev \
qml-module-qtgstreamer qtmultimedia5-dev qtquickcontrols2-5-dev qttools5-dev qttools5-dev-tools \
qml-module-qtgraphicaleffects qml-module-qtmultimedia qml-module-qtquick-controls2 qml-module-qtquick-layouts
```
##### macOS (Xcode 10.2 or later) ##### macOS (Xcode 10.2 or later)
```bash ```bash
@ -158,61 +192,29 @@ brew install qt5 lmdb cmake llvm libsodium spdlog boost cmark
(for the CMake integration) workloads. (for the CMake integration) workloads.
2. Download the latest Qt for windows installer and install it somewhere. 2. Download the latest Qt for windows installer and install it somewhere.
Make sure to install the `MSVC 2017 64-bit` toolset for at least Qt 5.9 Make sure to install the `MSVC 2017 64-bit` toolset for at least Qt 5.10
(lower versions does not support VS2017). (lower versions does not support VS2017).
3. Install dependencies with `vcpkg`. You can simply clone it into a subfolder 3. If you don't have openssl installed, you will need to install perl to build it (i.e. Strawberry Perl).
of the root nheko source directory.
```powershell
git clone http:\\github.com\Microsoft\vcpkg
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg install --triplet x64-windows \
boost-asio \
boost-beast \
boost-iostreams \
boost-random \
boost-signals2 \
boost-system \
boost-thread \
cmark \
libsodium \
lmdb \
openssl \
zlib
```
4. Install dependencies not managed by vcpkg. (libolm, libmtxclient, libmatrix_structs)
Inside the project root run the following (replacing the path to vcpkg as necessary).
```bash
cmake -G "Visual Studio 15 2017 Win64" -Hdeps -B.deps
-DCMAKE_TOOLCHAIN_FILE=C:/Users/<your-path>/vcpkg/scripts/buildsystems/vcpkg.cmake
-DUSE_BUNDLED_BOOST=OFF
cmake --build .deps --config Release
cmake --build .deps --config Debug
```
### Building ### Building
First we need to install the rest of the dependencies that are not available in our system We can now build nheko:
```bash ```bash
cmake -Hdeps -B.deps \ cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release
-DUSE_BUNDLED_BOOST=OFF # if we already have boost & spdlog installed.
-DUSE_BUNDLED_SPDLOG=OFF
cmake --build .deps
```
We can now build nheko by pointing it to the path that we installed the dependencies.
```bash
cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=.deps/usr
cmake --build build cmake --build build
``` ```
To use bundled dependencies you can use hunter, i.e.:
```bash
cmake -H. -Bbuild -DHUNTER_ENABLED=ON -DBUILD_SHARED_LIBS=OFF -DUSE_BUNDLED_OPENSSL=OFF
cmake --build build --config Release
```
Adapt the USE_BUNDLED_* as needed.
If the build fails with the following error If the build fails with the following error
``` ```
Could not find a package configuration file provided by "Qt5Widgets" with Could not find a package configuration file provided by "Qt5Widgets" with
@ -237,13 +239,14 @@ The `nheko` binary will be located in the `build` directory.
After installing all dependencies, you need to edit the `CMakeSettings.json` to After installing all dependencies, you need to edit the `CMakeSettings.json` to
be able to load and compile nheko within Visual Studio. be able to load and compile nheko within Visual Studio.
You need to fill out the paths for the `CMAKE_TOOLCHAIN_FILE` and the `Qt5_DIR`. You need to fill out the paths for the `Qt5_DIR`.
The toolchain file should point to the `vcpkg.cmake` and the Qt5 dir to the `lib\cmake\Qt5` dir. The Qt5 dir should point to the `lib\cmake\Qt5` dir.
Examples for the paths are: Examples for the paths are:
- `C:\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake`
- `C:\\Qt\\5.10.1\\msvc2017_64\\lib\\cmake\\Qt5` - `C:\\Qt\\5.10.1\\msvc2017_64\\lib\\cmake\\Qt5`
You should also enable hunter by setting `HUNTER_ENABLED` to `ON` and `BUILD_SHARED_LIBS` to `OFF`.
Now right click into the root nheko source directory and choose `Open in Visual Studio`. Now right click into the root nheko source directory and choose `Open in Visual Studio`.
You can choose the build type Release and Debug in the top toolbar. You can choose the build type Release and Debug in the top toolbar.
After a successful CMake generation you can select the `nheko.exe` as the run target. After a successful CMake generation you can select the `nheko.exe` as the run target.
@ -261,6 +264,9 @@ windeployqt nheko.exe
The final binary will be located inside `build-vc\Release\Release` for the Release build The final binary will be located inside `build-vc\Release\Release` for the Release build
and `build-vc\Debug\Debug` for the Debug build. and `build-vc\Debug\Debug` for the Debug build.
Also copy the respective cmark.dll to the binary dir from `build/cmark-build/src/Release` (or Debug).
### Contributing ### Contributing
See [CONTRIBUTING](.github/CONTRIBUTING.md) See [CONTRIBUTING](.github/CONTRIBUTING.md)

View File

@ -1,9 +1,9 @@
--- ---
version: 0.6.4-{build} version: 0.7.0-{build}
configuration: Release configuration: Release
image: Visual Studio 2019 image: Visual Studio 2017
platform: x64 platform: x64
environment: environment:
@ -11,32 +11,16 @@ environment:
secure: "iGl5mzE9/ta9kFELUxDw9XtlYMSCMai9xowXIkYzU8WKHz7NfW0mLwMJZvblZFXJ" secure: "iGl5mzE9/ta9kFELUxDw9XtlYMSCMai9xowXIkYzU8WKHz7NfW0mLwMJZvblZFXJ"
cache: cache:
- c:\tools\vcpkg\installed\ -> appveyor.yml - c:\hunter\ -> appveyor.yml
# - .deps -> appveyor.yml,deps\CMakeLists.txt <- disabled because it randomly seems to break everytime - build\_deps -> appveyor.yml,deps\CMakeLists.txt
build: build:
verbosity: minimal verbosity: minimal
install: install:
- set QT_DIR=C:\Qt\5.14\msvc2017_64 - set QT_DIR=C:\Qt\5.13\msvc2017_64
- set PATH=%PATH%;%QT_DIR%\bin;C:\MinGW\bin - set PATH=%PATH%;%QT_DIR%\bin
- set PATH=%PATH%;C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev1\mingw64\bin - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
- cd "C:\Tools\vcpkg"&& git pull && .\bootstrap-vcpkg.bat && cd %APPVEYOR_BUILD_FOLDER%
- vcpkg install
nlohmann-json:%PLATFORM%-windows
boost-asio:%PLATFORM%-windows
boost-beast:%PLATFORM%-windows
boost-iostreams:%PLATFORM%-windows
boost-random:%PLATFORM%-windows
boost-signals2:%PLATFORM%-windows
boost-system:%PLATFORM%-windows
boost-thread:%PLATFORM%-windows
libsodium:%PLATFORM%-windows
lmdb:%PLATFORM%-windows
openssl:%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
@ -57,23 +41,13 @@ build_script:
- echo %INSTVERSION% - echo %INSTVERSION%
- echo %DATE% - echo %DATE%
# Build & install the dependencies
- cmake -G "Visual Studio 16 2019" -A x64 -Hdeps -B.deps
-DCMAKE_TOOLCHAIN_FILE=C:/Tools/vcpkg/scripts/buildsystems/vcpkg.cmake
-DUSE_BUNDLED_BOOST=OFF
-DUSE_BUNDLED_JSON=OFF
-DMTX_STATIC=ON
- cmake --build .deps --config Release
# Build nheko # Build nheko
- rm -f cmake/FindOlm.cmake #- cmake -G "Visual Studio 16 2019" -A x64 -H. -Bbuild
- cmake -G "Visual Studio 16 2019" -A x64 -H. -Bbuild - cmake -G "Visual Studio 15 2017 Win64" -H. -Bbuild
-DCMAKE_TOOLCHAIN_FILE=C:/Tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DHUNTER_ROOT="C:\hunter"
-DLMDBXX_INCLUDE_DIR=.deps/usr/include -DHUNTER_ENABLED=ON -DBUILD_SHARED_LIBS=OFF
-DTWEENY_INCLUDE_DIR=.deps/usr/include -DCMAKE_BUILD_TYPE=Release -DHUNTER_CONFIGURATION_TYPES=Release
-DCMARK_INCLUDE_DIR=C:/projects/nheko/.deps/usr/include
-DCMARK_LIBRARY=C:/projects/nheko/.deps/usr/lib/cmark.lib
-DJSON_INCLUDE_DIR=.deps/usr/include
- cmake --build build --config Release - cmake --build build --config Release
after_build: after_build:
@ -82,12 +56,9 @@ after_build:
- echo %BUILD% - echo %BUILD%
- mkdir NhekoRelease - mkdir NhekoRelease
- copy build\Release\nheko.exe NhekoRelease\nheko.exe - copy build\Release\nheko.exe NhekoRelease\nheko.exe
- copy build\_deps\cmark-build\src\Release\cmark.dll NhekoRelease\cmark.dll
- windeployqt --qmldir %QT_DIR%\qml\ --release NhekoRelease\nheko.exe - windeployqt --qmldir %QT_DIR%\qml\ --release NhekoRelease\nheko.exe
- copy C:\Tools\vcpkg\installed\x64-windows\bin\*.dll .\NhekoRelease\
- copy C:\projects\nheko\.deps\usr\bin\cmark.dll .\NhekoRelease\
- 7z a nheko_win_64.zip .\NhekoRelease\* - 7z a nheko_win_64.zip .\NhekoRelease\*
- ls -lh build\Release\ - ls -lh build\Release\
- ls -lh NhekoRelease\ - ls -lh NhekoRelease\

View File

@ -1,44 +0,0 @@
#
# CMake module to search for the olm library
#
# On success, the macro sets the following variables:
# OLM_FOUND = if the library found
# OLM_LIBRARY = full path to the library
# OLM_INCLUDE_DIR = where to find the library headers
#
if(WIN32)
message(STATUS "FindOlm is not supported in Windows")
return()
endif()
find_path(OLM_INCLUDE_DIR
NAMES olm/olm.h
PATHS /usr/include
/usr/local/include
$ENV{LIB_DIR}/include
$ENV{LIB_DIR}/include/olm)
find_library(OLM_LIBRARY
NAMES olm
PATHS /usr/lib /usr/local/lib $ENV{LIB_DIR}/lib)
if(OLM_FOUND)
set(OLM_INCLUDE_DIRS ${OLM_INCLUDE_DIR})
if(NOT OLM_LIBRARIES)
set(OLM_LIBRARIES ${OLM_LIBRARY})
endif()
endif()
if(NOT TARGET Olm::Olm)
add_library(Olm::Olm UNKNOWN IMPORTED)
set_target_properties(Olm::Olm
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
${OLM_INCLUDE_DIR})
set_property(TARGET Olm::Olm APPEND PROPERTY IMPORTED_LOCATION ${OLM_LIBRARY})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OLM DEFAULT_MSG OLM_INCLUDE_DIR OLM_LIBRARY)
mark_as_advanced(OLM_LIBRARY OLM_INCLUDE_DIR)

View File

@ -0,0 +1,5 @@
hunter_config(
Boost
VERSION "1.70.0-p0"
CMAKE_ARGS IOSTREAMS_NO_BZIP2=1
)

528
cmake/HunterGate.cmake Normal file
View File

@ -0,0 +1,528 @@
# Copyright (c) 2013-2019, Ruslan Baratov
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# This is a gate file to Hunter package manager.
# Include this file using `include` command and add package you need, example:
#
# cmake_minimum_required(VERSION 3.2)
#
# include("cmake/HunterGate.cmake")
# HunterGate(
# URL "https://github.com/path/to/hunter/archive.tar.gz"
# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d"
# )
#
# project(MyProject)
#
# hunter_add_package(Foo)
# hunter_add_package(Boo COMPONENTS Bar Baz)
#
# Projects:
# * https://github.com/hunter-packages/gate/
# * https://github.com/ruslo/hunter
option(HUNTER_ENABLED "Enable Hunter package manager support" ON)
if(HUNTER_ENABLED)
if(CMAKE_VERSION VERSION_LESS "3.2")
message(
FATAL_ERROR
"At least CMake version 3.2 required for Hunter dependency management."
" Update CMake or set HUNTER_ENABLED to OFF."
)
endif()
endif()
include(CMakeParseArguments) # cmake_parse_arguments
option(HUNTER_STATUS_PRINT "Print working status" ON)
option(HUNTER_STATUS_DEBUG "Print a lot info" OFF)
option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON)
set(HUNTER_ERROR_PAGE "https://docs.hunter.sh/en/latest/reference/errors")
function(hunter_gate_status_print)
if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG)
foreach(print_message ${ARGV})
message(STATUS "[hunter] ${print_message}")
endforeach()
endif()
endfunction()
function(hunter_gate_status_debug)
if(HUNTER_STATUS_DEBUG)
foreach(print_message ${ARGV})
string(TIMESTAMP timestamp)
message(STATUS "[hunter *** DEBUG *** ${timestamp}] ${print_message}")
endforeach()
endif()
endfunction()
function(hunter_gate_error_page error_page)
message("------------------------------ ERROR ------------------------------")
message(" ${HUNTER_ERROR_PAGE}/${error_page}.html")
message("-------------------------------------------------------------------")
message("")
message(FATAL_ERROR "")
endfunction()
function(hunter_gate_internal_error)
message("")
foreach(print_message ${ARGV})
message("[hunter ** INTERNAL **] ${print_message}")
endforeach()
message("[hunter ** INTERNAL **] [Directory:${CMAKE_CURRENT_LIST_DIR}]")
message("")
hunter_gate_error_page("error.internal")
endfunction()
function(hunter_gate_fatal_error)
cmake_parse_arguments(hunter "" "ERROR_PAGE" "" "${ARGV}")
if("${hunter_ERROR_PAGE}" STREQUAL "")
hunter_gate_internal_error("Expected ERROR_PAGE")
endif()
message("")
foreach(x ${hunter_UNPARSED_ARGUMENTS})
message("[hunter ** FATAL ERROR **] ${x}")
endforeach()
message("[hunter ** FATAL ERROR **] [Directory:${CMAKE_CURRENT_LIST_DIR}]")
message("")
hunter_gate_error_page("${hunter_ERROR_PAGE}")
endfunction()
function(hunter_gate_user_error)
hunter_gate_fatal_error(${ARGV} ERROR_PAGE "error.incorrect.input.data")
endfunction()
function(hunter_gate_self root version sha1 result)
string(COMPARE EQUAL "${root}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("root is empty")
endif()
string(COMPARE EQUAL "${version}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("version is empty")
endif()
string(COMPARE EQUAL "${sha1}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("sha1 is empty")
endif()
string(SUBSTRING "${sha1}" 0 7 archive_id)
set(
hunter_self
"${root}/_Base/Download/Hunter/${version}/${archive_id}/Unpacked"
)
set("${result}" "${hunter_self}" PARENT_SCOPE)
endfunction()
# Set HUNTER_GATE_ROOT cmake variable to suitable value.
function(hunter_gate_detect_root)
# Check CMake variable
string(COMPARE NOTEQUAL "${HUNTER_ROOT}" "" not_empty)
if(not_empty)
set(HUNTER_GATE_ROOT "${HUNTER_ROOT}" PARENT_SCOPE)
hunter_gate_status_debug("HUNTER_ROOT detected by cmake variable")
return()
endif()
# Check environment variable
string(COMPARE NOTEQUAL "$ENV{HUNTER_ROOT}" "" not_empty)
if(not_empty)
set(HUNTER_GATE_ROOT "$ENV{HUNTER_ROOT}" PARENT_SCOPE)
hunter_gate_status_debug("HUNTER_ROOT detected by environment variable")
return()
endif()
# Check HOME environment variable
string(COMPARE NOTEQUAL "$ENV{HOME}" "" result)
if(result)
set(HUNTER_GATE_ROOT "$ENV{HOME}/.hunter" PARENT_SCOPE)
hunter_gate_status_debug("HUNTER_ROOT set using HOME environment variable")
return()
endif()
# Check SYSTEMDRIVE and USERPROFILE environment variable (windows only)
if(WIN32)
string(COMPARE NOTEQUAL "$ENV{SYSTEMDRIVE}" "" result)
if(result)
set(HUNTER_GATE_ROOT "$ENV{SYSTEMDRIVE}/.hunter" PARENT_SCOPE)
hunter_gate_status_debug(
"HUNTER_ROOT set using SYSTEMDRIVE environment variable"
)
return()
endif()
string(COMPARE NOTEQUAL "$ENV{USERPROFILE}" "" result)
if(result)
set(HUNTER_GATE_ROOT "$ENV{USERPROFILE}/.hunter" PARENT_SCOPE)
hunter_gate_status_debug(
"HUNTER_ROOT set using USERPROFILE environment variable"
)
return()
endif()
endif()
hunter_gate_fatal_error(
"Can't detect HUNTER_ROOT"
ERROR_PAGE "error.detect.hunter.root"
)
endfunction()
function(hunter_gate_download dir)
string(
COMPARE
NOTEQUAL
"$ENV{HUNTER_DISABLE_AUTOINSTALL}"
""
disable_autoinstall
)
if(disable_autoinstall AND NOT HUNTER_RUN_INSTALL)
hunter_gate_fatal_error(
"Hunter not found in '${dir}'"
"Set HUNTER_RUN_INSTALL=ON to auto-install it from '${HUNTER_GATE_URL}'"
"Settings:"
" HUNTER_ROOT: ${HUNTER_GATE_ROOT}"
" HUNTER_SHA1: ${HUNTER_GATE_SHA1}"
ERROR_PAGE "error.run.install"
)
endif()
string(COMPARE EQUAL "${dir}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("Empty 'dir' argument")
endif()
string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("HUNTER_GATE_SHA1 empty")
endif()
string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("HUNTER_GATE_URL empty")
endif()
set(done_location "${dir}/DONE")
set(sha1_location "${dir}/SHA1")
set(build_dir "${dir}/Build")
set(cmakelists "${dir}/CMakeLists.txt")
hunter_gate_status_debug("Locking directory: ${dir}")
file(LOCK "${dir}" DIRECTORY GUARD FUNCTION)
hunter_gate_status_debug("Lock done")
if(EXISTS "${done_location}")
# while waiting for lock other instance can do all the job
hunter_gate_status_debug("File '${done_location}' found, skip install")
return()
endif()
file(REMOVE_RECURSE "${build_dir}")
file(REMOVE_RECURSE "${cmakelists}")
file(MAKE_DIRECTORY "${build_dir}") # check directory permissions
# Disabling languages speeds up a little bit, reduces noise in the output
# and avoids path too long windows error
file(
WRITE
"${cmakelists}"
"cmake_minimum_required(VERSION 3.2)\n"
"project(HunterDownload LANGUAGES NONE)\n"
"include(ExternalProject)\n"
"ExternalProject_Add(\n"
" Hunter\n"
" URL\n"
" \"${HUNTER_GATE_URL}\"\n"
" URL_HASH\n"
" SHA1=${HUNTER_GATE_SHA1}\n"
" DOWNLOAD_DIR\n"
" \"${dir}\"\n"
" TLS_VERIFY\n"
" ${HUNTER_TLS_VERIFY}\n"
" SOURCE_DIR\n"
" \"${dir}/Unpacked\"\n"
" CONFIGURE_COMMAND\n"
" \"\"\n"
" BUILD_COMMAND\n"
" \"\"\n"
" INSTALL_COMMAND\n"
" \"\"\n"
")\n"
)
if(HUNTER_STATUS_DEBUG)
set(logging_params "")
else()
set(logging_params OUTPUT_QUIET)
endif()
hunter_gate_status_debug("Run generate")
# Need to add toolchain file too.
# Otherwise on Visual Studio + MDD this will fail with error:
# "Could not find an appropriate version of the Windows 10 SDK installed on this machine"
if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
get_filename_component(absolute_CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE)
set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=${absolute_CMAKE_TOOLCHAIN_FILE}")
else()
# 'toolchain_arg' can't be empty
set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=")
endif()
string(COMPARE EQUAL "${CMAKE_MAKE_PROGRAM}" "" no_make)
if(no_make)
set(make_arg "")
else()
# Test case: remove Ninja from PATH but set it via CMAKE_MAKE_PROGRAM
set(make_arg "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}")
endif()
execute_process(
COMMAND
"${CMAKE_COMMAND}"
"-H${dir}"
"-B${build_dir}"
"-G${CMAKE_GENERATOR}"
"${toolchain_arg}"
${make_arg}
WORKING_DIRECTORY "${dir}"
RESULT_VARIABLE download_result
${logging_params}
)
if(NOT download_result EQUAL 0)
hunter_gate_internal_error(
"Configure project failed."
"To reproduce the error run: ${CMAKE_COMMAND} -H${dir} -B${build_dir} -G${CMAKE_GENERATOR} ${toolchain_arg} ${make_arg}"
"In directory ${dir}"
)
endif()
hunter_gate_status_print(
"Initializing Hunter workspace (${HUNTER_GATE_SHA1})"
" ${HUNTER_GATE_URL}"
" -> ${dir}"
)
execute_process(
COMMAND "${CMAKE_COMMAND}" --build "${build_dir}"
WORKING_DIRECTORY "${dir}"
RESULT_VARIABLE download_result
${logging_params}
)
if(NOT download_result EQUAL 0)
hunter_gate_internal_error("Build project failed")
endif()
file(REMOVE_RECURSE "${build_dir}")
file(REMOVE_RECURSE "${cmakelists}")
file(WRITE "${sha1_location}" "${HUNTER_GATE_SHA1}")
file(WRITE "${done_location}" "DONE")
hunter_gate_status_debug("Finished")
endfunction()
# Must be a macro so master file 'cmake/Hunter' can
# apply all variables easily just by 'include' command
# (otherwise PARENT_SCOPE magic needed)
macro(HunterGate)
if(HUNTER_GATE_DONE)
# variable HUNTER_GATE_DONE set explicitly for external project
# (see `hunter_download`)
set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES)
endif()
# First HunterGate command will init Hunter, others will be ignored
get_property(_hunter_gate_done GLOBAL PROPERTY HUNTER_GATE_DONE SET)
if(NOT HUNTER_ENABLED)
# Empty function to avoid error "unknown function"
function(hunter_add_package)
endfunction()
set(
_hunter_gate_disabled_mode_dir
"${CMAKE_CURRENT_LIST_DIR}/cmake/Hunter/disabled-mode"
)
if(EXISTS "${_hunter_gate_disabled_mode_dir}")
hunter_gate_status_debug(
"Adding \"disabled-mode\" modules: ${_hunter_gate_disabled_mode_dir}"
)
list(APPEND CMAKE_PREFIX_PATH "${_hunter_gate_disabled_mode_dir}")
endif()
elseif(_hunter_gate_done)
hunter_gate_status_debug("Secondary HunterGate (use old settings)")
hunter_gate_self(
"${HUNTER_CACHED_ROOT}"
"${HUNTER_VERSION}"
"${HUNTER_SHA1}"
_hunter_self
)
include("${_hunter_self}/cmake/Hunter")
else()
set(HUNTER_GATE_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}")
string(COMPARE NOTEQUAL "${PROJECT_NAME}" "" _have_project_name)
if(_have_project_name)
hunter_gate_fatal_error(
"Please set HunterGate *before* 'project' command. "
"Detected project: ${PROJECT_NAME}"
ERROR_PAGE "error.huntergate.before.project"
)
endif()
cmake_parse_arguments(
HUNTER_GATE "LOCAL" "URL;SHA1;GLOBAL;FILEPATH" "" ${ARGV}
)
string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" _empty_sha1)
string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" _empty_url)
string(
COMPARE
NOTEQUAL
"${HUNTER_GATE_UNPARSED_ARGUMENTS}"
""
_have_unparsed
)
string(COMPARE NOTEQUAL "${HUNTER_GATE_GLOBAL}" "" _have_global)
string(COMPARE NOTEQUAL "${HUNTER_GATE_FILEPATH}" "" _have_filepath)
if(_have_unparsed)
hunter_gate_user_error(
"HunterGate unparsed arguments: ${HUNTER_GATE_UNPARSED_ARGUMENTS}"
)
endif()
if(_empty_sha1)
hunter_gate_user_error("SHA1 suboption of HunterGate is mandatory")
endif()
if(_empty_url)
hunter_gate_user_error("URL suboption of HunterGate is mandatory")
endif()
if(_have_global)
if(HUNTER_GATE_LOCAL)
hunter_gate_user_error("Unexpected LOCAL (already has GLOBAL)")
endif()
if(_have_filepath)
hunter_gate_user_error("Unexpected FILEPATH (already has GLOBAL)")
endif()
endif()
if(HUNTER_GATE_LOCAL)
if(_have_global)
hunter_gate_user_error("Unexpected GLOBAL (already has LOCAL)")
endif()
if(_have_filepath)
hunter_gate_user_error("Unexpected FILEPATH (already has LOCAL)")
endif()
endif()
if(_have_filepath)
if(_have_global)
hunter_gate_user_error("Unexpected GLOBAL (already has FILEPATH)")
endif()
if(HUNTER_GATE_LOCAL)
hunter_gate_user_error("Unexpected LOCAL (already has FILEPATH)")
endif()
endif()
hunter_gate_detect_root() # set HUNTER_GATE_ROOT
# Beautify path, fix probable problems with windows path slashes
get_filename_component(
HUNTER_GATE_ROOT "${HUNTER_GATE_ROOT}" ABSOLUTE
)
hunter_gate_status_debug("HUNTER_ROOT: ${HUNTER_GATE_ROOT}")
if(NOT HUNTER_ALLOW_SPACES_IN_PATH)
string(FIND "${HUNTER_GATE_ROOT}" " " _contain_spaces)
if(NOT _contain_spaces EQUAL -1)
hunter_gate_fatal_error(
"HUNTER_ROOT (${HUNTER_GATE_ROOT}) contains spaces."
"Set HUNTER_ALLOW_SPACES_IN_PATH=ON to skip this error"
"(Use at your own risk!)"
ERROR_PAGE "error.spaces.in.hunter.root"
)
endif()
endif()
string(
REGEX
MATCH
"[0-9]+\\.[0-9]+\\.[0-9]+[-_a-z0-9]*"
HUNTER_GATE_VERSION
"${HUNTER_GATE_URL}"
)
string(COMPARE EQUAL "${HUNTER_GATE_VERSION}" "" _is_empty)
if(_is_empty)
set(HUNTER_GATE_VERSION "unknown")
endif()
hunter_gate_self(
"${HUNTER_GATE_ROOT}"
"${HUNTER_GATE_VERSION}"
"${HUNTER_GATE_SHA1}"
_hunter_self
)
set(_master_location "${_hunter_self}/cmake/Hunter")
get_filename_component(_archive_id_location "${_hunter_self}/.." ABSOLUTE)
set(_done_location "${_archive_id_location}/DONE")
set(_sha1_location "${_archive_id_location}/SHA1")
# Check Hunter already downloaded by HunterGate
if(NOT EXISTS "${_done_location}")
hunter_gate_download("${_archive_id_location}")
endif()
if(NOT EXISTS "${_done_location}")
hunter_gate_internal_error("hunter_gate_download failed")
endif()
if(NOT EXISTS "${_sha1_location}")
hunter_gate_internal_error("${_sha1_location} not found")
endif()
file(READ "${_sha1_location}" _sha1_value)
string(COMPARE EQUAL "${_sha1_value}" "${HUNTER_GATE_SHA1}" _is_equal)
if(NOT _is_equal)
hunter_gate_internal_error(
"Short SHA1 collision:"
" ${_sha1_value} (from ${_sha1_location})"
" ${HUNTER_GATE_SHA1} (HunterGate)"
)
endif()
if(NOT EXISTS "${_master_location}")
hunter_gate_user_error(
"Master file not found:"
" ${_master_location}"
"try to update Hunter/HunterGate"
)
endif()
include("${_master_location}")
set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES)
endif()
endmacro()

View File

@ -1,29 +0,0 @@
#
# Find the lmdb library & include dir.
# Build lmdb on Appveyor.
#
if(APPVEYOR_BUILD)
set(LMDB_VERSION "LMDB_0.9.21")
set(NTDLIB "C:/WINDDK/7600.16385.1/lib/win7/amd64/ntdll.lib")
execute_process(
COMMAND git clone --depth=1 --branch ${LMDB_VERSION} https://github.com/LMDB/lmdb)
set(LMDB_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/lmdb/libraries/liblmdb)
add_library(lmdb
${CMAKE_SOURCE_DIR}/lmdb/libraries/liblmdb/lmdb.h
${CMAKE_SOURCE_DIR}/lmdb/libraries/liblmdb/mdb.c
${CMAKE_SOURCE_DIR}/lmdb/libraries/liblmdb/midl.h
${CMAKE_SOURCE_DIR}/lmdb/libraries/liblmdb/midl.c)
set(LMDB_LIBRARY lmdb)
else()
find_path (LMDB_INCLUDE_DIR NAMES lmdb.h PATHS "$ENV{LMDB_DIR}/include")
find_library (LMDB_LIBRARY NAMES lmdb PATHS "$ENV{LMDB_DIR}/lib" )
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LMDB DEFAULT_MSG LMDB_INCLUDE_DIR LMDB_LIBRARY)
endif()
include_directories(${LMDB_INCLUDE_DIR})

125
deps/CMakeLists.txt vendored
View File

@ -1,125 +0,0 @@
cmake_minimum_required(VERSION 3.11)
project(NHEKO_DEPS)
# Point CMake at any custom modules we may ship
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(DEPS_INSTALL_DIR "${CMAKE_BINARY_DIR}/usr"
CACHE PATH "Dependencies install directory.")
set(DEPS_BIN_DIR "${DEPS_INSTALL_DIR}/bin"
CACHE PATH "Dependencies binary install directory.")
set(DEPS_LIB_DIR "${DEPS_INSTALL_DIR}/lib"
CACHE PATH "Dependencies library install directory.")
set(DEPS_BUILD_DIR "${CMAKE_BINARY_DIR}/build"
CACHE PATH "Dependencies build directory.")
set(DEPS_DOWNLOAD_DIR "${DEPS_BUILD_DIR}/downloads"
CACHE PATH "Dependencies download directory.")
option(USE_BUNDLED "Use bundled dependencies." ON)
option(USE_BUNDLED_BOOST "Use the bundled version of Boost." ${USE_BUNDLED})
option(USE_BUNDLED_CMARK "Use the bundled version of cmark." ${USE_BUNDLED})
option(USE_BUNDLED_SPDLOG "Use the bundled version of spdlog." ${USE_BUNDLED})
option(USE_BUNDLED_OLM "Use the bundled version of libolm." ${USE_BUNDLED})
option(USE_BUNDLED_TWEENY "Use the bundled version of Tweeny." ${USE_BUNDLED})
option(USE_BUNDLED_LMDBXX "Use the bundled version of lmdbxx." ${USE_BUNDLED})
option(USE_BUNDLED_MATRIX_CLIENT "Use the bundled version of mtxclient."
${USE_BUNDLED})
option(USE_BUNDLED_JSON "Use the bundled version of nlohmann json." ${USE_BUNDLED})
option(MTX_STATIC "Compile / link bundled mtx client statically" OFF)
if(USE_BUNDLED_BOOST)
# bundled boost is 1.70, which requires CMake 3.15 or greater.
cmake_minimum_required(VERSION 3.15)
endif()
include(ExternalProject)
set(BOOST_URL
https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.bz2)
set(BOOST_SHA256
430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778)
set(
MTXCLIENT_URL
https://github.com/Nheko-Reborn/mtxclient/archive/84c6778cc367bca79755e73e77b2cc69950375b2.zip
)
set(MTXCLIENT_HASH
009fc9628cbdb94694eff3bba3fe54415e432385200c886bb1c1182bcf290c0a)
set(
TWEENY_URL
https://github.com/mobius3/tweeny/archive/b94ce07cfb02a0eb8ac8aaf66137dabdaea857cf.tar.gz
)
set(TWEENY_HASH
9a632b9da84823fae002ad5d9ba02c8d77c0a3810479974c6b637c5504165475)
set(
LMDBXX_HEADER_URL
https://raw.githubusercontent.com/bendiken/lmdbxx/0b43ca87d8cfabba392dfe884eb1edb83874de02/lmdb%2B%2B.h
)
set(LMDBXX_HASH
c57b501a4e8fa1187fa7fd348da415c7685a50a7cb25b17b3f257b9e9426f73d)
set(OLM_URL https://gitlab.matrix.org/matrix-org/olm.git)
set(OLM_TAG 4065c8e11a33ba41133a086ed3de4da94dcb6bae)
set(CMARK_URL https://github.com/commonmark/cmark/archive/0.29.0.tar.gz)
set(CMARK_HASH 2558ace3cbeff85610de3bda32858f722b359acdadf0c4691851865bb84924a6)
set(SPDLOG_URL https://github.com/gabime/spdlog/archive/v1.1.0.tar.gz)
set(SPDLOG_HASH
3dbcbfd8c07e25f5e0d662b194d3a7772ef214358c49ada23c044c4747ce8b19)
set(JSON_URL
https://github.com/nlohmann/json.git)
set(JSON_TAG
v3.2.0)
if(USE_BUNDLED_JSON)
include(Json)
endif()
if(USE_BUNDLED_BOOST)
include(Boost)
endif()
if(USE_BUNDLED_SPDLOG)
include(SpdLog)
endif()
if(USE_BUNDLED_OLM)
include(Olm)
endif()
if(USE_BUNDLED_CMARK)
include(cmark)
endif()
if(USE_BUNDLED_TWEENY)
include(Tweeny)
endif()
if(USE_BUNDLED_LMDBXX)
file(DOWNLOAD ${LMDBXX_HEADER_URL} ${DEPS_INSTALL_DIR}/include/lmdb++.h
EXPECTED_HASH SHA256=${LMDBXX_HASH})
endif()
if(WIN32)
if("${TARGET_ARCH}" STREQUAL "X86_64")
set(TARGET_ARCH x64)
elseif(TARGET_ARCH STREQUAL "X86")
set(TARGET_ARCH ia32)
endif()
endif()
add_custom_target(third-party ALL
COMMAND ${CMAKE_COMMAND} -E touch .third-party
DEPENDS ${THIRD_PARTY_DEPS})
if(USE_BUNDLED_MATRIX_CLIENT)
include(MatrixClient)
add_dependencies(MatrixClient third-party)
endif()

View File

@ -1,28 +0,0 @@
if(WIN32)
message(STATUS "Building Boost in Windows is not supported (skipping)")
return()
endif()
include(BoostToolsetId)
set(BOOST_TOOLSET "gcc")
Boost_Get_ToolsetId(BOOST_TOOLSET)
ExternalProject_Add(
Boost
URL ${BOOST_URL}
URL_HASH SHA256=${BOOST_SHA256}
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/boost
DOWNLOAD_NO_PROGRESS 0
BUILD_IN_SOURCE 1
SOURCE_DIR ${DEPS_BUILD_DIR}/boost
CONFIGURE_COMMAND ${DEPS_BUILD_DIR}/boost/bootstrap.sh
--with-libraries=random,thread,system,iostreams,atomic,chrono,date_time,regex
--prefix=${DEPS_INSTALL_DIR}
--with-toolset=${BOOST_TOOLSET}
BUILD_COMMAND ${DEPS_BUILD_DIR}/boost/b2 -d0 cxxstd=14 variant=release link=shared runtime-link=shared threading=multi --layout=system
INSTALL_COMMAND ${DEPS_BUILD_DIR}/boost/b2 -d0 install
)
list(APPEND THIRD_PARTY_DEPS Boost)

View File

@ -1,35 +0,0 @@
# - Translate CMake compilers to the Boost.Build toolset equivalents
# To build Boost reliably when a non-system compiler may be used, we
# need to both specify the toolset when running bootstrap.sh *and* in
# the user-config.jam file.
#
# This module provides the following functions to help translate between
# the systems:
#
# function Boost_Get_ToolsetId(<var>)
# Set var equal to Boost's name for the CXX toolchain picked
# up by CMake. Only supports GNU and Clang families at present.
# Intel support is provisional
#
# downloaded from https://github.com/drbenmorgan/BoostBuilder/blob/master/BoostToolsetId.cmake
function(Boost_Get_ToolsetId _var)
set(BOOST_TOOLSET)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if(APPLE)
set(BOOST_TOOLSET "darwin")
else()
set(BOOST_TOOLSET "gcc")
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
set(BOOST_TOOLSET "clang")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
set(BOOST_TOOLSET "intel")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(BOOST_TOOLSET "msvc")
endif()
set(${_var} ${BOOST_TOOLSET} PARENT_SCOPE)
endfunction()

19
deps/cmake/Json.cmake vendored
View File

@ -1,19 +0,0 @@
ExternalProject_Add(
Json
GIT_REPOSITORY ${JSON_URL}
GIT_TAG ${JSON_TAG}
BUILD_IN_SOURCE 1
SOURCE_DIR ${DEPS_BUILD_DIR}/json
CONFIGURE_COMMAND ${CMAKE_COMMAND}
-DJSON_BuildTests=OFF
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
BUILD_COMMAND ${CMAKE_COMMAND} --build ${DEPS_BUILD_DIR}/json
INSTALL_COMMAND ${CMAKE_COMMAND} --build ${DEPS_BUILD_DIR}/json --target install
)
list(APPEND THIRD_PARTY_DEPS Json)

View File

@ -1,43 +0,0 @@
set(PLATFORM_FLAGS "")
if(MSVC)
set(PLATFORM_FLAGS "-DCMAKE_GENERATOR_PLATFORM=x64")
endif()
if(APPLE)
set(PLATFORM_FLAGS "-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl")
endif()
# Force to build with the bundled version of Boost. This is necessary because
# if an outdated version of Boost is installed, then CMake will grab that
# instead of the bundled version of Boost, like we wanted.
set(BOOST_BUNDLE_ROOT "-DBOOST_ROOT=${DEPS_BUILD_DIR}/boost")
set (MTX_SHARED ON)
if (MTX_STATIC)
set (MTX_SHARED OFF)
endif()
ExternalProject_Add(
MatrixClient
URL ${MTXCLIENT_URL}
URL_HASH SHA256=${MTXCLIENT_HASH}
BUILD_IN_SOURCE 1
SOURCE_DIR ${DEPS_BUILD_DIR}/mtxclient
CONFIGURE_COMMAND ${CMAKE_COMMAND}
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
-DCMAKE_BUILD_TYPE=Release
-DBUILD_LIB_TESTS=OFF
-DBUILD_LIB_EXAMPLES=OFF
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
${BOOST_BUNDLE_ROOT}
-DBUILD_SHARED_LIBS=${MTX_SHARED}
${PLATFORM_FLAGS}
${DEPS_BUILD_DIR}/mtxclient
BUILD_COMMAND
${CMAKE_COMMAND} --build ${DEPS_BUILD_DIR}/mtxclient --config Release)
list(APPEND THIRD_PARTY_DEPS MatrixClient)

34
deps/cmake/Olm.cmake vendored
View File

@ -1,34 +0,0 @@
set(WINDOWS_FLAGS "")
if(MSVC)
set(WINDOWS_FLAGS "-DCMAKE_GENERATOR_PLATFORM=x64")
endif()
ExternalProject_Add(
Olm
GIT_REPOSITORY ${OLM_URL}
GIT_TAG ${OLM_TAG}
BUILD_IN_SOURCE 1
SOURCE_DIR ${DEPS_BUILD_DIR}/olm
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/cmake/OlmCMakeLists.txt
${DEPS_BUILD_DIR}/olm/CMakeLists.txt
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/cmake/OlmConfig.cmake.in
${DEPS_BUILD_DIR}/olm/cmake/OlmConfig.cmake.in
COMMAND ${CMAKE_COMMAND}
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
-DCMAKE_BUILD_TYPE=Release
${DEPS_BUILD_DIR}/olm
${WINDOWS_FLAGS}
BUILD_COMMAND ${CMAKE_COMMAND}
--build ${DEPS_BUILD_DIR}/olm
--config Release
INSTALL_COMMAND ${CMAKE_COMMAND}
--build ${DEPS_BUILD_DIR}/olm
--config Release
--target install)
list(APPEND THIRD_PARTY_DEPS Olm)

View File

@ -1,107 +0,0 @@
cmake_minimum_required(VERSION 3.1)
project(olm VERSION 2.2.2 LANGUAGES CXX C)
add_definitions(-DOLMLIB_VERSION_MAJOR=${PROJECT_VERSION_MAJOR})
add_definitions(-DOLMLIB_VERSION_MINOR=${PROJECT_VERSION_MINOR})
add_definitions(-DOLMLIB_VERSION_PATCH=${PROJECT_VERSION_PATCH})
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
add_library(olm
src/account.cpp
src/base64.cpp
src/cipher.cpp
src/crypto.cpp
src/memory.cpp
src/message.cpp
src/pickle.cpp
src/ratchet.cpp
src/session.cpp
src/utility.cpp
src/ed25519.c
src/error.c
src/inbound_group_session.c
src/megolm.c
src/olm.cpp
src/outbound_group_session.c
src/pickle_encoding.c
lib/crypto-algorithms/aes.c
lib/crypto-algorithms/sha256.c
lib/curve25519-donna/curve25519-donna.c)
add_library(Olm::Olm ALIAS olm)
target_include_directories(olm
PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib)
set_target_properties(olm PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}
VERSION ${PROJECT_VERSION})
set_target_properties(olm PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
#
# Installation
#
include(GNUInstallDirs)
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/Olm)
install(TARGETS olm
EXPORT olm-targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
# The exported target will be named Olm.
set_target_properties(olm PROPERTIES EXPORT_NAME Olm)
install(FILES
${CMAKE_SOURCE_DIR}/include/olm/olm.h
${CMAKE_SOURCE_DIR}/include/olm/outbound_group_session.h
${CMAKE_SOURCE_DIR}/include/olm/inbound_group_session.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/olm)
# Export the targets to a script.
install(EXPORT olm-targets
FILE OlmTargets.cmake
NAMESPACE Olm::
DESTINATION ${INSTALL_CONFIGDIR})
# Create a ConfigVersion.cmake file.
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/OlmConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/cmake/OlmConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/OlmConfig.cmake
INSTALL_DESTINATION ${INSTALL_CONFIGDIR})
#Install the config & configversion.
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/OlmConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/OlmConfigVersion.cmake
DESTINATION ${INSTALL_CONFIGDIR})
# Register package in user's package registry
export(EXPORT olm-targets
FILE ${CMAKE_CURRENT_BINARY_DIR}/OlmTargets.cmake
NAMESPACE Olm::)
export(PACKAGE Olm)

View File

@ -1,11 +0,0 @@
get_filename_component(Olm_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
include(CMakeFindDependencyMacro)
list(APPEND CMAKE_MODULE_PATH ${Olm_CMAKE_DIR})
list(REMOVE_AT CMAKE_MODULE_PATH -1)
if(NOT TARGET Olm::Olm)
include("${Olm_CMAKE_DIR}/OlmTargets.cmake")
endif()
set(Olm_LIBRARIES Olm::Olm)

View File

@ -1,23 +0,0 @@
set(WINDOWS_FLAGS "")
if(MSVC)
set(WINDOWS_FLAGS "-DCMAKE_GENERATOR_PLATFORM=x64")
endif()
ExternalProject_Add(
SpdLog
URL ${SPDLOG_URL}
URL_HASH SHA256=${SPDLOG_HASH}
BUILD_IN_SOURCE 1
SOURCE_DIR ${DEPS_BUILD_DIR}/spdlog
CONFIGURE_COMMAND ${CMAKE_COMMAND}
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
-DSPDLOG_BUILD_EXAMPLES=0
-DSPDLOG_BUILD_BENCH=0
-DSPDLOG_BUILD_TESTING=0
${DEPS_BUILD_DIR}/spdlog
${WINDOWS_FLAGS})
list(APPEND THIRD_PARTY_DEPS SpdLog)

View File

@ -1,22 +0,0 @@
set(WINDOWS_FLAGS "")
if(MSVC)
set(WINDOWS_FLAGS "-DCMAKE_GENERATOR_PLATFORM=x64")
endif()
ExternalProject_Add(
Tweeny
URL ${TWEENY_URL}
URL_HASH SHA256=${TWEENY_HASH}
BUILD_IN_SOURCE 1
SOURCE_DIR ${DEPS_BUILD_DIR}/tweeny
CONFIGURE_COMMAND ${CMAKE_COMMAND}
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
-DTWEENY_BUILD_EXAMPLES=OFF
-DTWEENY_BUILD_DOCUMENTATION=OFF
${DEPS_BUILD_DIR}/tweeny
${WINDOWS_FLAGS})
list(APPEND THIRD_PARTY_DEPS Tweeny)

View File

@ -1,21 +0,0 @@
set(WINDOWS_FLAGS "")
if(MSVC)
set(WINDOWS_FLAGS "-DCMAKE_GENERATOR_PLATFORM=x64")
endif()
ExternalProject_Add(
cmark
URL ${CMARK_URL}
URL_HASH SHA256=${CMARK_HASH}
BUILD_IN_SOURCE 0
SOURCE_DIR ${DEPS_BUILD_DIR}/cmark
CONFIGURE_COMMAND ${CMAKE_COMMAND}
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
-DCMARK_TESTS=OFF
${DEPS_BUILD_DIR}/cmark
${WINDOWS_FLAGS})
list(APPEND THIRD_PARTY_DEPS cmark)

View File

@ -4,7 +4,53 @@
<context> <context>
<name>ChatPage</name> <name>ChatPage</name>
<message> <message>
<location filename="../../src/ChatPage.cpp" line="+328"/> <location filename="../../src/ChatPage.cpp" line="+211"/>
<source>Failed to invite user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
<location line="+84"/>
<source>Invited user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="-6"/>
<source>Failed to invite %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+20"/>
<source>Failed to kick %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Kicked user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+14"/>
<source>Failed to ban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Banned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+16"/>
<source>Failed to unban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>Unbanned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+50"/>
<source>Failed to upload media. Please try again.</source> <source>Failed to upload media. Please try again.</source>
<translation>Medienupload fehlgeschlagen. Bitte versuche es erneut.</translation> <translation>Medienupload fehlgeschlagen. Bitte versuche es erneut.</translation>
</message> </message>
@ -25,17 +71,37 @@
</message> </message>
<message> <message>
<location line="+51"/> <location line="+51"/>
<location line="+155"/> <location line="+154"/>
<source>Please try to login again: %1</source> <source>Please try to login again: %1</source>
<translation>Bitte melde dich erneut an: %1</translation> <translation>Bitte melde dich erneut an: %1</translation>
</message> </message>
<message> <message>
<location line="-47"/> <location line="-77"/>
<source>Failed to join room: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>You joined the room</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Failed to remove invite: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+19"/>
<source>Room creation failed: %1</source> <source>Room creation failed: %1</source>
<translation>Raum konnte nicht erstellt werden: %1</translation> <translation>Raum konnte nicht erstellt werden: %1</translation>
</message> </message>
<message> <message>
<location line="+16"/> <location line="+5"/>
<source>Room %1 created</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+11"/>
<source>Failed to leave room: %1</source> <source>Failed to leave room: %1</source>
<translation>Konnte den Raum nicht verlassen: %1</translation> <translation>Konnte den Raum nicht verlassen: %1</translation>
</message> </message>
@ -385,7 +451,7 @@
<translation>Emoji</translation> <translation>Emoji</translation>
</message> </message>
<message> <message>
<location line="+73"/> <location line="+81"/>
<source>Select a file</source> <source>Select a file</source>
<translation>Datei auswählen</translation> <translation>Datei auswählen</translation>
</message> </message>
@ -403,7 +469,7 @@
<context> <context>
<name>TimelineModel</name> <name>TimelineModel</name>
<message> <message>
<location filename="../../src/timeline/TimelineModel.cpp" line="+698"/> <location filename="../../src/timeline/TimelineModel.cpp" line="+716"/>
<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&apos;t be decrypted</comment> <comment>Placeholder, when the message was not decrypted yet or can&apos;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>
@ -646,42 +712,47 @@
<context> <context>
<name>UserSettingsPage</name> <name>UserSettingsPage</name>
<message> <message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/> <location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source> <source>Minimize to tray</source>
<translation>Ins Benachrichtigungsfeld minimieren</translation> <translation>Ins Benachrichtigungsfeld minimieren</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Start in tray</source> <source>Start in tray</source>
<translation>Im Benachrichtigungsfeld starten</translation> <translation>Im Benachrichtigungsfeld starten</translation>
</message> </message>
<message> <message>
<location line="+11"/> <location line="+5"/>
<source>Group&apos;s sidebar</source> <source>Group&apos;s sidebar</source>
<translation>Gruppen-Seitenleiste</translation> <translation>Gruppen-Seitenleiste</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Circular Avatars</source> <source>Circular Avatars</source>
<translation>Runde Profilbilder</translation> <translation>Runde Profilbilder</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Typing notifications</source> <source>Typing notifications</source>
<translation>Schreibbenachrichtigungen</translation> <translation>Schreibbenachrichtigungen</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Read receipts</source> <source>Read receipts</source>
<translation>Lesebestätigungen</translation> <translation>Lesebestätigungen</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Send messages as markdown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Desktop notifications</source> <source>Desktop notifications</source>
<translation>Desktopbenachrichtigungen</translation> <translation>Desktopbenachrichtigungen</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+4"/>
<source>Scale factor</source> <source>Scale factor</source>
<translation>Skalierungsfaktor</translation> <translation>Skalierungsfaktor</translation>
</message> </message>
@ -741,7 +812,7 @@
<translation>ALLGEMEINES</translation> <translation>ALLGEMEINES</translation>
</message> </message>
<message> <message>
<location line="+161"/> <location line="+168"/>
<source>Open Sessions File</source> <source>Open Sessions File</source>
<translation>Öffne Sessions Datei</translation> <translation>Öffne Sessions Datei</translation>
</message> </message>

View File

@ -4,7 +4,53 @@
<context> <context>
<name>ChatPage</name> <name>ChatPage</name>
<message> <message>
<location filename="../../src/ChatPage.cpp" line="+328"/> <location filename="../../src/ChatPage.cpp" line="+211"/>
<source>Failed to invite user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
<location line="+84"/>
<source>Invited user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="-6"/>
<source>Failed to invite %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+20"/>
<source>Failed to kick %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Kicked user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+14"/>
<source>Failed to ban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Banned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+16"/>
<source>Failed to unban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>Unbanned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+50"/>
<source>Failed to upload media. Please try again.</source> <source>Failed to upload media. Please try again.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -25,17 +71,37 @@
</message> </message>
<message> <message>
<location line="+51"/> <location line="+51"/>
<location line="+155"/> <location line="+154"/>
<source>Please try to login again: %1</source> <source>Please try to login again: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="-47"/> <location line="-77"/>
<source>Failed to join room: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>You joined the room</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Failed to remove invite: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+19"/>
<source>Room creation failed: %1</source> <source>Room creation failed: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+16"/> <location line="+5"/>
<source>Room %1 created</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+11"/>
<source>Failed to leave room: %1</source> <source>Failed to leave room: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -385,7 +451,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+73"/> <location line="+81"/>
<source>Select a file</source> <source>Select a file</source>
<translation>Διάλεξε ένα αρχείο</translation> <translation>Διάλεξε ένα αρχείο</translation>
</message> </message>
@ -403,7 +469,7 @@
<context> <context>
<name>TimelineModel</name> <name>TimelineModel</name>
<message> <message>
<location filename="../../src/timeline/TimelineModel.cpp" line="+698"/> <location filename="../../src/timeline/TimelineModel.cpp" line="+716"/>
<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&apos;t be decrypted</comment> <comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -646,42 +712,47 @@
<context> <context>
<name>UserSettingsPage</name> <name>UserSettingsPage</name>
<message> <message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/> <location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source> <source>Minimize to tray</source>
<translation>Ελαχιστοποίηση</translation> <translation>Ελαχιστοποίηση</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Start in tray</source> <source>Start in tray</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+11"/> <location line="+5"/>
<source>Group&apos;s sidebar</source> <source>Group&apos;s sidebar</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Circular Avatars</source> <source>Circular Avatars</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Typing notifications</source> <source>Typing notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Read receipts</source> <source>Read receipts</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Send messages as markdown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Desktop notifications</source> <source>Desktop notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+4"/>
<source>Scale factor</source> <source>Scale factor</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -741,7 +812,7 @@
<translation>ΓΕΝΙΚΑ</translation> <translation>ΓΕΝΙΚΑ</translation>
</message> </message>
<message> <message>
<location line="+161"/> <location line="+168"/>
<source>Open Sessions File</source> <source>Open Sessions File</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -4,7 +4,53 @@
<context> <context>
<name>ChatPage</name> <name>ChatPage</name>
<message> <message>
<location filename="../../src/ChatPage.cpp" line="+328"/> <location filename="../../src/ChatPage.cpp" line="+211"/>
<source>Failed to invite user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
<location line="+84"/>
<source>Invited user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="-6"/>
<source>Failed to invite %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+20"/>
<source>Failed to kick %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Kicked user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+14"/>
<source>Failed to ban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Banned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+16"/>
<source>Failed to unban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>Unbanned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+50"/>
<source>Failed to upload media. Please try again.</source> <source>Failed to upload media. Please try again.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -25,17 +71,37 @@
</message> </message>
<message> <message>
<location line="+51"/> <location line="+51"/>
<location line="+155"/> <location line="+154"/>
<source>Please try to login again: %1</source> <source>Please try to login again: %1</source>
<translation>Please try to login again: %1</translation> <translation>Please try to login again: %1</translation>
</message> </message>
<message> <message>
<location line="-47"/> <location line="-77"/>
<source>Failed to join room: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>You joined the room</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Failed to remove invite: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+19"/>
<source>Room creation failed: %1</source> <source>Room creation failed: %1</source>
<translation>Room creation failed: %1</translation> <translation>Room creation failed: %1</translation>
</message> </message>
<message> <message>
<location line="+16"/> <location line="+5"/>
<source>Room %1 created</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+11"/>
<source>Failed to leave room: %1</source> <source>Failed to leave room: %1</source>
<translation>Failed to leave room: %1</translation> <translation>Failed to leave room: %1</translation>
</message> </message>
@ -385,7 +451,7 @@
<translation>Emoji</translation> <translation>Emoji</translation>
</message> </message>
<message> <message>
<location line="+73"/> <location line="+81"/>
<source>Select a file</source> <source>Select a file</source>
<translation>Select a file</translation> <translation>Select a file</translation>
</message> </message>
@ -403,7 +469,7 @@
<context> <context>
<name>TimelineModel</name> <name>TimelineModel</name>
<message> <message>
<location filename="../../src/timeline/TimelineModel.cpp" line="+698"/> <location filename="../../src/timeline/TimelineModel.cpp" line="+716"/>
<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&apos;t be decrypted</comment> <comment>Placeholder, when the message was not decrypted yet or can&apos;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>
@ -646,42 +712,47 @@
<context> <context>
<name>UserSettingsPage</name> <name>UserSettingsPage</name>
<message> <message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/> <location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source> <source>Minimize to tray</source>
<translation>Minimize to tray</translation> <translation>Minimize to tray</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Start in tray</source> <source>Start in tray</source>
<translation>Start in tray</translation> <translation>Start in tray</translation>
</message> </message>
<message> <message>
<location line="+11"/> <location line="+5"/>
<source>Group&apos;s sidebar</source> <source>Group&apos;s sidebar</source>
<translation>Group&apos;s sidebar</translation> <translation>Group&apos;s sidebar</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Circular Avatars</source> <source>Circular Avatars</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Typing notifications</source> <source>Typing notifications</source>
<translation>Typing notifications</translation> <translation>Typing notifications</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Read receipts</source> <source>Read receipts</source>
<translation>Read receipts</translation> <translation>Read receipts</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Send messages as markdown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Desktop notifications</source> <source>Desktop notifications</source>
<translation>Desktop notifications</translation> <translation>Desktop notifications</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+4"/>
<source>Scale factor</source> <source>Scale factor</source>
<translation>Scale factor</translation> <translation>Scale factor</translation>
</message> </message>
@ -741,7 +812,7 @@
<translation>GENERAL</translation> <translation>GENERAL</translation>
</message> </message>
<message> <message>
<location line="+161"/> <location line="+168"/>
<source>Open Sessions File</source> <source>Open Sessions File</source>
<translation>Open Sessions File</translation> <translation>Open Sessions File</translation>
</message> </message>

View File

@ -4,7 +4,53 @@
<context> <context>
<name>ChatPage</name> <name>ChatPage</name>
<message> <message>
<location filename="../../src/ChatPage.cpp" line="+328"/> <location filename="../../src/ChatPage.cpp" line="+211"/>
<source>Failed to invite user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
<location line="+84"/>
<source>Invited user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="-6"/>
<source>Failed to invite %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+20"/>
<source>Failed to kick %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Kicked user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+14"/>
<source>Failed to ban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Banned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+16"/>
<source>Failed to unban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>Unbanned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+50"/>
<source>Failed to upload media. Please try again.</source> <source>Failed to upload media. Please try again.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -25,17 +71,37 @@
</message> </message>
<message> <message>
<location line="+51"/> <location line="+51"/>
<location line="+155"/> <location line="+154"/>
<source>Please try to login again: %1</source> <source>Please try to login again: %1</source>
<translation>Ole hyvä ja yritä kirjautua sisään uudelleen: %1</translation> <translation>Ole hyvä ja yritä kirjautua sisään uudelleen: %1</translation>
</message> </message>
<message> <message>
<location line="-47"/> <location line="-77"/>
<source>Failed to join room: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>You joined the room</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Failed to remove invite: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+19"/>
<source>Room creation failed: %1</source> <source>Room creation failed: %1</source>
<translation>Huoneen luominen epäonnistui: %1</translation> <translation>Huoneen luominen epäonnistui: %1</translation>
</message> </message>
<message> <message>
<location line="+16"/> <location line="+5"/>
<source>Room %1 created</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+11"/>
<source>Failed to leave room: %1</source> <source>Failed to leave room: %1</source>
<translation>Huoneesta poistuminen epäonnistui: %1</translation> <translation>Huoneesta poistuminen epäonnistui: %1</translation>
</message> </message>
@ -385,7 +451,7 @@
<translation>Emoji</translation> <translation>Emoji</translation>
</message> </message>
<message> <message>
<location line="+73"/> <location line="+81"/>
<source>Select a file</source> <source>Select a file</source>
<translation>Valitse tiedosto</translation> <translation>Valitse tiedosto</translation>
</message> </message>
@ -403,7 +469,7 @@
<context> <context>
<name>TimelineModel</name> <name>TimelineModel</name>
<message> <message>
<location filename="../../src/timeline/TimelineModel.cpp" line="+698"/> <location filename="../../src/timeline/TimelineModel.cpp" line="+716"/>
<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&apos;t be decrypted</comment> <comment>Placeholder, when the message was not decrypted yet or can&apos;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>
@ -646,42 +712,47 @@
<context> <context>
<name>UserSettingsPage</name> <name>UserSettingsPage</name>
<message> <message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/> <location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source> <source>Minimize to tray</source>
<translation>Pienennä ilmoitusalueelle</translation> <translation>Pienennä ilmoitusalueelle</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Start in tray</source> <source>Start in tray</source>
<translation>Aloita ilmoitusalueella</translation> <translation>Aloita ilmoitusalueella</translation>
</message> </message>
<message> <message>
<location line="+11"/> <location line="+5"/>
<source>Group&apos;s sidebar</source> <source>Group&apos;s sidebar</source>
<translation>Ryhmäsivupalkki</translation> <translation>Ryhmäsivupalkki</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Circular Avatars</source> <source>Circular Avatars</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Typing notifications</source> <source>Typing notifications</source>
<translation>Kirjoitusilmoitukset</translation> <translation>Kirjoitusilmoitukset</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Read receipts</source> <source>Read receipts</source>
<translation>Lukukuittaukset</translation> <translation>Lukukuittaukset</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Send messages as markdown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Desktop notifications</source> <source>Desktop notifications</source>
<translation>Työpöytäilmoitukset</translation> <translation>Työpöytäilmoitukset</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+4"/>
<source>Scale factor</source> <source>Scale factor</source>
<translation>Mittakerroin</translation> <translation>Mittakerroin</translation>
</message> </message>
@ -741,7 +812,7 @@
<translation>YLEISET ASETUKSET</translation> <translation>YLEISET ASETUKSET</translation>
</message> </message>
<message> <message>
<location line="+161"/> <location line="+168"/>
<source>Open Sessions File</source> <source>Open Sessions File</source>
<translation>Avaa Istuntoavaintiedosto</translation> <translation>Avaa Istuntoavaintiedosto</translation>
</message> </message>

View File

@ -4,7 +4,53 @@
<context> <context>
<name>ChatPage</name> <name>ChatPage</name>
<message> <message>
<location filename="../../src/ChatPage.cpp" line="+328"/> <location filename="../../src/ChatPage.cpp" line="+211"/>
<source>Failed to invite user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
<location line="+84"/>
<source>Invited user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="-6"/>
<source>Failed to invite %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+20"/>
<source>Failed to kick %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Kicked user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+14"/>
<source>Failed to ban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Banned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+16"/>
<source>Failed to unban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>Unbanned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+50"/>
<source>Failed to upload media. Please try again.</source> <source>Failed to upload media. Please try again.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -25,17 +71,37 @@
</message> </message>
<message> <message>
<location line="+51"/> <location line="+51"/>
<location line="+155"/> <location line="+154"/>
<source>Please try to login again: %1</source> <source>Please try to login again: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="-47"/> <location line="-77"/>
<source>Failed to join room: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>You joined the room</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Failed to remove invite: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+19"/>
<source>Room creation failed: %1</source> <source>Room creation failed: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+16"/> <location line="+5"/>
<source>Room %1 created</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+11"/>
<source>Failed to leave room: %1</source> <source>Failed to leave room: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -386,7 +452,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+73"/> <location line="+81"/>
<source>Select a file</source> <source>Select a file</source>
<translation>Sélectionnez un fichier</translation> <translation>Sélectionnez un fichier</translation>
</message> </message>
@ -404,7 +470,7 @@
<context> <context>
<name>TimelineModel</name> <name>TimelineModel</name>
<message> <message>
<location filename="../../src/timeline/TimelineModel.cpp" line="+698"/> <location filename="../../src/timeline/TimelineModel.cpp" line="+716"/>
<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&apos;t be decrypted</comment> <comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -647,42 +713,47 @@
<context> <context>
<name>UserSettingsPage</name> <name>UserSettingsPage</name>
<message> <message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/> <location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source> <source>Minimize to tray</source>
<translation>Réduire à la barre des tâches</translation> <translation>Réduire à la barre des tâches</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Start in tray</source> <source>Start in tray</source>
<translation>Démarrer dans la barre des tâches</translation> <translation>Démarrer dans la barre des tâches</translation>
</message> </message>
<message> <message>
<location line="+11"/> <location line="+5"/>
<source>Group&apos;s sidebar</source> <source>Group&apos;s sidebar</source>
<translation>Barre latérale des groupes</translation> <translation>Barre latérale des groupes</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Circular Avatars</source> <source>Circular Avatars</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Typing notifications</source> <source>Typing notifications</source>
<translation>Notifications d&apos;écriture</translation> <translation>Notifications d&apos;écriture</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Read receipts</source> <source>Read receipts</source>
<translation>Accusés de lecture</translation> <translation>Accusés de lecture</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Send messages as markdown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Desktop notifications</source> <source>Desktop notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+4"/>
<source>Scale factor</source> <source>Scale factor</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -742,7 +813,7 @@
<translation>GÉNÉRAL</translation> <translation>GÉNÉRAL</translation>
</message> </message>
<message> <message>
<location line="+161"/> <location line="+168"/>
<source>Open Sessions File</source> <source>Open Sessions File</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -4,7 +4,53 @@
<context> <context>
<name>ChatPage</name> <name>ChatPage</name>
<message> <message>
<location filename="../../src/ChatPage.cpp" line="+328"/> <location filename="../../src/ChatPage.cpp" line="+211"/>
<source>Failed to invite user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
<location line="+84"/>
<source>Invited user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="-6"/>
<source>Failed to invite %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+20"/>
<source>Failed to kick %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Kicked user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+14"/>
<source>Failed to ban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Banned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+16"/>
<source>Failed to unban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>Unbanned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+50"/>
<source>Failed to upload media. Please try again.</source> <source>Failed to upload media. Please try again.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -25,17 +71,37 @@
</message> </message>
<message> <message>
<location line="+51"/> <location line="+51"/>
<location line="+155"/> <location line="+154"/>
<source>Please try to login again: %1</source> <source>Please try to login again: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="-47"/> <location line="-77"/>
<source>Failed to join room: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>You joined the room</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Failed to remove invite: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+19"/>
<source>Room creation failed: %1</source> <source>Room creation failed: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+16"/> <location line="+5"/>
<source>Room %1 created</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+11"/>
<source>Failed to leave room: %1</source> <source>Failed to leave room: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -385,7 +451,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+73"/> <location line="+81"/>
<source>Select a file</source> <source>Select a file</source>
<translation>Kies een bestand</translation> <translation>Kies een bestand</translation>
</message> </message>
@ -403,7 +469,7 @@
<context> <context>
<name>TimelineModel</name> <name>TimelineModel</name>
<message> <message>
<location filename="../../src/timeline/TimelineModel.cpp" line="+698"/> <location filename="../../src/timeline/TimelineModel.cpp" line="+716"/>
<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&apos;t be decrypted</comment> <comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -646,42 +712,47 @@
<context> <context>
<name>UserSettingsPage</name> <name>UserSettingsPage</name>
<message> <message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/> <location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source> <source>Minimize to tray</source>
<translation>Minimaliseren naar systeemvak</translation> <translation>Minimaliseren naar systeemvak</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Start in tray</source> <source>Start in tray</source>
<translation>Geminimaliseerd opstarten</translation> <translation>Geminimaliseerd opstarten</translation>
</message> </message>
<message> <message>
<location line="+11"/> <location line="+5"/>
<source>Group&apos;s sidebar</source> <source>Group&apos;s sidebar</source>
<translation>Zijbalk van groep</translation> <translation>Zijbalk van groep</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Circular Avatars</source> <source>Circular Avatars</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Typing notifications</source> <source>Typing notifications</source>
<translation>Meldingen bij typen van berichten</translation> <translation>Meldingen bij typen van berichten</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Read receipts</source> <source>Read receipts</source>
<translation>Leesbevestigingen</translation> <translation>Leesbevestigingen</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Send messages as markdown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Desktop notifications</source> <source>Desktop notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+4"/>
<source>Scale factor</source> <source>Scale factor</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -741,7 +812,7 @@
<translation>ALGEMEEN</translation> <translation>ALGEMEEN</translation>
</message> </message>
<message> <message>
<location line="+161"/> <location line="+168"/>
<source>Open Sessions File</source> <source>Open Sessions File</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -4,7 +4,53 @@
<context> <context>
<name>ChatPage</name> <name>ChatPage</name>
<message> <message>
<location filename="../../src/ChatPage.cpp" line="+328"/> <location filename="../../src/ChatPage.cpp" line="+211"/>
<source>Failed to invite user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
<location line="+84"/>
<source>Invited user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="-6"/>
<source>Failed to invite %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+20"/>
<source>Failed to kick %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Kicked user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+14"/>
<source>Failed to ban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Banned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+16"/>
<source>Failed to unban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>Unbanned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+50"/>
<source>Failed to upload media. Please try again.</source> <source>Failed to upload media. Please try again.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -25,17 +71,37 @@
</message> </message>
<message> <message>
<location line="+51"/> <location line="+51"/>
<location line="+155"/> <location line="+154"/>
<source>Please try to login again: %1</source> <source>Please try to login again: %1</source>
<translation>Spróbuj zalogować się ponownie: %1</translation> <translation>Spróbuj zalogować się ponownie: %1</translation>
</message> </message>
<message> <message>
<location line="-47"/> <location line="-77"/>
<source>Failed to join room: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>You joined the room</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Failed to remove invite: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+19"/>
<source>Room creation failed: %1</source> <source>Room creation failed: %1</source>
<translation>Tworzenie pokoju nie powiodło się: %1</translation> <translation>Tworzenie pokoju nie powiodło się: %1</translation>
</message> </message>
<message> <message>
<location line="+16"/> <location line="+5"/>
<source>Room %1 created</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+11"/>
<source>Failed to leave room: %1</source> <source>Failed to leave room: %1</source>
<translation>Nie udało się opuścić pokoju: %1</translation> <translation>Nie udało się opuścić pokoju: %1</translation>
</message> </message>
@ -385,7 +451,7 @@
<translation>Emoji</translation> <translation>Emoji</translation>
</message> </message>
<message> <message>
<location line="+73"/> <location line="+81"/>
<source>Select a file</source> <source>Select a file</source>
<translation>Wybierz plik</translation> <translation>Wybierz plik</translation>
</message> </message>
@ -403,7 +469,7 @@
<context> <context>
<name>TimelineModel</name> <name>TimelineModel</name>
<message> <message>
<location filename="../../src/timeline/TimelineModel.cpp" line="+698"/> <location filename="../../src/timeline/TimelineModel.cpp" line="+716"/>
<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&apos;t be decrypted</comment> <comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -647,42 +713,47 @@
<context> <context>
<name>UserSettingsPage</name> <name>UserSettingsPage</name>
<message> <message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/> <location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source> <source>Minimize to tray</source>
<translation>Zminimalizuj do paska zadań</translation> <translation>Zminimalizuj do paska zadań</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Start in tray</source> <source>Start in tray</source>
<translation>Rozpocznij na pasku zadań</translation> <translation>Rozpocznij na pasku zadań</translation>
</message> </message>
<message> <message>
<location line="+11"/> <location line="+5"/>
<source>Group&apos;s sidebar</source> <source>Group&apos;s sidebar</source>
<translation>Pasek boczny grupy</translation> <translation>Pasek boczny grupy</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Circular Avatars</source> <source>Circular Avatars</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Typing notifications</source> <source>Typing notifications</source>
<translation>Powiadomienia o pisaniu</translation> <translation>Powiadomienia o pisaniu</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Read receipts</source> <source>Read receipts</source>
<translation>Potwierdzenia przeczytania</translation> <translation>Potwierdzenia przeczytania</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Send messages as markdown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Desktop notifications</source> <source>Desktop notifications</source>
<translation>Powiadomienia na pulpicie</translation> <translation>Powiadomienia na pulpicie</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+4"/>
<source>Scale factor</source> <source>Scale factor</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -742,7 +813,7 @@
<translation>OGÓLNE</translation> <translation>OGÓLNE</translation>
</message> </message>
<message> <message>
<location line="+161"/> <location line="+168"/>
<source>Open Sessions File</source> <source>Open Sessions File</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -4,7 +4,53 @@
<context> <context>
<name>ChatPage</name> <name>ChatPage</name>
<message> <message>
<location filename="../../src/ChatPage.cpp" line="+328"/> <location filename="../../src/ChatPage.cpp" line="+211"/>
<source>Failed to invite user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
<location line="+84"/>
<source>Invited user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="-6"/>
<source>Failed to invite %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+20"/>
<source>Failed to kick %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Kicked user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+14"/>
<source>Failed to ban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Banned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+16"/>
<source>Failed to unban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>Unbanned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+50"/>
<source>Failed to upload media. Please try again.</source> <source>Failed to upload media. Please try again.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -25,17 +71,37 @@
</message> </message>
<message> <message>
<location line="+51"/> <location line="+51"/>
<location line="+155"/> <location line="+154"/>
<source>Please try to login again: %1</source> <source>Please try to login again: %1</source>
<translation>Повторите попытку входа: %1</translation> <translation>Повторите попытку входа: %1</translation>
</message> </message>
<message> <message>
<location line="-47"/> <location line="-77"/>
<source>Failed to join room: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>You joined the room</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Failed to remove invite: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+19"/>
<source>Room creation failed: %1</source> <source>Room creation failed: %1</source>
<translation>Не удалось создать комнату: %1</translation> <translation>Не удалось создать комнату: %1</translation>
</message> </message>
<message> <message>
<location line="+16"/> <location line="+5"/>
<source>Room %1 created</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+11"/>
<source>Failed to leave room: %1</source> <source>Failed to leave room: %1</source>
<translation>Не удалось покинуть комнату: %1</translation> <translation>Не удалось покинуть комнату: %1</translation>
</message> </message>
@ -385,7 +451,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+73"/> <location line="+81"/>
<source>Select a file</source> <source>Select a file</source>
<translation>Выберите файл</translation> <translation>Выберите файл</translation>
</message> </message>
@ -403,7 +469,7 @@
<context> <context>
<name>TimelineModel</name> <name>TimelineModel</name>
<message> <message>
<location filename="../../src/timeline/TimelineModel.cpp" line="+698"/> <location filename="../../src/timeline/TimelineModel.cpp" line="+716"/>
<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&apos;t be decrypted</comment> <comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -647,42 +713,47 @@
<context> <context>
<name>UserSettingsPage</name> <name>UserSettingsPage</name>
<message> <message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/> <location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source> <source>Minimize to tray</source>
<translation>Сворачивать в системную панель</translation> <translation>Сворачивать в системную панель</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Start in tray</source> <source>Start in tray</source>
<translation>Запускать в системной панели</translation> <translation>Запускать в системной панели</translation>
</message> </message>
<message> <message>
<location line="+11"/> <location line="+5"/>
<source>Group&apos;s sidebar</source> <source>Group&apos;s sidebar</source>
<translation>Боковая панель групп</translation> <translation>Боковая панель групп</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Circular Avatars</source> <source>Circular Avatars</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Typing notifications</source> <source>Typing notifications</source>
<translation>Сообщать о наборе сообщения</translation> <translation>Сообщать о наборе сообщения</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Read receipts</source> <source>Read receipts</source>
<translation>Подтверждать прочтение</translation> <translation>Подтверждать прочтение</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Send messages as markdown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Desktop notifications</source> <source>Desktop notifications</source>
<translation>Уведомления на рабочем столе</translation> <translation>Уведомления на рабочем столе</translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+4"/>
<source>Scale factor</source> <source>Scale factor</source>
<translation>Масштаб</translation> <translation>Масштаб</translation>
</message> </message>
@ -742,7 +813,7 @@
<translation>ГЛАВНОЕ</translation> <translation>ГЛАВНОЕ</translation>
</message> </message>
<message> <message>
<location line="+161"/> <location line="+168"/>
<source>Open Sessions File</source> <source>Open Sessions File</source>
<translation>Открыть файл сеансов</translation> <translation>Открыть файл сеансов</translation>
</message> </message>

View File

@ -4,7 +4,53 @@
<context> <context>
<name>ChatPage</name> <name>ChatPage</name>
<message> <message>
<location filename="../../src/ChatPage.cpp" line="+328"/> <location filename="../../src/ChatPage.cpp" line="+211"/>
<source>Failed to invite user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
<location line="+84"/>
<source>Invited user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="-6"/>
<source>Failed to invite %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+20"/>
<source>Failed to kick %1 to %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Kicked user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+14"/>
<source>Failed to ban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Banned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+16"/>
<source>Failed to unban %1 in %2: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>Unbanned user: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+50"/>
<source>Failed to upload media. Please try again.</source> <source>Failed to upload media. Please try again.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -25,17 +71,37 @@
</message> </message>
<message> <message>
<location line="+51"/> <location line="+51"/>
<location line="+155"/> <location line="+154"/>
<source>Please try to login again: %1</source> <source>Please try to login again: %1</source>
<translation>%1</translation> <translation>%1</translation>
</message> </message>
<message> <message>
<location line="-47"/> <location line="-77"/>
<source>Failed to join room: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>You joined the room</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>Failed to remove invite: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+19"/>
<source>Room creation failed: %1</source> <source>Room creation failed: %1</source>
<translation>%1</translation> <translation>%1</translation>
</message> </message>
<message> <message>
<location line="+16"/> <location line="+5"/>
<source>Room %1 created</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+11"/>
<source>Failed to leave room: %1</source> <source>Failed to leave room: %1</source>
<translation>%1</translation> <translation>%1</translation>
</message> </message>
@ -385,7 +451,7 @@
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location line="+73"/> <location line="+81"/>
<source>Select a file</source> <source>Select a file</source>
<translation></translation> <translation></translation>
</message> </message>
@ -403,7 +469,7 @@
<context> <context>
<name>TimelineModel</name> <name>TimelineModel</name>
<message> <message>
<location filename="../../src/timeline/TimelineModel.cpp" line="+698"/> <location filename="../../src/timeline/TimelineModel.cpp" line="+716"/>
<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&apos;t be decrypted</comment> <comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -645,42 +711,47 @@
<context> <context>
<name>UserSettingsPage</name> <name>UserSettingsPage</name>
<message> <message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/> <location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source> <source>Minimize to tray</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Start in tray</source> <source>Start in tray</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location line="+11"/> <location line="+5"/>
<source>Group&apos;s sidebar</source> <source>Group&apos;s sidebar</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Circular Avatars</source> <source>Circular Avatars</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Typing notifications</source> <source>Typing notifications</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Read receipts</source> <source>Read receipts</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+3"/>
<source>Send messages as markdown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Desktop notifications</source> <source>Desktop notifications</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location line="+9"/> <location line="+4"/>
<source>Scale factor</source> <source>Scale factor</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -740,7 +811,7 @@
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location line="+161"/> <location line="+168"/>
<source>Open Sessions File</source> <source>Open Sessions File</source>
<translation></translation> <translation></translation>
</message> </message>

View File

@ -22,7 +22,11 @@
#include <QImage> #include <QImage>
#include <QString> #include <QString>
#if __has_include(<lmdbxx/lmdb++.h>)
#include <lmdbxx/lmdb++.h>
#else
#include <lmdb++.h> #include <lmdb++.h>
#endif
#include <mtx/responses.hpp> #include <mtx/responses.hpp>

View File

@ -26,7 +26,11 @@
#include <QImage> #include <QImage>
#include <QString> #include <QString>
#if __has_include(<lmdbxx/lmdb++.h>)
#include <lmdbxx/lmdb++.h>
#else
#include <lmdb++.h> #include <lmdb++.h>
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <mtx/responses.hpp> #include <mtx/responses.hpp>

View File

@ -116,7 +116,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
contentLayout_->setMargin(0); contentLayout_->setMargin(0);
top_bar_ = new TopRoomBar(this); top_bar_ = new TopRoomBar(this);
view_manager_ = new TimelineViewManager(this); view_manager_ = new TimelineViewManager(userSettings_, this);
contentLayout_->addWidget(top_bar_); contentLayout_->addWidget(top_bar_);
contentLayout_->addWidget(view_manager_->getWidget()); contentLayout_->addWidget(view_manager_->getWidget());
@ -208,12 +208,11 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
mtx::http::RequestErr err) { mtx::http::RequestErr err) {
if (err) { if (err) {
emit showNotification( emit showNotification(
QString("Failed to invite user: %1").arg(user)); tr("Failed to invite user: %1").arg(user));
return; return;
} }
emit showNotification( emit showNotification(tr("Invited user: %1").arg(user));
QString("Invited user: %1").arg(user));
}); });
}); });
} }
@ -280,6 +279,89 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
connect(text_input_, &TextInputWidget::sendJoinRoomRequest, this, &ChatPage::joinRoom); connect(text_input_, &TextInputWidget::sendJoinRoomRequest, this, &ChatPage::joinRoom);
// invites and bans via quick command
connect(text_input_,
&TextInputWidget::sendInviteRoomRequest,
this,
[this](QString userid, QString reason) {
http::client()->invite_user(
current_room_.toStdString(),
userid.toStdString(),
[this, userid, room = current_room_](const mtx::responses::Empty &,
mtx::http::RequestErr err) {
if (err) {
emit showNotification(tr("Failed to invite %1 to %2: %3")
.arg(userid)
.arg(room)
.arg(QString::fromStdString(
err->matrix_error.error)));
} else
emit showNotification(tr("Invited user: %1").arg(userid));
},
reason.trimmed().toStdString());
});
connect(text_input_,
&TextInputWidget::sendKickRoomRequest,
this,
[this](QString userid, QString reason) {
http::client()->kick_user(
current_room_.toStdString(),
userid.toStdString(),
[this, userid, room = current_room_](const mtx::responses::Empty &,
mtx::http::RequestErr err) {
if (err) {
emit showNotification(tr("Failed to kick %1 to %2: %3")
.arg(userid)
.arg(room)
.arg(QString::fromStdString(
err->matrix_error.error)));
} else
emit showNotification(tr("Kicked user: %1").arg(userid));
},
reason.trimmed().toStdString());
});
connect(text_input_,
&TextInputWidget::sendBanRoomRequest,
this,
[this](QString userid, QString reason) {
http::client()->ban_user(
current_room_.toStdString(),
userid.toStdString(),
[this, userid, room = current_room_](const mtx::responses::Empty &,
mtx::http::RequestErr err) {
if (err) {
emit showNotification(tr("Failed to ban %1 in %2: %3")
.arg(userid)
.arg(room)
.arg(QString::fromStdString(
err->matrix_error.error)));
} else
emit showNotification(tr("Banned user: %1").arg(userid));
},
reason.trimmed().toStdString());
});
connect(
text_input_,
&TextInputWidget::sendUnbanRoomRequest,
this,
[this](QString userid, QString reason) {
http::client()->unban_user(
current_room_.toStdString(),
userid.toStdString(),
[this, userid, room = current_room_](const mtx::responses::Empty &,
mtx::http::RequestErr err) {
if (err) {
emit showNotification(
tr("Failed to unban %1 in %2: %3")
.arg(userid)
.arg(room)
.arg(QString::fromStdString(err->matrix_error.error)));
} else
emit showNotification(tr("Unbanned user: %1").arg(userid));
},
reason.trimmed().toStdString());
});
connect( connect(
text_input_, text_input_,
&TextInputWidget::uploadMedia, &TextInputWidget::uploadMedia,
@ -1001,19 +1083,18 @@ ChatPage::joinRoom(const QString &room)
room_id, [this, room_id](const nlohmann::json &, mtx::http::RequestErr err) { room_id, [this, room_id](const nlohmann::json &, mtx::http::RequestErr err) {
if (err) { if (err) {
emit showNotification( emit showNotification(
QString("Failed to join room: %1") tr("Failed to join room: %1")
.arg(QString::fromStdString(err->matrix_error.error))); .arg(QString::fromStdString(err->matrix_error.error)));
return; return;
} }
emit showNotification("You joined the room"); emit tr("You joined the room");
// We remove any invites with the same room_id. // We remove any invites with the same room_id.
try { try {
cache::removeInvite(room_id); cache::removeInvite(room_id);
} catch (const lmdb::error &e) { } catch (const lmdb::error &e) {
emit showNotification( emit showNotification(tr("Failed to remove invite: %1").arg(e.what()));
QString("Failed to remove invite: %1").arg(e.what()));
} }
}); });
} }
@ -1036,8 +1117,8 @@ ChatPage::createRoom(const mtx::requests::CreateRoom &req)
return; return;
} }
emit showNotification(QString("Room %1 created") emit showNotification(
.arg(QString::fromStdString(res.room_id.to_string()))); tr("Room %1 created").arg(QString::fromStdString(res.room_id.to_string())));
}); });
} }

View File

@ -605,6 +605,14 @@ TextInputWidget::command(QString command, QString args)
sendEmoteMessage(args, input_->related); sendEmoteMessage(args, input_->related);
} else if (command == "join") { } else if (command == "join") {
sendJoinRoomRequest(args); sendJoinRoomRequest(args);
} else if (command == "invite") {
sendInviteRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1));
} else if (command == "kick") {
sendKickRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1));
} else if (command == "ban") {
sendBanRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1));
} else if (command == "unban") {
sendUnbanRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1));
} else if (command == "shrug") { } else if (command == "shrug") {
sendTextMessage("¯\\_(ツ)_/¯", input_->related); sendTextMessage("¯\\_(ツ)_/¯", input_->related);
} else if (command == "fliptable") { } else if (command == "fliptable") {

View File

@ -183,6 +183,10 @@ signals:
const std::optional<RelatedInfo> &related); const std::optional<RelatedInfo> &related);
void sendJoinRoomRequest(const QString &room); void sendJoinRoomRequest(const QString &room);
void sendInviteRoomRequest(const QString &userid, const QString &reason);
void sendKickRoomRequest(const QString &userid, const QString &reason);
void sendBanRoomRequest(const QString &userid, const QString &reason);
void sendUnbanRoomRequest(const QString &userid, const QString &reason);
void startedTyping(); void startedTyping();
void stoppedTyping(); void stoppedTyping();

View File

@ -50,6 +50,7 @@ UserSettings::load()
hasDesktopNotifications_ = settings.value("user/desktop_notifications", true).toBool(); hasDesktopNotifications_ = settings.value("user/desktop_notifications", true).toBool();
isStartInTrayEnabled_ = settings.value("user/window/start_in_tray", false).toBool(); isStartInTrayEnabled_ = settings.value("user/window/start_in_tray", false).toBool();
isGroupViewEnabled_ = settings.value("user/group_view", true).toBool(); isGroupViewEnabled_ = settings.value("user/group_view", true).toBool();
isMarkdownEnabled_ = settings.value("user/markdown_enabled", true).toBool();
isTypingNotificationsEnabled_ = settings.value("user/typing_notifications", true).toBool(); isTypingNotificationsEnabled_ = settings.value("user/typing_notifications", true).toBool();
isReadReceiptsEnabled_ = settings.value("user/read_receipts", true).toBool(); isReadReceiptsEnabled_ = settings.value("user/read_receipts", true).toBool();
theme_ = settings.value("user/theme", defaultTheme_).toString(); theme_ = settings.value("user/theme", defaultTheme_).toString();
@ -126,6 +127,7 @@ UserSettings::save()
settings.setValue("typing_notifications", isTypingNotificationsEnabled_); settings.setValue("typing_notifications", isTypingNotificationsEnabled_);
settings.setValue("read_receipts", isReadReceiptsEnabled_); settings.setValue("read_receipts", isReadReceiptsEnabled_);
settings.setValue("group_view", isGroupViewEnabled_); settings.setValue("group_view", isGroupViewEnabled_);
settings.setValue("markdown_enabled", isMarkdownEnabled_);
settings.setValue("desktop_notifications", hasDesktopNotifications_); settings.setValue("desktop_notifications", hasDesktopNotifications_);
settings.setValue("theme", theme()); settings.setValue("theme", theme());
settings.setValue("font_family", font_); settings.setValue("font_family", font_);
@ -167,70 +169,46 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
topBarLayout_->addWidget(backBtn_, 1, Qt::AlignLeft | Qt::AlignVCenter); topBarLayout_->addWidget(backBtn_, 1, Qt::AlignLeft | Qt::AlignVCenter);
topBarLayout_->addStretch(1); topBarLayout_->addStretch(1);
auto trayOptionLayout_ = new QHBoxLayout; auto addSetting = [this, &font](QString labelText) {
trayOptionLayout_->setContentsMargins(0, OptionMargin, 0, OptionMargin); auto layout = new QHBoxLayout;
auto trayLabel = new QLabel(tr("Minimize to tray"), this); layout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
trayLabel->setFont(font);
trayToggle_ = new Toggle(this);
trayOptionLayout_->addWidget(trayLabel); auto label = new QLabel(labelText, this);
trayOptionLayout_->addWidget(trayToggle_, 0, Qt::AlignRight); label->setFont(font);
auto startInTrayOptionLayout_ = new QHBoxLayout; auto toggle = new Toggle(this);
startInTrayOptionLayout_->setContentsMargins(0, OptionMargin, 0, OptionMargin);
auto startInTrayLabel = new QLabel(tr("Start in tray"), this); layout->addWidget(label);
startInTrayLabel->setFont(font); layout->addWidget(toggle, 0, Qt::AlignRight);
startInTrayToggle_ = new Toggle(this);
return std::pair{layout, toggle};
};
QHBoxLayout *trayOptionLayout_ = nullptr;
std::tie(trayOptionLayout_, trayToggle_) = addSetting(tr("Minimize to tray"));
QHBoxLayout *startInTrayOptionLayout_ = nullptr;
std::tie(startInTrayOptionLayout_, startInTrayToggle_) = addSetting(tr("Start in tray"));
if (!settings_->isTrayEnabled()) if (!settings_->isTrayEnabled())
startInTrayToggle_->setDisabled(true); startInTrayToggle_->setDisabled(true);
startInTrayOptionLayout_->addWidget(startInTrayLabel); QHBoxLayout *groupViewLayout = nullptr;
startInTrayOptionLayout_->addWidget(startInTrayToggle_, 0, Qt::AlignRight); std::tie(groupViewLayout, groupViewToggle_) = addSetting(tr("Group's sidebar"));
auto groupViewLayout = new QHBoxLayout; QHBoxLayout *avatarViewLayout = nullptr;
groupViewLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin); std::tie(avatarViewLayout, avatarCircles_) = addSetting(tr("Circular Avatars"));
auto groupViewLabel = new QLabel(tr("Group's sidebar"), this);
groupViewLabel->setFont(font);
groupViewToggle_ = new Toggle(this);
groupViewLayout->addWidget(groupViewLabel); QHBoxLayout *typingLayout = nullptr;
groupViewLayout->addWidget(groupViewToggle_, 0, Qt::AlignRight); std::tie(typingLayout, typingNotifications_) = addSetting(tr("Typing notifications"));
auto avatarViewLayout = new QHBoxLayout; QHBoxLayout *receiptsLayout = nullptr;
avatarViewLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin); std::tie(receiptsLayout, readReceipts_) = addSetting(tr("Read receipts"));
auto avatarViewLabel = new QLabel(tr("Circular Avatars"), this);
avatarViewLabel->setFont(font);
avatarCircles_ = new Toggle(this);
avatarViewLayout->addWidget(avatarViewLabel); QHBoxLayout *markdownLayout = nullptr;
avatarViewLayout->addWidget(avatarCircles_, 0, Qt::AlignRight); std::tie(markdownLayout, markdownEnabled_) = addSetting(tr("Send messages as markdown"));
auto typingLayout = new QHBoxLayout; QHBoxLayout *desktopLayout = nullptr;
typingLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin); std::tie(desktopLayout, desktopNotifications_) = addSetting(tr("Desktop notifications"));
auto typingLabel = new QLabel(tr("Typing notifications"), this);
typingLabel->setFont(font);
typingNotifications_ = new Toggle(this);
typingLayout->addWidget(typingLabel);
typingLayout->addWidget(typingNotifications_, 0, Qt::AlignRight);
auto receiptsLayout = new QHBoxLayout;
receiptsLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
auto receiptsLabel = new QLabel(tr("Read receipts"), this);
receiptsLabel->setFont(font);
readReceipts_ = new Toggle(this);
receiptsLayout->addWidget(receiptsLabel);
receiptsLayout->addWidget(readReceipts_, 0, Qt::AlignRight);
auto desktopLayout = new QHBoxLayout;
desktopLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
auto desktopLabel = new QLabel(tr("Desktop notifications"), this);
desktopLabel->setFont(font);
desktopNotifications_ = new Toggle(this);
desktopLayout->addWidget(desktopLabel);
desktopLayout->addWidget(desktopNotifications_, 0, Qt::AlignRight);
auto scaleFactorOptionLayout = new QHBoxLayout; auto scaleFactorOptionLayout = new QHBoxLayout;
scaleFactorOptionLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin); scaleFactorOptionLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin);
@ -385,6 +363,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
mainLayout_->addWidget(new HorizontalLine(this)); mainLayout_->addWidget(new HorizontalLine(this));
mainLayout_->addLayout(typingLayout); mainLayout_->addLayout(typingLayout);
mainLayout_->addLayout(receiptsLayout); mainLayout_->addLayout(receiptsLayout);
mainLayout_->addLayout(markdownLayout);
mainLayout_->addLayout(desktopLayout); mainLayout_->addLayout(desktopLayout);
mainLayout_->addWidget(new HorizontalLine(this)); mainLayout_->addWidget(new HorizontalLine(this));
@ -466,6 +445,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
settings_->setAvatarCircles(!isDisabled); settings_->setAvatarCircles(!isDisabled);
}); });
connect(markdownEnabled_, &Toggle::toggled, this, [this](bool isDisabled) {
settings_->setMarkdownEnabled(!isDisabled);
});
connect(typingNotifications_, &Toggle::toggled, this, [this](bool isDisabled) { connect(typingNotifications_, &Toggle::toggled, this, [this](bool isDisabled) {
settings_->setTypingNotifications(!isDisabled); settings_->setTypingNotifications(!isDisabled);
}); });
@ -496,8 +479,10 @@ UserSettingsPage::showEvent(QShowEvent *)
trayToggle_->setState(!settings_->isTrayEnabled()); trayToggle_->setState(!settings_->isTrayEnabled());
startInTrayToggle_->setState(!settings_->isStartInTrayEnabled()); startInTrayToggle_->setState(!settings_->isStartInTrayEnabled());
groupViewToggle_->setState(!settings_->isGroupViewEnabled()); groupViewToggle_->setState(!settings_->isGroupViewEnabled());
avatarCircles_->setState(!settings_->isAvatarCirclesEnabled());
typingNotifications_->setState(!settings_->isTypingNotificationsEnabled()); typingNotifications_->setState(!settings_->isTypingNotificationsEnabled());
readReceipts_->setState(!settings_->isReadReceiptsEnabled()); readReceipts_->setState(!settings_->isReadReceiptsEnabled());
markdownEnabled_->setState(!settings_->isMarkdownEnabled());
desktopNotifications_->setState(!settings_->hasDesktopNotifications()); desktopNotifications_->setState(!settings_->hasDesktopNotifications());
deviceIdValue_->setText(QString::fromStdString(http::client()->device_id())); deviceIdValue_->setText(QString::fromStdString(http::client()->device_id()));

View File

@ -68,6 +68,12 @@ public:
save(); save();
} }
void setMarkdownEnabled(bool state)
{
isMarkdownEnabled_ = state;
save();
}
void setReadReceipts(bool state) void setReadReceipts(bool state)
{ {
isReadReceiptsEnabled_ = state; isReadReceiptsEnabled_ = state;
@ -96,6 +102,8 @@ public:
bool isTrayEnabled() const { return isTrayEnabled_; } bool isTrayEnabled() const { return isTrayEnabled_; }
bool isStartInTrayEnabled() const { return isStartInTrayEnabled_; } bool isStartInTrayEnabled() const { return isStartInTrayEnabled_; }
bool isGroupViewEnabled() const { return isGroupViewEnabled_; } bool isGroupViewEnabled() const { return isGroupViewEnabled_; }
bool isAvatarCirclesEnabled() const { return avatarCircles_; }
bool isMarkdownEnabled() const { return isMarkdownEnabled_; }
bool isTypingNotificationsEnabled() const { return isTypingNotificationsEnabled_; } bool isTypingNotificationsEnabled() const { return isTypingNotificationsEnabled_; }
bool isReadReceiptsEnabled() const { return isReadReceiptsEnabled_; } bool isReadReceiptsEnabled() const { return isReadReceiptsEnabled_; }
bool hasDesktopNotifications() const { return hasDesktopNotifications_; } bool hasDesktopNotifications() const { return hasDesktopNotifications_; }
@ -116,6 +124,7 @@ private:
bool isTrayEnabled_; bool isTrayEnabled_;
bool isStartInTrayEnabled_; bool isStartInTrayEnabled_;
bool isGroupViewEnabled_; bool isGroupViewEnabled_;
bool isMarkdownEnabled_;
bool isTypingNotificationsEnabled_; bool isTypingNotificationsEnabled_;
bool isReadReceiptsEnabled_; bool isReadReceiptsEnabled_;
bool hasDesktopNotifications_; bool hasDesktopNotifications_;
@ -168,6 +177,7 @@ private:
Toggle *groupViewToggle_; Toggle *groupViewToggle_;
Toggle *typingNotifications_; Toggle *typingNotifications_;
Toggle *readReceipts_; Toggle *readReceipts_;
Toggle *markdownEnabled_;
Toggle *desktopNotifications_; Toggle *desktopNotifications_;
Toggle *avatarCircles_; Toggle *avatarCircles_;
QLabel *deviceFingerprintValue_; QLabel *deviceFingerprintValue_;

View File

@ -397,6 +397,10 @@ utils::markdownToHtml(const QString &text)
auto result = linkifyMessage(escapeBlacklistedHtml(QString::fromStdString(html))).trimmed(); auto result = linkifyMessage(escapeBlacklistedHtml(QString::fromStdString(html))).trimmed();
if (result.count("<p>") == 1 && result.startsWith("<p>") && result.endsWith("</p>")) {
result = result.mid(3, result.size() - 3 - 4);
}
return result; return result;
} }

24
src/install-debian.txt Normal file
View File

@ -0,0 +1,24 @@
sudo apt install cmake
sudo apt install gcc make automake
sudo apt install qt5-default
sudo apt install liblmdb-dev
sudo apt install qttools5-dev-tools
sudo apt install qttools5-dev-tools
sudo apt install qttools5
sudo apt install qt5-qmltooling-plugins qml-module-qtgstreamer
sudo apt install libqt5webview5-dev
sudo apt install libqt5quickcontrols2-5
sudo apt install qtquickcontrols2-5-dev
sudo apt install libssl-dev
sudo apt install qml-module-qtgraphicaleffects
sudo apt install qml-module-qtquick-controls2
sudo apt install qml-module-qtquick-layouts
sudo apt install qml-module-qtmultimedia
sudo apt install qml-module-qt-labs-settings qml-module-qt-labs-sharedimage
sudo apt install qttools5-dev
sudo apt install libqt5svg5-dev
sudo apt install qt5multimedia
sudo apt install libqt5multimedia5
sudo apt install libqt5multimedia5-plugins libqt5multimediagsttools5 libqt5multimediaquick5 libqt5multimediawidgets5
sudo apt install qt5ct
sudo apt install qtmultimedia5-dev

View File

@ -1,6 +1,7 @@
#include "TimelineModel.h" #include "TimelineModel.h"
#include <algorithm> #include <algorithm>
#include <thread>
#include <type_traits> #include <type_traits>
#include <QFileDialog> #include <QFileDialog>
@ -280,9 +281,26 @@ TimelineModel::data(const QString &id, int role) const
case FormattedBody: { case FormattedBody: {
const static QRegularExpression replyFallback( const static QRegularExpression replyFallback(
"<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption); "<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption);
return QVariant(
utils::replaceEmoji(utils::linkifyMessage(utils::escapeBlacklistedHtml( bool isReply = !in_reply_to_event(event).empty();
formattedBodyWithFallback(event).remove(replyFallback)))));
auto formattedBody_ = QString::fromStdString(formatted_body(event));
if (formattedBody_.isEmpty()) {
auto body_ = QString::fromStdString(body(event));
if (isReply) {
while (body_.startsWith("> "))
body_ = body_.right(body_.size() - body_.indexOf('\n') - 1);
if (body_.startsWith('\n'))
body_ = body_.right(body_.size() - 1);
}
formattedBody_ = body_.toHtmlEscaped().replace('\n', "<br>");
} else {
if (isReply)
formattedBody_ = formattedBody_.remove(replyFallback);
}
return QVariant(utils::replaceEmoji(
utils::linkifyMessage(utils::escapeBlacklistedHtml(formattedBody_))));
} }
case Url: case Url:
return QVariant(QString::fromStdString(url(event))); return QVariant(QString::fromStdString(url(event)));

View File

@ -18,8 +18,7 @@ Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents)
void void
TimelineViewManager::updateColorPalette() TimelineViewManager::updateColorPalette()
{ {
UserSettings settings; if (settings->theme() == "light") {
if (settings.theme() == "light") {
QPalette lightActive(/*windowText*/ QColor("#333"), QPalette lightActive(/*windowText*/ QColor("#333"),
/*button*/ QColor("#333"), /*button*/ QColor("#333"),
/*light*/ QColor(), /*light*/ QColor(),
@ -33,7 +32,7 @@ TimelineViewManager::updateColorPalette()
lightActive.setColor(QPalette::ToolTipText, lightActive.text().color()); lightActive.setColor(QPalette::ToolTipText, lightActive.text().color());
view->rootContext()->setContextProperty("currentActivePalette", lightActive); view->rootContext()->setContextProperty("currentActivePalette", lightActive);
view->rootContext()->setContextProperty("currentInactivePalette", lightActive); view->rootContext()->setContextProperty("currentInactivePalette", lightActive);
} else if (settings.theme() == "dark") { } else if (settings->theme() == "dark") {
QPalette darkActive(/*windowText*/ QColor("#caccd1"), QPalette darkActive(/*windowText*/ QColor("#caccd1"),
/*button*/ QColor("#caccd1"), /*button*/ QColor("#caccd1"),
/*light*/ QColor(), /*light*/ QColor(),
@ -54,9 +53,10 @@ TimelineViewManager::updateColorPalette()
} }
} }
TimelineViewManager::TimelineViewManager(QWidget *parent) TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettings, QWidget *parent)
: imgProvider(new MxcImageProvider()) : imgProvider(new MxcImageProvider())
, colorImgProvider(new ColorImageProvider()) , colorImgProvider(new ColorImageProvider())
, settings(userSettings)
{ {
qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject, qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject,
"im.nheko", "im.nheko",
@ -190,9 +190,17 @@ TimelineViewManager::queueTextMessage(const QString &msg, const std::optional<Re
{ {
mtx::events::msg::Text text = {}; mtx::events::msg::Text text = {};
text.body = msg.trimmed().toStdString(); text.body = msg.trimmed().toStdString();
text.format = "org.matrix.custom.html";
if (settings->isMarkdownEnabled()) {
text.formatted_body = utils::markdownToHtml(msg).toStdString(); text.formatted_body = utils::markdownToHtml(msg).toStdString();
// Don't send formatted_body, when we don't need to
if (text.formatted_body == text.body)
text.formatted_body = "";
else
text.format = "org.matrix.custom.html";
}
if (related) { if (related) {
QString body; QString body;
bool firstLine = true; bool firstLine = true;
@ -206,8 +214,17 @@ TimelineViewManager::queueTextMessage(const QString &msg, const std::optional<Re
} }
text.body = QString("%1\n%2").arg(body).arg(msg).toStdString(); text.body = QString("%1\n%2").arg(body).arg(msg).toStdString();
// NOTE(Nico): rich replies always need a formatted_body!
text.format = "org.matrix.custom.html";
if (settings->isMarkdownEnabled())
text.formatted_body = text.formatted_body =
utils::getFormattedQuoteBody(*related, utils::markdownToHtml(msg)).toStdString(); utils::getFormattedQuoteBody(*related, utils::markdownToHtml(msg))
.toStdString();
else
text.formatted_body =
utils::getFormattedQuoteBody(*related, msg.toHtmlEscaped()).toStdString();
text.relates_to.in_reply_to.event_id = related->related_event; text.relates_to.in_reply_to.event_id = related->related_event;
} }
@ -223,8 +240,10 @@ TimelineViewManager::queueEmoteMessage(const QString &msg)
mtx::events::msg::Emote emote; mtx::events::msg::Emote emote;
emote.body = msg.trimmed().toStdString(); emote.body = msg.trimmed().toStdString();
if (html != msg.trimmed().toHtmlEscaped()) if (html != msg.trimmed().toHtmlEscaped() && settings->isMarkdownEnabled()) {
emote.formatted_body = html.toStdString(); emote.formatted_body = html.toStdString();
emote.format = "org.matrix.custom.html";
}
if (timeline_) if (timeline_)
timeline_->sendMessage(emote); timeline_->sendMessage(emote);

View File

@ -15,6 +15,7 @@
class MxcImageProvider; class MxcImageProvider;
class ColorImageProvider; class ColorImageProvider;
class UserSettings;
class TimelineViewManager : public QObject class TimelineViewManager : public QObject
{ {
@ -28,7 +29,7 @@ class TimelineViewManager : public QObject
replyingEventChanged) replyingEventChanged)
public: public:
TimelineViewManager(QWidget *parent = 0); TimelineViewManager(QSharedPointer<UserSettings> userSettings, QWidget *parent = 0);
QWidget *getWidget() const { return container; } QWidget *getWidget() const { return container; }
void sync(const mtx::responses::Rooms &rooms); void sync(const mtx::responses::Rooms &rooms);
@ -109,4 +110,6 @@ private:
TimelineModel *timeline_ = nullptr; TimelineModel *timeline_ = nullptr;
bool isInitialSync_ = true; bool isInitialSync_ = true;
QString replyingEvent_; QString replyingEvent_;
QSharedPointer<UserSettings> settings;
}; };

View File

@ -1,6 +1,6 @@
#include <QPainter> #include <QPainter>
#include <tweeny/tweeny.h> #include <tweeny.h>
#include "SnackBar.h" #include "SnackBar.h"

3
toolchain.cmake Normal file
View File

@ -0,0 +1,3 @@
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)