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
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
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
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

View File

@ -19,19 +19,32 @@ if [ "$TRAVIS_OS_NAME" = "osx" ]; then
export CMAKE_PREFIX_PATH=/usr/local/opt/qt5
fi
# Build & install dependencies
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
mkdir -p .deps/usr .hunter
# Build nheko
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
cmake -GNinja -H. -Bbuild \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-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
if [ "$TRAVIS_OS_NAME" = "osx" ]; then

View File

@ -13,7 +13,7 @@ notifications:
cache:
directories:
- .deps
- .hunter
matrix:
include:
@ -23,21 +23,12 @@ matrix:
osx_image: xcode10.2
env:
- DEPLOYMENT=1
- USE_BUNDLED_BOOST=0
- USE_BUNDLED_CMARK=0
- USE_BUNDLED_JSON=0
- MTX_STATIC=1
addons:
homebrew:
taps: nlohmann/json
packages:
- boost
- clang-format
- cmake
- cmark
- icu4c
- libsodium
- lmdb
- ninja
- openssl
- qt5
@ -48,9 +39,6 @@ matrix:
- CC=gcc-7
- QT_PKG=512
- DEPLOYMENT=1
- USE_BUNDLED_BOOST=1
- USE_BUNDLED_CMARK=1
- USE_BUNDLED_JSON=1
addons:
apt:
sources:
@ -73,9 +61,6 @@ matrix:
- CXX=g++-8
- CC=gcc-8
- QT_PKG=59
- USE_BUNDLED_BOOST=1
- USE_BUNDLED_CMARK=1
- USE_BUNDLED_JSON=1
addons:
apt:
sources:
@ -98,9 +83,6 @@ matrix:
- CXX=clang++-6.0
- CC=clang-6.0
- QT_PKG=59
- USE_BUNDLED_BOOST=1
- USE_BUNDLED_CMARK=1
- USE_BUNDLED_JSON=1
addons:
apt:
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(CI_BUILD "Set when building in CI. Enables -Werror where possible" OFF)
option(ASAN "Compile with address sanitizers" 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 Qt basic functions
include(QtCommon)
project(nheko LANGUAGES C CXX)
project(nheko LANGUAGES CXX C)
set(CPACK_PACKAGE_VERSION_MAJOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "7")
set(CPACK_PACKAGE_VERSION_PATCH "0")
@ -30,39 +96,42 @@ set(IDENTIFIER "com.github.mujx.nheko")
add_project_meta(META_FILES_TO_INCLUDE)
if(APPLE)
set(OPENSSL_ROOT_DIR /usr/local/opt/openssl)
endif()
if(NOT MSVC AND NOT APPLE)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
endif()
if (BUILD_DOCS)
find_package(Doxygen)
find_package(Doxygen)
if (DOXYGEN_FOUND)
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Doxyfile.in)
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
if (DOXYGEN_FOUND)
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Doxyfile.in)
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT})
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT})
add_custom_target(docs ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM )
else (DOXYGEN_FOUND)
message("Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
add_custom_target(docs ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM )
else (DOXYGEN_FOUND)
message("Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
endif()
#
# 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.
@ -72,86 +141,76 @@ find_package(Qt5QuickCompiler)
find_package(Qt5DBus)
if (APPLE)
find_package(Qt5MacExtras REQUIRED)
find_package(Qt5MacExtras REQUIRED)
endif(APPLE)
if (Qt5Widgets_FOUND)
if (Qt5Widgets_VERSION VERSION_LESS 5.7.0)
message(STATUS "Qt version ${Qt5Widgets_VERSION}")
message(WARNING "Minimum supported Qt5 version is 5.7!")
endif()
if (Qt5Widgets_VERSION VERSION_LESS 5.9.0)
message(STATUS "Qt version ${Qt5Widgets_VERSION}")
message(WARNING "Minimum supported Qt5 version is 5.9!")
endif()
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)
if(NOT MSVC)
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} \
-Wall \
-Wextra \
-Werror \
-pipe \
-pedantic \
-fsized-deallocation \
-fdiagnostics-color=always \
-Wunreachable-code \
-std=c++17"
)
if (NOT CMAKE_COMPILER_IS_GNUCXX)
# -Wshadow is buggy and broken in GCC, so do not enable it.
# see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79328
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow")
endif()
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} \
-Wall \
-Wextra \
-pipe \
-pedantic \
-fsized-deallocation \
-fdiagnostics-color=always \
-Wunreachable-code \
-std=c++17"
)
if (NOT CMAKE_COMPILER_IS_GNUCXX)
# -Wshadow is buggy and broken in GCC, so do not enable it.
# see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79328
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow")
endif()
endif()
if (MSVC)
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} /bigobj"
)
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} /bigobj"
)
endif()
if(NOT (CMAKE_BUILD_TYPE OR CMAKE_CONFIGURATION_TYPES))
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
FORCE)
message("Setting build type to '${CMAKE_BUILD_TYPE}'")
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
FORCE)
message("Setting build type to '${CMAKE_BUILD_TYPE}'")
else(NOT (CMAKE_BUILD_TYPE OR CMAKE_CONFIGURATION_TYPES))
message("Build type set to '${CMAKE_BUILD_TYPE}'")
message("Build type set to '${CMAKE_BUILD_TYPE}'")
endif(NOT (CMAKE_BUILD_TYPE OR CMAKE_CONFIGURATION_TYPES))
set(SPDLOG_DEBUG_ON false)
# Windows doesn't handle CMAKE_BUILD_TYPE.
if(NOT WIN32)
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set(SPDLOG_DEBUG_ON true)
else()
set(SPDLOG_DEBUG_ON false)
endif()
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set(SPDLOG_DEBUG_ON true)
else()
set(SPDLOG_DEBUG_ON false)
endif()
endif()
find_program(GIT git)
if(GIT)
execute_process(
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${GIT} rev-parse --short HEAD
OUTPUT_VARIABLE GIT_OUT OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(GIT_OUT)
set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH}-${GIT_OUT}")
else()
set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH}")
endif()
execute_process(
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${GIT} rev-parse --short HEAD
OUTPUT_VARIABLE GIT_OUT OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(GIT_OUT)
set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH}-${GIT_OUT}")
else()
set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH}")
endif()
endif(GIT)
set(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
@ -168,220 +227,275 @@ configure_file(cmake/nheko.h config/nheko.h)
# Declare source and header files.
#
set(SRC_FILES
# Dialogs
src/dialogs/CreateRoom.cpp
src/dialogs/ImageOverlay.cpp
src/dialogs/PreviewUploadOverlay.cpp
src/dialogs/InviteUsers.cpp
src/dialogs/JoinRoom.cpp
src/dialogs/MemberList.cpp
src/dialogs/LeaveRoom.cpp
src/dialogs/Logout.cpp
src/dialogs/UserProfile.cpp
src/dialogs/ReadReceipts.cpp
src/dialogs/ReCaptcha.cpp
src/dialogs/RoomSettings.cpp
# Dialogs
src/dialogs/CreateRoom.cpp
src/dialogs/ImageOverlay.cpp
src/dialogs/PreviewUploadOverlay.cpp
src/dialogs/InviteUsers.cpp
src/dialogs/JoinRoom.cpp
src/dialogs/MemberList.cpp
src/dialogs/LeaveRoom.cpp
src/dialogs/Logout.cpp
src/dialogs/UserProfile.cpp
src/dialogs/ReadReceipts.cpp
src/dialogs/ReCaptcha.cpp
src/dialogs/RoomSettings.cpp
# Emoji
src/emoji/Category.cpp
src/emoji/ItemDelegate.cpp
src/emoji/Panel.cpp
src/emoji/PickButton.cpp
src/emoji/Provider.cpp
# Emoji
src/emoji/Category.cpp
src/emoji/ItemDelegate.cpp
src/emoji/Panel.cpp
src/emoji/PickButton.cpp
src/emoji/Provider.cpp
# Timeline
src/timeline/TimelineViewManager.cpp
src/timeline/TimelineModel.cpp
src/timeline/DelegateChooser.cpp
# Timeline
src/timeline/TimelineViewManager.cpp
src/timeline/TimelineModel.cpp
src/timeline/DelegateChooser.cpp
# UI components
src/ui/Avatar.cpp
src/ui/Badge.cpp
src/ui/LoadingIndicator.cpp
src/ui/InfoMessage.cpp
src/ui/FlatButton.cpp
src/ui/FloatingButton.cpp
src/ui/Label.cpp
src/ui/OverlayModal.cpp
src/ui/SnackBar.cpp
src/ui/RaisedButton.cpp
src/ui/Ripple.cpp
src/ui/RippleOverlay.cpp
src/ui/OverlayWidget.cpp
src/ui/TextField.cpp
src/ui/TextLabel.cpp
src/ui/ToggleButton.cpp
src/ui/Theme.cpp
src/ui/ThemeManager.cpp
# UI components
src/ui/Avatar.cpp
src/ui/Badge.cpp
src/ui/LoadingIndicator.cpp
src/ui/InfoMessage.cpp
src/ui/FlatButton.cpp
src/ui/FloatingButton.cpp
src/ui/Label.cpp
src/ui/OverlayModal.cpp
src/ui/SnackBar.cpp
src/ui/RaisedButton.cpp
src/ui/Ripple.cpp
src/ui/RippleOverlay.cpp
src/ui/OverlayWidget.cpp
src/ui/TextField.cpp
src/ui/TextLabel.cpp
src/ui/ToggleButton.cpp
src/ui/Theme.cpp
src/ui/ThemeManager.cpp
src/AvatarProvider.cpp
src/Cache.cpp
src/ChatPage.cpp
src/CommunitiesListItem.cpp
src/CommunitiesList.cpp
src/EventAccessors.cpp
src/InviteeItem.cpp
src/LoginPage.cpp
src/Logging.cpp
src/MainWindow.cpp
src/MatrixClient.cpp
src/MxcImageProvider.cpp
src/ColorImageProvider.cpp
src/QuickSwitcher.cpp
src/Olm.cpp
src/RegisterPage.cpp
src/RoomInfoListItem.cpp
src/RoomList.cpp
src/RunGuard.cpp
src/SideBarActions.cpp
src/Splitter.cpp
src/popups/SuggestionsPopup.cpp
src/popups/PopupItem.cpp
src/popups/ReplyPopup.cpp
src/popups/UserMentions.cpp
src/TextInputWidget.cpp
src/TopRoomBar.cpp
src/TrayIcon.cpp
src/Utils.cpp
src/UserInfoWidget.cpp
src/UserSettingsPage.cpp
src/WelcomePage.cpp
src/main.cpp
)
src/AvatarProvider.cpp
src/Cache.cpp
src/ChatPage.cpp
src/CommunitiesListItem.cpp
src/CommunitiesList.cpp
src/EventAccessors.cpp
src/InviteeItem.cpp
src/LoginPage.cpp
src/Logging.cpp
src/MainWindow.cpp
src/MatrixClient.cpp
src/MxcImageProvider.cpp
src/ColorImageProvider.cpp
src/QuickSwitcher.cpp
src/Olm.cpp
src/RegisterPage.cpp
src/RoomInfoListItem.cpp
src/RoomList.cpp
src/RunGuard.cpp
src/SideBarActions.cpp
src/Splitter.cpp
src/popups/SuggestionsPopup.cpp
src/popups/PopupItem.cpp
src/popups/ReplyPopup.cpp
src/popups/UserMentions.cpp
src/TextInputWidget.cpp
src/TopRoomBar.cpp
src/TrayIcon.cpp
src/Utils.cpp
src/UserInfoWidget.cpp
src/UserSettingsPage.cpp
src/WelcomePage.cpp
src/main.cpp
)
# ExternalProject dependencies
set(EXTERNAL_PROJECT_DEPS "")
include(FeatureSummary)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_USE_MULTITHREADED ON)
if(USE_BUNDLED_BOOST)
hunter_add_package(Boost COMPONENTS iostreams system thread)
endif()
find_package(Boost 1.70 REQUIRED
COMPONENTS atomic
chrono
date_time
iostreams
random
regex
system
thread)
COMPONENTS iostreams
system
thread)
if(USE_BUNDLED_ZLIB)
hunter_add_package(ZLIB)
endif()
find_package(ZLIB REQUIRED)
if(USE_BUNDLED_OPENSSL)
hunter_add_package(OpenSSL)
endif()
find_package(OpenSSL REQUIRED)
find_package(MatrixClient 0.3.0 REQUIRED)
find_package(Olm 2 REQUIRED)
if(USE_BUNDLED_MTXCLIENT)
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(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)
set_package_properties(nlohmann_json PROPERTIES
DESCRIPTION "JSON for Modern C++, a C++11 header-only JSON class"
URL "https://nlohmann.github.io/json/"
TYPE REQUIRED
)
DESCRIPTION "JSON for Modern C++, a C++11 header-only JSON class"
URL "https://nlohmann.github.io/json/"
TYPE REQUIRED
)
if(NOT LMDBXX_INCLUDE_DIR)
find_path(LMDBXX_INCLUDE_DIR
NAMES lmdb++.h
PATHS /usr/include
/usr/local/include
$ENV{LIB_DIR}/include
$ENV{LIB_DIR}/include/lmdbxx)
if(USE_BUNDLED_LMDBXX)
hunter_add_package(lmdbxx)
find_package(lmdbxx CONFIG REQUIRED)
else()
if(NOT LMDBXX_INCLUDE_DIR)
find_path(LMDBXX_INCLUDE_DIR
NAMES lmdb++.h
PATHS /usr/include
/usr/local/include
$ENV{LIB_DIR}/include
$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()
include_directories(SYSTEM ${LMDBXX_INCLUDE_DIR})
if(NOT TWEENY_INCLUDE_DIR)
find_path(TWEENY_INCLUDE_DIR
NAMES tweeny/tweeny.h
PATHS /usr/include/
/usr/local/include/
$ENV{LIB_DIR}/include/
$ENV{LIB_DIR}/include/tweeny)
if(USE_BUNDLED_TWEENY)
include(FetchContent)
FetchContent_Declare(
Tweeny
GIT_REPOSITORY https://github.com/mobius3/tweeny.git
GIT_TAG 6a5033372fe53c4c731c66c8a2d56261746cd85c #v3 <- v3 has unfixed warnings
)
FetchContent_MakeAvailable(Tweeny)
else()
find_package(Tweeny REQUIRED)
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)
qt5_wrap_cpp(MOC_HEADERS
# Dialogs
src/dialogs/CreateRoom.h
src/dialogs/ImageOverlay.h
src/dialogs/PreviewUploadOverlay.h
src/dialogs/InviteUsers.h
src/dialogs/JoinRoom.h
src/dialogs/MemberList.h
src/dialogs/LeaveRoom.h
src/dialogs/Logout.h
src/dialogs/UserProfile.h
src/dialogs/RawMessage.h
src/dialogs/ReadReceipts.h
src/dialogs/ReCaptcha.h
src/dialogs/RoomSettings.h
# Dialogs
src/dialogs/CreateRoom.h
src/dialogs/ImageOverlay.h
src/dialogs/PreviewUploadOverlay.h
src/dialogs/InviteUsers.h
src/dialogs/JoinRoom.h
src/dialogs/MemberList.h
src/dialogs/LeaveRoom.h
src/dialogs/Logout.h
src/dialogs/UserProfile.h
src/dialogs/RawMessage.h
src/dialogs/ReadReceipts.h
src/dialogs/ReCaptcha.h
src/dialogs/RoomSettings.h
# Emoji
src/emoji/Category.h
src/emoji/ItemDelegate.h
src/emoji/Panel.h
src/emoji/PickButton.h
# Emoji
src/emoji/Category.h
src/emoji/ItemDelegate.h
src/emoji/Panel.h
src/emoji/PickButton.h
# Timeline
src/timeline/TimelineViewManager.h
src/timeline/TimelineModel.h
src/timeline/DelegateChooser.h
# Timeline
src/timeline/TimelineViewManager.h
src/timeline/TimelineModel.h
src/timeline/DelegateChooser.h
# UI components
src/ui/Avatar.h
src/ui/Badge.h
src/ui/LoadingIndicator.h
src/ui/InfoMessage.h
src/ui/FlatButton.h
src/ui/Label.h
src/ui/FloatingButton.h
src/ui/Menu.h
src/ui/OverlayWidget.h
src/ui/SnackBar.h
src/ui/RaisedButton.h
src/ui/Ripple.h
src/ui/RippleOverlay.h
src/ui/TextField.h
src/ui/TextLabel.h
src/ui/ToggleButton.h
src/ui/Theme.h
src/ui/ThemeManager.h
# UI components
src/ui/Avatar.h
src/ui/Badge.h
src/ui/LoadingIndicator.h
src/ui/InfoMessage.h
src/ui/FlatButton.h
src/ui/Label.h
src/ui/FloatingButton.h
src/ui/Menu.h
src/ui/OverlayWidget.h
src/ui/SnackBar.h
src/ui/RaisedButton.h
src/ui/Ripple.h
src/ui/RippleOverlay.h
src/ui/TextField.h
src/ui/TextLabel.h
src/ui/ToggleButton.h
src/ui/Theme.h
src/ui/ThemeManager.h
src/notifications/Manager.h
src/notifications/Manager.h
src/AvatarProvider.h
src/Cache_p.h
src/ChatPage.h
src/CommunitiesListItem.h
src/CommunitiesList.h
src/LoginPage.h
src/MainWindow.h
src/MxcImageProvider.h
src/InviteeItem.h
src/QuickSwitcher.h
src/RegisterPage.h
src/RoomInfoListItem.h
src/RoomList.h
src/SideBarActions.h
src/Splitter.h
src/popups/SuggestionsPopup.h
src/popups/ReplyPopup.h
src/popups/PopupItem.h
src/popups/UserMentions.h
src/TextInputWidget.h
src/TopRoomBar.h
src/TrayIcon.h
src/UserInfoWidget.h
src/UserSettingsPage.h
src/WelcomePage.h
)
src/AvatarProvider.h
src/Cache_p.h
src/ChatPage.h
src/CommunitiesListItem.h
src/CommunitiesList.h
src/LoginPage.h
src/MainWindow.h
src/MxcImageProvider.h
src/InviteeItem.h
src/QuickSwitcher.h
src/RegisterPage.h
src/RoomInfoListItem.h
src/RoomList.h
src/SideBarActions.h
src/Splitter.h
src/popups/SuggestionsPopup.h
src/popups/ReplyPopup.h
src/popups/PopupItem.h
src/popups/UserMentions.h
src/TextInputWidget.h
src/TopRoomBar.h
src/TrayIcon.h
src/UserInfoWidget.h
src/UserSettingsPage.h
src/WelcomePage.h
)
#
# Bundle translations.
@ -389,96 +503,106 @@ qt5_wrap_cpp(MOC_HEADERS
include(Translations)
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)
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(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)
elseif (WIN32)
file(DOWNLOAD
"https://raw.githubusercontent.com/mohabouje/WinToast/41ed1c58d5dce0ee9c01dbdeac05be45358d4f57/src/wintoastlib.cpp"
${PROJECT_SOURCE_DIR}/src/wintoastlib.cpp
EXPECTED_HASH SHA256=1A1A7CE41C1052B12946798F4A6C67CE1FAD209C967F5ED4D720B173527E2073)
file(DOWNLOAD
"https://raw.githubusercontent.com/mohabouje/WinToast/41ed1c58d5dce0ee9c01dbdeac05be45358d4f57/src/wintoastlib.cpp"
${PROJECT_SOURCE_DIR}/src/wintoastlib.cpp
EXPECTED_HASH SHA256=1A1A7CE41C1052B12946798F4A6C67CE1FAD209C967F5ED4D720B173527E2073)
file(DOWNLOAD
"https://raw.githubusercontent.com/mohabouje/WinToast/41ed1c58d5dce0ee9c01dbdeac05be45358d4f57/src/wintoastlib.h"
${PROJECT_SOURCE_DIR}/src/wintoastlib.h
EXPECTED_HASH SHA256=b4481023c5782733795838be22bf1a75f45d87458cd4d9a5a75f664a146eea11)
file(DOWNLOAD
"https://raw.githubusercontent.com/mohabouje/WinToast/41ed1c58d5dce0ee9c01dbdeac05be45358d4f57/src/wintoastlib.h"
${PROJECT_SOURCE_DIR}/src/wintoastlib.h
EXPECTED_HASH SHA256=b4481023c5782733795838be22bf1a75f45d87458cd4d9a5a75f664a146eea11)
set(SRC_FILES ${SRC_FILES} src/notifications/ManagerWin.cpp src/wintoastlib.cpp)
set(SRC_FILES ${SRC_FILES} src/notifications/ManagerWin.cpp src/wintoastlib.cpp)
else ()
set(SRC_FILES ${SRC_FILES} src/notifications/ManagerLinux.cpp)
set(SRC_FILES ${SRC_FILES} src/notifications/ManagerLinux.cpp)
endif ()
set(NHEKO_DEPS
${SRC_FILES}
${UI_HEADERS}
${MOC_HEADERS}
${TRANSLATION_DEPS}
${META_FILES_TO_INCLUDE})
${SRC_FILES}
${UI_HEADERS}
${MOC_HEADERS}
${TRANSLATION_DEPS}
${META_FILES_TO_INCLUDE})
if(ASAN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined")
endif()
add_executable (nheko ${OS_BUNDLE} ${NHEKO_DEPS})
if(APPLE)
add_executable (nheko ${OS_BUNDLE} ${NHEKO_DEPS})
target_link_libraries (nheko ${NHEKO_LIBS} Qt5::MacExtras)
target_link_libraries (nheko PRIVATE Qt5::MacExtras)
elseif(WIN32)
add_executable (nheko ${OS_BUNDLE} ${ICON_FILE} ${NHEKO_DEPS})
target_compile_definitions(nheko PRIVATE WIN32_LEAN_AND_MEAN)
target_link_libraries (nheko ${NTDLIB} ${NHEKO_LIBS} Qt5::WinMain)
target_compile_definitions(nheko PRIVATE WIN32_LEAN_AND_MEAN)
target_link_libraries (nheko PRIVATE ${NTDLIB} Qt5::WinMain)
else()
add_executable (nheko ${OS_BUNDLE} ${NHEKO_DEPS})
target_link_libraries (nheko ${NHEKO_LIBS} Qt5::DBus)
target_link_libraries (nheko PRIVATE Qt5::DBus)
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)
target_compile_definitions(nheko PRIVATE QML_DEBUGGING)
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()
set_target_properties(nheko PROPERTIES SKIP_BUILD_RPATH TRUE)
if(UNIX AND NOT APPLE)
install (TARGETS nheko RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
install (FILES "resources/nheko-16.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME "nheko.png")
install (FILES "resources/nheko-32.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME "nheko.png")
install (FILES "resources/nheko-48.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps" RENAME "nheko.png")
install (FILES "resources/nheko-64.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps" RENAME "nheko.png")
install (FILES "resources/nheko-128.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps" RENAME "nheko.png")
install (FILES "resources/nheko-256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "nheko.png")
install (FILES "resources/nheko-512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "nheko.png")
install (FILES "resources/nheko.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
install (FILES "resources/nheko.appdata.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo")
install (TARGETS nheko RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
install (FILES "resources/nheko-16.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME "nheko.png")
install (FILES "resources/nheko-32.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME "nheko.png")
install (FILES "resources/nheko-48.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps" RENAME "nheko.png")
install (FILES "resources/nheko-64.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps" RENAME "nheko.png")
install (FILES "resources/nheko-128.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps" RENAME "nheko.png")
install (FILES "resources/nheko-256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "nheko.png")
install (FILES "resources/nheko-512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "nheko.png")
install (FILES "resources/nheko.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
install (FILES "resources/nheko.appdata.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo")
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
endif()

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
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
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.
Specifically there is support for:
- E2E encryption (text messages only: attachments are currently sent unencrypted).
- E2E encryption.
- User registration.
- Creating, joining & leaving rooms.
- Sending & receiving invites.
- 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.
- Username auto-completion.
- Message & mention notifications.
@ -61,7 +63,7 @@ sudo dnf install nheko
#### Gentoo Linux
```bash
sudo layman -a matrix
sudo eselect repository enable matrix
sudo emerge -a nheko
```
@ -105,6 +107,27 @@ sudo port install nheko
- GCC 7 (tested on Travis CI)
- 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
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
```
##### 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)
```bash
@ -158,61 +192,29 @@ brew install qt5 lmdb cmake llvm libsodium spdlog boost cmark
(for the CMake integration) workloads.
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).
3. Install dependencies with `vcpkg`. You can simply clone it into a subfolder
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
```
3. If you don't have openssl installed, you will need to install perl to build it (i.e. Strawberry Perl).
### Building
First we need to install the rest of the dependencies that are not available in our system
We can now build nheko:
```bash
cmake -Hdeps -B.deps \
-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 -H. -Bbuild -DCMAKE_BUILD_TYPE=Release
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
```
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
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`.
The toolchain file should point to the `vcpkg.cmake` and the Qt5 dir to the `lib\cmake\Qt5` dir.
You need to fill out the paths for the `Qt5_DIR`.
The Qt5 dir should point to the `lib\cmake\Qt5` dir.
Examples for the paths are:
- `C:\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake`
- `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`.
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.
@ -261,6 +264,9 @@ windeployqt nheko.exe
The final binary will be located inside `build-vc\Release\Release` for the Release 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
See [CONTRIBUTING](.github/CONTRIBUTING.md)

View File

@ -1,9 +1,9 @@
---
version: 0.6.4-{build}
version: 0.7.0-{build}
configuration: Release
image: Visual Studio 2019
image: Visual Studio 2017
platform: x64
environment:
@ -11,32 +11,16 @@ environment:
secure: "iGl5mzE9/ta9kFELUxDw9XtlYMSCMai9xowXIkYzU8WKHz7NfW0mLwMJZvblZFXJ"
cache:
- c:\tools\vcpkg\installed\ -> appveyor.yml
# - .deps -> appveyor.yml,deps\CMakeLists.txt <- disabled because it randomly seems to break everytime
- c:\hunter\ -> appveyor.yml
- build\_deps -> appveyor.yml,deps\CMakeLists.txt
build:
verbosity: minimal
install:
- set QT_DIR=C:\Qt\5.14\msvc2017_64
- set PATH=%PATH%;%QT_DIR%\bin;C:\MinGW\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\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
- set QT_DIR=C:\Qt\5.13\msvc2017_64
- set PATH=%PATH%;%QT_DIR%\bin
- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
build_script:
# VERSION format: branch-master/branch-1.2
@ -57,23 +41,13 @@ build_script:
- echo %INSTVERSION%
- 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
- rm -f cmake/FindOlm.cmake
- cmake -G "Visual Studio 16 2019" -A x64 -H. -Bbuild
-DCMAKE_TOOLCHAIN_FILE=C:/Tools/vcpkg/scripts/buildsystems/vcpkg.cmake
-DLMDBXX_INCLUDE_DIR=.deps/usr/include
-DTWEENY_INCLUDE_DIR=.deps/usr/include
-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 -G "Visual Studio 16 2019" -A x64 -H. -Bbuild
- cmake -G "Visual Studio 15 2017 Win64" -H. -Bbuild
-DHUNTER_ROOT="C:\hunter"
-DHUNTER_ENABLED=ON -DBUILD_SHARED_LIBS=OFF
-DCMAKE_BUILD_TYPE=Release -DHUNTER_CONFIGURATION_TYPES=Release
- cmake --build build --config Release
after_build:
@ -82,12 +56,9 @@ after_build:
- echo %BUILD%
- mkdir NhekoRelease
- 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
- 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\*
- ls -lh build\Release\
- 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>
<name>ChatPage</name>
<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>
<translation>Medienupload fehlgeschlagen. Bitte versuche es erneut.</translation>
</message>
@ -25,17 +71,37 @@
</message>
<message>
<location line="+51"/>
<location line="+155"/>
<location line="+154"/>
<source>Please try to login again: %1</source>
<translation>Bitte melde dich erneut an: %1</translation>
</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>
<translation>Raum konnte nicht erstellt werden: %1</translation>
</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>
<translation>Konnte den Raum nicht verlassen: %1</translation>
</message>
@ -385,7 +451,7 @@
<translation>Emoji</translation>
</message>
<message>
<location line="+73"/>
<location line="+81"/>
<source>Select a file</source>
<translation>Datei auswählen</translation>
</message>
@ -403,7 +469,7 @@
<context>
<name>TimelineModel</name>
<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>
<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>
@ -646,42 +712,47 @@
<context>
<name>UserSettingsPage</name>
<message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/>
<location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source>
<translation>Ins Benachrichtigungsfeld minimieren</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Start in tray</source>
<translation>Im Benachrichtigungsfeld starten</translation>
</message>
<message>
<location line="+11"/>
<location line="+5"/>
<source>Group&apos;s sidebar</source>
<translation>Gruppen-Seitenleiste</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Circular Avatars</source>
<translation>Runde Profilbilder</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Typing notifications</source>
<translation>Schreibbenachrichtigungen</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Read receipts</source>
<translation>Lesebestätigungen</translation>
</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>
<translation>Desktopbenachrichtigungen</translation>
</message>
<message>
<location line="+9"/>
<location line="+4"/>
<source>Scale factor</source>
<translation>Skalierungsfaktor</translation>
</message>
@ -741,7 +812,7 @@
<translation>ALLGEMEINES</translation>
</message>
<message>
<location line="+161"/>
<location line="+168"/>
<source>Open Sessions File</source>
<translation>Öffne Sessions Datei</translation>
</message>

View File

@ -4,7 +4,53 @@
<context>
<name>ChatPage</name>
<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>
<translation type="unfinished"></translation>
</message>
@ -25,17 +71,37 @@
</message>
<message>
<location line="+51"/>
<location line="+155"/>
<location line="+154"/>
<source>Please try to login again: %1</source>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</message>
@ -385,7 +451,7 @@
<translation type="unfinished"></translation>
</message>
<message>
<location line="+73"/>
<location line="+81"/>
<source>Select a file</source>
<translation>Διάλεξε ένα αρχείο</translation>
</message>
@ -403,7 +469,7 @@
<context>
<name>TimelineModel</name>
<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>
<comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation>
@ -646,42 +712,47 @@
<context>
<name>UserSettingsPage</name>
<message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/>
<location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source>
<translation>Ελαχιστοποίηση</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Start in tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+11"/>
<location line="+5"/>
<source>Group&apos;s sidebar</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Circular Avatars</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Typing notifications</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Read receipts</source>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+4"/>
<source>Scale factor</source>
<translation type="unfinished"></translation>
</message>
@ -741,7 +812,7 @@
<translation>ΓΕΝΙΚΑ</translation>
</message>
<message>
<location line="+161"/>
<location line="+168"/>
<source>Open Sessions File</source>
<translation type="unfinished"></translation>
</message>

View File

@ -4,7 +4,53 @@
<context>
<name>ChatPage</name>
<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>
<translation type="unfinished"></translation>
</message>
@ -25,17 +71,37 @@
</message>
<message>
<location line="+51"/>
<location line="+155"/>
<location line="+154"/>
<source>Please try to login again: %1</source>
<translation>Please try to login again: %1</translation>
</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>
<translation>Room creation failed: %1</translation>
</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>
<translation>Failed to leave room: %1</translation>
</message>
@ -385,7 +451,7 @@
<translation>Emoji</translation>
</message>
<message>
<location line="+73"/>
<location line="+81"/>
<source>Select a file</source>
<translation>Select a file</translation>
</message>
@ -403,7 +469,7 @@
<context>
<name>TimelineModel</name>
<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>
<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>
@ -646,42 +712,47 @@
<context>
<name>UserSettingsPage</name>
<message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/>
<location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source>
<translation>Minimize to tray</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Start in tray</source>
<translation>Start in tray</translation>
</message>
<message>
<location line="+11"/>
<location line="+5"/>
<source>Group&apos;s sidebar</source>
<translation>Group&apos;s sidebar</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Circular Avatars</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Typing notifications</source>
<translation>Typing notifications</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Read receipts</source>
<translation>Read receipts</translation>
</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>
<translation>Desktop notifications</translation>
</message>
<message>
<location line="+9"/>
<location line="+4"/>
<source>Scale factor</source>
<translation>Scale factor</translation>
</message>
@ -741,7 +812,7 @@
<translation>GENERAL</translation>
</message>
<message>
<location line="+161"/>
<location line="+168"/>
<source>Open Sessions File</source>
<translation>Open Sessions File</translation>
</message>

View File

@ -4,7 +4,53 @@
<context>
<name>ChatPage</name>
<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>
<translation type="unfinished"></translation>
</message>
@ -25,17 +71,37 @@
</message>
<message>
<location line="+51"/>
<location line="+155"/>
<location line="+154"/>
<source>Please try to login again: %1</source>
<translation>Ole hyvä ja yritä kirjautua sisään uudelleen: %1</translation>
</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>
<translation>Huoneen luominen epäonnistui: %1</translation>
</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>
<translation>Huoneesta poistuminen epäonnistui: %1</translation>
</message>
@ -385,7 +451,7 @@
<translation>Emoji</translation>
</message>
<message>
<location line="+73"/>
<location line="+81"/>
<source>Select a file</source>
<translation>Valitse tiedosto</translation>
</message>
@ -403,7 +469,7 @@
<context>
<name>TimelineModel</name>
<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>
<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>
@ -646,42 +712,47 @@
<context>
<name>UserSettingsPage</name>
<message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/>
<location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source>
<translation>Pienennä ilmoitusalueelle</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Start in tray</source>
<translation>Aloita ilmoitusalueella</translation>
</message>
<message>
<location line="+11"/>
<location line="+5"/>
<source>Group&apos;s sidebar</source>
<translation>Ryhmäsivupalkki</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Circular Avatars</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Typing notifications</source>
<translation>Kirjoitusilmoitukset</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Read receipts</source>
<translation>Lukukuittaukset</translation>
</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>
<translation>Työpöytäilmoitukset</translation>
</message>
<message>
<location line="+9"/>
<location line="+4"/>
<source>Scale factor</source>
<translation>Mittakerroin</translation>
</message>
@ -741,7 +812,7 @@
<translation>YLEISET ASETUKSET</translation>
</message>
<message>
<location line="+161"/>
<location line="+168"/>
<source>Open Sessions File</source>
<translation>Avaa Istuntoavaintiedosto</translation>
</message>

View File

@ -4,7 +4,53 @@
<context>
<name>ChatPage</name>
<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>
<translation type="unfinished"></translation>
</message>
@ -25,17 +71,37 @@
</message>
<message>
<location line="+51"/>
<location line="+155"/>
<location line="+154"/>
<source>Please try to login again: %1</source>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</message>
@ -386,7 +452,7 @@
<translation type="unfinished"></translation>
</message>
<message>
<location line="+73"/>
<location line="+81"/>
<source>Select a file</source>
<translation>Sélectionnez un fichier</translation>
</message>
@ -404,7 +470,7 @@
<context>
<name>TimelineModel</name>
<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>
<comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation>
@ -647,42 +713,47 @@
<context>
<name>UserSettingsPage</name>
<message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/>
<location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source>
<translation>Réduire à la barre des tâches</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Start in tray</source>
<translation>Démarrer dans la barre des tâches</translation>
</message>
<message>
<location line="+11"/>
<location line="+5"/>
<source>Group&apos;s sidebar</source>
<translation>Barre latérale des groupes</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Circular Avatars</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Typing notifications</source>
<translation>Notifications d&apos;écriture</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Read receipts</source>
<translation>Accusés de lecture</translation>
</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>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+4"/>
<source>Scale factor</source>
<translation type="unfinished"></translation>
</message>
@ -742,7 +813,7 @@
<translation>GÉNÉRAL</translation>
</message>
<message>
<location line="+161"/>
<location line="+168"/>
<source>Open Sessions File</source>
<translation type="unfinished"></translation>
</message>

View File

@ -4,7 +4,53 @@
<context>
<name>ChatPage</name>
<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>
<translation type="unfinished"></translation>
</message>
@ -25,17 +71,37 @@
</message>
<message>
<location line="+51"/>
<location line="+155"/>
<location line="+154"/>
<source>Please try to login again: %1</source>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</message>
@ -385,7 +451,7 @@
<translation type="unfinished"></translation>
</message>
<message>
<location line="+73"/>
<location line="+81"/>
<source>Select a file</source>
<translation>Kies een bestand</translation>
</message>
@ -403,7 +469,7 @@
<context>
<name>TimelineModel</name>
<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>
<comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation>
@ -646,42 +712,47 @@
<context>
<name>UserSettingsPage</name>
<message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/>
<location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source>
<translation>Minimaliseren naar systeemvak</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Start in tray</source>
<translation>Geminimaliseerd opstarten</translation>
</message>
<message>
<location line="+11"/>
<location line="+5"/>
<source>Group&apos;s sidebar</source>
<translation>Zijbalk van groep</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Circular Avatars</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Typing notifications</source>
<translation>Meldingen bij typen van berichten</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Read receipts</source>
<translation>Leesbevestigingen</translation>
</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>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+4"/>
<source>Scale factor</source>
<translation type="unfinished"></translation>
</message>
@ -741,7 +812,7 @@
<translation>ALGEMEEN</translation>
</message>
<message>
<location line="+161"/>
<location line="+168"/>
<source>Open Sessions File</source>
<translation type="unfinished"></translation>
</message>

View File

@ -4,7 +4,53 @@
<context>
<name>ChatPage</name>
<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>
<translation type="unfinished"></translation>
</message>
@ -25,17 +71,37 @@
</message>
<message>
<location line="+51"/>
<location line="+155"/>
<location line="+154"/>
<source>Please try to login again: %1</source>
<translation>Spróbuj zalogować się ponownie: %1</translation>
</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>
<translation>Tworzenie pokoju nie powiodło się: %1</translation>
</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>
<translation>Nie udało się opuścić pokoju: %1</translation>
</message>
@ -385,7 +451,7 @@
<translation>Emoji</translation>
</message>
<message>
<location line="+73"/>
<location line="+81"/>
<source>Select a file</source>
<translation>Wybierz plik</translation>
</message>
@ -403,7 +469,7 @@
<context>
<name>TimelineModel</name>
<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>
<comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation>
@ -647,42 +713,47 @@
<context>
<name>UserSettingsPage</name>
<message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/>
<location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source>
<translation>Zminimalizuj do paska zadań</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Start in tray</source>
<translation>Rozpocznij na pasku zadań</translation>
</message>
<message>
<location line="+11"/>
<location line="+5"/>
<source>Group&apos;s sidebar</source>
<translation>Pasek boczny grupy</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Circular Avatars</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Typing notifications</source>
<translation>Powiadomienia o pisaniu</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Read receipts</source>
<translation>Potwierdzenia przeczytania</translation>
</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>
<translation>Powiadomienia na pulpicie</translation>
</message>
<message>
<location line="+9"/>
<location line="+4"/>
<source>Scale factor</source>
<translation type="unfinished"></translation>
</message>
@ -742,7 +813,7 @@
<translation>OGÓLNE</translation>
</message>
<message>
<location line="+161"/>
<location line="+168"/>
<source>Open Sessions File</source>
<translation type="unfinished"></translation>
</message>

View File

@ -4,7 +4,53 @@
<context>
<name>ChatPage</name>
<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>
<translation type="unfinished"></translation>
</message>
@ -25,17 +71,37 @@
</message>
<message>
<location line="+51"/>
<location line="+155"/>
<location line="+154"/>
<source>Please try to login again: %1</source>
<translation>Повторите попытку входа: %1</translation>
</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>
<translation>Не удалось создать комнату: %1</translation>
</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>
<translation>Не удалось покинуть комнату: %1</translation>
</message>
@ -385,7 +451,7 @@
<translation type="unfinished"></translation>
</message>
<message>
<location line="+73"/>
<location line="+81"/>
<source>Select a file</source>
<translation>Выберите файл</translation>
</message>
@ -403,7 +469,7 @@
<context>
<name>TimelineModel</name>
<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>
<comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation>
@ -647,42 +713,47 @@
<context>
<name>UserSettingsPage</name>
<message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/>
<location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source>
<translation>Сворачивать в системную панель</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Start in tray</source>
<translation>Запускать в системной панели</translation>
</message>
<message>
<location line="+11"/>
<location line="+5"/>
<source>Group&apos;s sidebar</source>
<translation>Боковая панель групп</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Circular Avatars</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Typing notifications</source>
<translation>Сообщать о наборе сообщения</translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Read receipts</source>
<translation>Подтверждать прочтение</translation>
</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>
<translation>Уведомления на рабочем столе</translation>
</message>
<message>
<location line="+9"/>
<location line="+4"/>
<source>Scale factor</source>
<translation>Масштаб</translation>
</message>
@ -742,7 +813,7 @@
<translation>ГЛАВНОЕ</translation>
</message>
<message>
<location line="+161"/>
<location line="+168"/>
<source>Open Sessions File</source>
<translation>Открыть файл сеансов</translation>
</message>

View File

@ -4,7 +4,53 @@
<context>
<name>ChatPage</name>
<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>
<translation type="unfinished"></translation>
</message>
@ -25,17 +71,37 @@
</message>
<message>
<location line="+51"/>
<location line="+155"/>
<location line="+154"/>
<source>Please try to login again: %1</source>
<translation>%1</translation>
</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>
<translation>%1</translation>
</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>
<translation>%1</translation>
</message>
@ -385,7 +451,7 @@
<translation></translation>
</message>
<message>
<location line="+73"/>
<location line="+81"/>
<source>Select a file</source>
<translation></translation>
</message>
@ -403,7 +469,7 @@
<context>
<name>TimelineModel</name>
<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>
<comment>Placeholder, when the message was not decrypted yet or can&apos;t be decrypted</comment>
<translation type="unfinished"></translation>
@ -645,42 +711,47 @@
<context>
<name>UserSettingsPage</name>
<message>
<location filename="../../src/UserSettingsPage.cpp" line="+172"/>
<location filename="../../src/UserSettingsPage.cpp" line="+188"/>
<source>Minimize to tray</source>
<translation></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Start in tray</source>
<translation></translation>
</message>
<message>
<location line="+11"/>
<location line="+5"/>
<source>Group&apos;s sidebar</source>
<translation></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Circular Avatars</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Typing notifications</source>
<translation></translation>
</message>
<message>
<location line="+9"/>
<location line="+3"/>
<source>Read receipts</source>
<translation></translation>
</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>
<translation></translation>
</message>
<message>
<location line="+9"/>
<location line="+4"/>
<source>Scale factor</source>
<translation type="unfinished"></translation>
</message>
@ -740,7 +811,7 @@
<translation></translation>
</message>
<message>
<location line="+161"/>
<location line="+168"/>
<source>Open Sessions File</source>
<translation></translation>
</message>

View File

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

View File

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

View File

@ -116,7 +116,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
contentLayout_->setMargin(0);
top_bar_ = new TopRoomBar(this);
view_manager_ = new TimelineViewManager(this);
view_manager_ = new TimelineViewManager(userSettings_, this);
contentLayout_->addWidget(top_bar_);
contentLayout_->addWidget(view_manager_->getWidget());
@ -208,12 +208,11 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
mtx::http::RequestErr err) {
if (err) {
emit showNotification(
QString("Failed to invite user: %1").arg(user));
tr("Failed to invite user: %1").arg(user));
return;
}
emit showNotification(
QString("Invited user: %1").arg(user));
emit showNotification(tr("Invited user: %1").arg(user));
});
});
}
@ -280,6 +279,89 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
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(
text_input_,
&TextInputWidget::uploadMedia,
@ -1001,19 +1083,18 @@ ChatPage::joinRoom(const QString &room)
room_id, [this, room_id](const nlohmann::json &, mtx::http::RequestErr err) {
if (err) {
emit showNotification(
QString("Failed to join room: %1")
tr("Failed to join room: %1")
.arg(QString::fromStdString(err->matrix_error.error)));
return;
}
emit showNotification("You joined the room");
emit tr("You joined the room");
// We remove any invites with the same room_id.
try {
cache::removeInvite(room_id);
} catch (const lmdb::error &e) {
emit showNotification(
QString("Failed to remove invite: %1").arg(e.what()));
emit showNotification(tr("Failed to remove invite: %1").arg(e.what()));
}
});
}
@ -1036,8 +1117,8 @@ ChatPage::createRoom(const mtx::requests::CreateRoom &req)
return;
}
emit showNotification(QString("Room %1 created")
.arg(QString::fromStdString(res.room_id.to_string())));
emit showNotification(
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);
} else if (command == "join") {
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") {
sendTextMessage("¯\\_(ツ)_/¯", input_->related);
} else if (command == "fliptable") {

View File

@ -183,6 +183,10 @@ signals:
const std::optional<RelatedInfo> &related);
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 stoppedTyping();

View File

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

View File

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

View File

@ -397,6 +397,10 @@ utils::markdownToHtml(const QString &text)
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;
}

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 <algorithm>
#include <thread>
#include <type_traits>
#include <QFileDialog>
@ -280,9 +281,26 @@ TimelineModel::data(const QString &id, int role) const
case FormattedBody: {
const static QRegularExpression replyFallback(
"<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption);
return QVariant(
utils::replaceEmoji(utils::linkifyMessage(utils::escapeBlacklistedHtml(
formattedBodyWithFallback(event).remove(replyFallback)))));
bool isReply = !in_reply_to_event(event).empty();
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:
return QVariant(QString::fromStdString(url(event)));

View File

@ -18,8 +18,7 @@ Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents)
void
TimelineViewManager::updateColorPalette()
{
UserSettings settings;
if (settings.theme() == "light") {
if (settings->theme() == "light") {
QPalette lightActive(/*windowText*/ QColor("#333"),
/*button*/ QColor("#333"),
/*light*/ QColor(),
@ -33,7 +32,7 @@ TimelineViewManager::updateColorPalette()
lightActive.setColor(QPalette::ToolTipText, lightActive.text().color());
view->rootContext()->setContextProperty("currentActivePalette", lightActive);
view->rootContext()->setContextProperty("currentInactivePalette", lightActive);
} else if (settings.theme() == "dark") {
} else if (settings->theme() == "dark") {
QPalette darkActive(/*windowText*/ QColor("#caccd1"),
/*button*/ QColor("#caccd1"),
/*light*/ QColor(),
@ -54,9 +53,10 @@ TimelineViewManager::updateColorPalette()
}
}
TimelineViewManager::TimelineViewManager(QWidget *parent)
TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettings, QWidget *parent)
: imgProvider(new MxcImageProvider())
, colorImgProvider(new ColorImageProvider())
, settings(userSettings)
{
qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject,
"im.nheko",
@ -190,8 +190,16 @@ TimelineViewManager::queueTextMessage(const QString &msg, const std::optional<Re
{
mtx::events::msg::Text text = {};
text.body = msg.trimmed().toStdString();
text.format = "org.matrix.custom.html";
text.formatted_body = utils::markdownToHtml(msg).toStdString();
if (settings->isMarkdownEnabled()) {
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) {
QString body;
@ -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.formatted_body =
utils::getFormattedQuoteBody(*related, utils::markdownToHtml(msg)).toStdString();
// NOTE(Nico): rich replies always need a formatted_body!
text.format = "org.matrix.custom.html";
if (settings->isMarkdownEnabled())
text.formatted_body =
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;
}
@ -223,8 +240,10 @@ TimelineViewManager::queueEmoteMessage(const QString &msg)
mtx::events::msg::Emote emote;
emote.body = msg.trimmed().toStdString();
if (html != msg.trimmed().toHtmlEscaped())
if (html != msg.trimmed().toHtmlEscaped() && settings->isMarkdownEnabled()) {
emote.formatted_body = html.toStdString();
emote.format = "org.matrix.custom.html";
}
if (timeline_)
timeline_->sendMessage(emote);

View File

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

View File

@ -1,6 +1,6 @@
#include <QPainter>
#include <tweeny/tweeny.h>
#include <tweeny.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)