mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-10-30 07:53:33 +08:00
Compare commits
70 Commits
stable/202
...
nightly/20
| Author | SHA1 | Date | |
|---|---|---|---|
| c6f79f4132 | |||
| 6b9cb684ec | |||
| 1d0fa772e2 | |||
| 51c716d718 | |||
| 5e4556f786 | |||
| da667056fd | |||
| 9d00c4f4e3 | |||
| f5743da2d6 | |||
| 7152b51597 | |||
| 4a53397561 | |||
| d86a90207a | |||
| 7b298deee8 | |||
| 056cf14613 | |||
| 2e75dd8777 | |||
| 8bda8da414 | |||
| b7fb63ae40 | |||
| 31bd0392da | |||
| 59f3aa7c44 | |||
| 9aeb405644 | |||
| 9e1d8e3e56 | |||
| b65774add0 | |||
| c55486988f | |||
| 39833924af | |||
| a194e86d7a | |||
| 8cfd9bc3fc | |||
| bdec942d72 | |||
| 35d5595401 | |||
| 7330a87082 | |||
| 7243b10e81 | |||
| 964c8e0553 | |||
| 96c00ff019 | |||
| c8716d1113 | |||
| 630e5e9fe4 | |||
| f447327c02 | |||
| 650f98636b | |||
| b92cd902b9 | |||
| b99c2674b4 | |||
| 1524ba0177 | |||
| 5503769023 | |||
| 89354a07e1 | |||
| 69400bee2a | |||
| 0e07f9cee7 | |||
| d2eba1d91e | |||
| 78389d8c28 | |||
| e6d820850a | |||
| 0a7f9349a9 | |||
| 99254f8d02 | |||
| 010a2c4eea | |||
| 61163037d4 | |||
| 3577982a93 | |||
| 3ad0b92dcd | |||
| 91475c3a3f | |||
| 9379af23ec | |||
| 406a251c85 | |||
| 20e2852e44 | |||
| 3225f90ce8 | |||
| df3e76a1cf | |||
| c5e15d26a0 | |||
| 77e019b02b | |||
| 89bed2bf85 | |||
| 519871e458 | |||
| 0a842042b0 | |||
| 9aeb2377dc | |||
| 6ad5f4b850 | |||
| f5c63d24fb | |||
| 5cb34bd31c | |||
| e56a966de1 | |||
| acc0c97234 | |||
| 665af7c0c3 | |||
| fa51e042e5 |
@ -29,7 +29,8 @@ else()
|
||||
project(jami)
|
||||
endif()
|
||||
|
||||
include(${PROJECT_SOURCE_DIR}/extras/build/cmake/extra_tools.cmake)
|
||||
set(CMAKE_SCRIPTS_DIR ${PROJECT_SOURCE_DIR}/extras/build/cmake)
|
||||
include(${CMAKE_SCRIPTS_DIR}/extra_tools.cmake)
|
||||
|
||||
option(WITH_DAEMON_SUBMODULE "Build with daemon submodule" ON)
|
||||
option(JAMICORE_AS_SUBDIR "Build Jami-core as a subdir dependency" OFF)
|
||||
@ -117,6 +118,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
# src
|
||||
set(LIBCLIENT_SRC_DIR ${PROJECT_SOURCE_DIR}/src/libclient)
|
||||
set(APP_SRC_DIR ${PROJECT_SOURCE_DIR}/src/app)
|
||||
set(VERSION_INFO_DIR ${PROJECT_SOURCE_DIR}/src/version_info)
|
||||
# doc
|
||||
set(DOC_DIR ${PROJECT_SOURCE_DIR}/doc)
|
||||
# extras
|
||||
@ -210,6 +212,23 @@ include(FindPython3)
|
||||
find_package(Python3 3.6 REQUIRED COMPONENTS Interpreter)
|
||||
set(PYTHON_EXEC ${Python3_EXECUTABLE})
|
||||
|
||||
# Versioning and build ID generation
|
||||
set(VERSION_FILE ${CMAKE_CURRENT_BINARY_DIR}/version_info.cpp)
|
||||
# Touch the file to make sure it exists at configure time as
|
||||
# we add it to the target_sources below.
|
||||
file(TOUCH ${VERSION_FILE})
|
||||
add_custom_target(
|
||||
generate_version_info ALL
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DAPP_SOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||
-DAPP_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
|
||||
-DCORE_SOURCE_DIR=${DAEMON_DIR}
|
||||
-DCPP_INT_FILE=${VERSION_INFO_DIR}/version_info.cpp.in
|
||||
-P ${CMAKE_SCRIPTS_DIR}/generate_version_info.cmake
|
||||
)
|
||||
list(APPEND CLIENT_INCLUDE_DIRS ${VERSION_INFO_DIR})
|
||||
|
||||
# Resource auto-gen
|
||||
# QML and related code files
|
||||
# Check files in the app's src directory and force a reconfigure if it
|
||||
@ -247,6 +266,7 @@ set(QML_IMPORT_PATH ${QML_DIRS}
|
||||
add_definitions(-DQT_NO_KEYWORDS)
|
||||
|
||||
set(COMMON_SOURCES
|
||||
${VERSION_FILE}
|
||||
${APP_SRC_DIR}/bannedlistmodel.cpp
|
||||
${APP_SRC_DIR}/accountlistmodel.cpp
|
||||
${APP_SRC_DIR}/networkmanager.cpp
|
||||
@ -626,6 +646,9 @@ qt_add_executable(
|
||||
${QML_RESOURCES_QML}
|
||||
${SFPM_OBJECTS})
|
||||
|
||||
# Make sure we can find the generated version file
|
||||
add_dependencies(${PROJECT_NAME} generate_version_info)
|
||||
|
||||
foreach(MODULE ${QT_MODULES})
|
||||
list(APPEND QT_LIBS "Qt::${MODULE}")
|
||||
endforeach()
|
||||
@ -819,12 +842,20 @@ else()
|
||||
"-framework Security"
|
||||
compression
|
||||
resolv
|
||||
)
|
||||
)
|
||||
|
||||
set(APP_CONTAINER "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app/Contents")
|
||||
|
||||
# ringtones. Copy the entire directory to the app bundle.
|
||||
# daemon/ringtones -> Jami.app/Contents/Resources/ringtones
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${DAEMON_DIR}/ringtones
|
||||
${APP_CONTAINER}/Resources/ringtones
|
||||
)
|
||||
|
||||
# translations
|
||||
if(Qt${QT_VERSION_MAJOR}LinguistTools_FOUND)
|
||||
set(APP_CONTAINER
|
||||
"${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app/Contents")
|
||||
file(GLOB TS_FILES ${PROJECT_SOURCE_DIR}/translations/*.ts)
|
||||
|
||||
# Generate lproj folders.
|
||||
@ -852,26 +883,26 @@ else()
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${JAMI_VERSION}"
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION "${JAMI_BUILD}"
|
||||
MACOSX_BUNDLE_COPYRIGHT "${PROJ_COPYRIGHT}")
|
||||
if(APPSTORE)
|
||||
message(STATUS "app store version")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/resources/entitlements/appstore/Jami.entitlements")
|
||||
else()
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
SPARKLE_URL "${SPARKLE_URL}"
|
||||
SPARKLE_PUBLIC_KEY "${SPARKLE_PUBLIC_KEY}"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/resources/entitlements/Jami.entitlements"
|
||||
XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE)
|
||||
endif()
|
||||
if(DEPLOY)
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -DQML_SRC_DIR=${SRC_DIR}
|
||||
-DMAC_DEPLOY_QT_PATH=${CMAKE_PREFIX_PATH}/bin
|
||||
-DEXE_NAME="${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app"
|
||||
-DSPARKLE_PATH=${SPARKLE_FRAMEWORK}
|
||||
-DENABLE_SPARKLE=${ENABLE_SPARKLE}
|
||||
-P ${EXTRAS_DIR}/build/cmake/macos_qt_deploy.cmake)
|
||||
endif()
|
||||
if(APPSTORE)
|
||||
message(STATUS "app store version")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/resources/entitlements/appstore/Jami.entitlements")
|
||||
else()
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
SPARKLE_URL "${SPARKLE_URL}"
|
||||
SPARKLE_PUBLIC_KEY "${SPARKLE_PUBLIC_KEY}"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/resources/entitlements/Jami.entitlements"
|
||||
XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE)
|
||||
endif()
|
||||
if(DEPLOY)
|
||||
execute_process(COMMAND
|
||||
"${CMAKE_PREFIX_PATH}/bin/macdeployqt"
|
||||
"${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app"
|
||||
-qmldir=${QML_SRC_DIR})
|
||||
if(${ENABLE_SPARKLE} MATCHES true)
|
||||
file(COPY ${SPARKLE_FRAMEWORK} DESTINATION ${EXE_NAME}/Contents/Frameworks/)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${CLIENT_INCLUDE_DIRS})
|
||||
|
||||
@ -14,7 +14,7 @@ So, you will need to get Qt 6.6 first. For this, there is 3 methods:
|
||||
### Qt from our repo (recommended)
|
||||
|
||||
If your distribution is supported, we provide a Qt package (libqt-jami) on our repo.
|
||||
The files will be installed in `/usr/lib/libqt-jami`.
|
||||
The files will be installed to `/usr/lib/libqt-jami` on Debian-like distributions. For RPM based distributions the files will be installed to `/usr/lib64/qt-jami`.
|
||||
|
||||
#### Install libqt-jami, Ubuntu based
|
||||
|
||||
|
||||
6
build.py
6
build.py
@ -100,7 +100,7 @@ ZYPPER_DEPENDENCIES = [
|
||||
'speexdsp-devel', 'speex-devel', 'libdbus-c++-devel', 'jsoncpp-devel', 'yaml-cpp-devel',
|
||||
'yasm', 'libuuid-devel', 'libnettle-devel', 'libopus-devel', 'libexpat-devel',
|
||||
'libgnutls-devel', 'msgpack-c-devel', 'msgpack-cxx-devel', 'libavcodec-devel', 'libavdevice-devel', 'pcre-devel',
|
||||
'alsa-devel', 'libpulse-devel', 'libudev-devel', 'libva-devel', 'libvdpau-devel',
|
||||
'alsa-devel', 'libpulse-devel', 'libudev-devel', 'libva-devel', 'libvdpau-devel', 'pipewire-devel',
|
||||
'libopenssl-devel', 'libavutil-devel',
|
||||
]
|
||||
|
||||
@ -130,7 +130,7 @@ DNF_DEPENDENCIES = [
|
||||
'gcc-c++', 'which', 'alsa-lib-devel', 'systemd-devel', 'libuuid-devel',
|
||||
'uuid-devel', 'gnutls-devel', 'nettle-devel', 'opus-devel', 'speexdsp-devel',
|
||||
'yaml-cpp-devel', 'swig', 'jsoncpp-devel',
|
||||
'patch', 'libva-devel', 'openssl-devel', 'libvdpau-devel', 'msgpack-devel',
|
||||
'patch', 'libva-devel', 'openssl-devel', 'libvdpau-devel', 'pipewire-devel', 'msgpack-devel',
|
||||
'sqlite-devel', 'openssl-static', 'pandoc', 'nasm',
|
||||
'bzip2'
|
||||
]
|
||||
@ -154,7 +154,7 @@ APT_DEPENDENCIES = [
|
||||
'libopus-dev', 'libpcre3-dev', 'libpulse-dev', 'libssl-dev',
|
||||
'libspeex-dev', 'libspeexdsp-dev', 'libswscale-dev', 'libtool',
|
||||
'libudev-dev', 'libyaml-cpp-dev', 'sip-tester', 'swig',
|
||||
'uuid-dev', 'yasm', 'libjsoncpp-dev', 'libva-dev', 'libvdpau-dev', 'libmsgpack-dev',
|
||||
'uuid-dev', 'yasm', 'libjsoncpp-dev', 'libva-dev', 'libvdpau-dev', 'libpipewire-0.3-dev', 'libmsgpack-dev',
|
||||
'pandoc', 'nasm', 'dpkg-dev', 'libsystemd-dev'
|
||||
]
|
||||
|
||||
|
||||
2
daemon
2
daemon
Submodule daemon updated: fd2f281544...f379421e8a
34
extras/build/cmake/generate_version_info.cmake
Normal file
34
extras/build/cmake/generate_version_info.cmake
Normal file
@ -0,0 +1,34 @@
|
||||
find_package(Git QUIET REQUIRED)
|
||||
|
||||
message(STATUS "Generating version information...")
|
||||
|
||||
function(configure_version_string SOURCE_DIR VERSION_STRING_OUT)
|
||||
# Get short git SHA
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" rev-parse --short HEAD
|
||||
WORKING_DIRECTORY "${SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE _GIT_SHA
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Output the VERSION_STRING_OUT to the caller
|
||||
set(${VERSION_STRING_OUT} "${_GIT_SHA}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# These need to be set to the parent scripts values for configure_file to work,
|
||||
# as it prepends CMAKE_CURRENT_SOURCE_DIR to the <input> and CMAKE_CURRENT_BINARY_DIR
|
||||
# to <output>.
|
||||
set(CMAKE_CURRENT_SOURCE_DIR ${APP_SOURCE_DIR})
|
||||
set(CMAKE_CURRENT_BINARY_DIR ${APP_BINARY_DIR})
|
||||
|
||||
# Generate the version string for the application and core
|
||||
configure_version_string(${APP_SOURCE_DIR} APP_VERSION_STRING)
|
||||
configure_version_string(${CORE_SOURCE_DIR} CORE_VERSION_STRING)
|
||||
|
||||
# Get output file names with the .in extension removed
|
||||
get_filename_component(VERSION_CPP_FILENAME ${CPP_INT_FILE} NAME_WE)
|
||||
set(VERSION_CPP_FILE "${CMAKE_CURRENT_BINARY_DIR}/${VERSION_CPP_FILENAME}.cpp")
|
||||
|
||||
message(STATUS "infiles: ${CPP_INT_FILE}")
|
||||
message(STATUS "outfiles: ${VERSION_CPP_FILE}")
|
||||
configure_file(${CPP_INT_FILE} ${VERSION_CPP_FILE})
|
||||
@ -1,7 +0,0 @@
|
||||
message("Qt deploying in dir " ${QML_SRC_DIR})
|
||||
execute_process(COMMAND "${MAC_DEPLOY_QT_PATH}/macdeployqt"
|
||||
${EXE_NAME}
|
||||
-qmldir=${QML_SRC_DIR})
|
||||
if(${ENABLE_SPARKLE} MATCHES true)
|
||||
file(COPY ${SPARKLE_PATH} DESTINATION ${EXE_NAME}/Contents/Frameworks/)
|
||||
endif()
|
||||
@ -66,6 +66,7 @@ RUN apt-get install -y -o Acquire::Retries=10 \
|
||||
libvdpau-dev \
|
||||
libssl-dev
|
||||
RUN apt-get install -y pandoc \
|
||||
libcppunit-dev \
|
||||
googletest \
|
||||
libgtest-dev \
|
||||
wget
|
||||
|
||||
@ -49,7 +49,7 @@ QT_MAJOR := 6
|
||||
QT_MINOR := 6
|
||||
QT_PATCH := 1
|
||||
QT_TARBALL_CHECKSUM := dd3668f65645fe270bc615d748bd4dc048bd17b9dc297025106e6ecc419ab95d
|
||||
DEBIAN_QT_VERSION := $(QT_MAJOR).$(QT_MINOR).$(QT_PATCH)-0
|
||||
DEBIAN_QT_VERSION := $(QT_MAJOR).$(QT_MINOR).$(QT_PATCH)-1
|
||||
DEBIAN_QT_DSC_FILENAME := libqt-jami_$(DEBIAN_QT_VERSION).dsc
|
||||
QT_JAMI_PREFIX := /usr/lib/libqt-jami
|
||||
|
||||
@ -166,13 +166,14 @@ DISTRIBUTIONS := \
|
||||
debian_unstable \
|
||||
ubuntu_20.04 \
|
||||
ubuntu_22.04 \
|
||||
ubuntu_23.04 \
|
||||
ubuntu_23.10 \
|
||||
ubuntu_24.04 \
|
||||
ubuntu_24.10 \
|
||||
fedora_37 \
|
||||
fedora_38 \
|
||||
fedora_39 \
|
||||
fedora_40 \
|
||||
fedora_41 \
|
||||
alma_9 \
|
||||
opensuse-leap_15.4 \
|
||||
opensuse-leap_15.5 \
|
||||
|
||||
@ -27,9 +27,7 @@ RUN /opt/prebuild-package-debian.sh qt-deps
|
||||
COPY extras/packaging/gnu-linux/rules/debian/control /tmp/builddeps/debian/control
|
||||
RUN /opt/prebuild-package-debian.sh jami-deps
|
||||
|
||||
# Install CMake 3.21 for Qt 6
|
||||
ADD extras/packaging/gnu-linux/scripts/install-cmake.sh /opt/install-cmake.sh
|
||||
RUN /opt/install-cmake.sh
|
||||
RUN apt-get remove -y libre2-dev libre2-11
|
||||
|
||||
ADD extras/packaging/gnu-linux/scripts/build-package-debian.sh /opt/build-package-debian.sh
|
||||
CMD ["/opt/build-package-debian.sh"]
|
||||
|
||||
@ -27,9 +27,7 @@ RUN /opt/prebuild-package-debian.sh qt-deps
|
||||
COPY extras/packaging/gnu-linux/rules/debian/control /tmp/builddeps/debian/control
|
||||
RUN /opt/prebuild-package-debian.sh jami-deps
|
||||
|
||||
# Install CMake 3.21 for Qt 6
|
||||
ADD extras/packaging/gnu-linux/scripts/install-cmake.sh /opt/install-cmake.sh
|
||||
RUN /opt/install-cmake.sh
|
||||
RUN apt-get remove -y libre2-dev libre2-11
|
||||
|
||||
ADD extras/packaging/gnu-linux/scripts/build-package-debian.sh /opt/build-package-debian.sh
|
||||
CMD ["/opt/build-package-debian.sh"]
|
||||
|
||||
103
extras/packaging/gnu-linux/docker/Dockerfile_fedora_41
Normal file
103
extras/packaging/gnu-linux/docker/Dockerfile_fedora_41
Normal file
@ -0,0 +1,103 @@
|
||||
FROM fedora:41
|
||||
|
||||
RUN dnf clean all
|
||||
RUN dnf update -y
|
||||
|
||||
RUN dnf install -y dnf-command\(builddep\) rpmdevtools && \
|
||||
dnf install -y mock
|
||||
|
||||
RUN dnf group install -y x-software-development
|
||||
|
||||
RUN dnf install -y \
|
||||
git \
|
||||
rpm-build \
|
||||
tar \
|
||||
make \
|
||||
autoconf \
|
||||
automake \
|
||||
nasm \
|
||||
speexdsp-devel \
|
||||
pulseaudio-libs-devel \
|
||||
libcanberra-devel \
|
||||
libcurl-devel \
|
||||
libtool \
|
||||
mesa-libgbm-devel \
|
||||
mesa-dri-drivers \
|
||||
dbus-devel \
|
||||
expat-devel \
|
||||
pcre-devel \
|
||||
yaml-cpp-devel \
|
||||
libXext-devel \
|
||||
libXfixes-devel \
|
||||
yasm \
|
||||
speex-devel \
|
||||
gsm-devel \
|
||||
chrpath \
|
||||
check \
|
||||
astyle \
|
||||
uuid-c++-devel \
|
||||
gettext-devel \
|
||||
gcc-c++ \
|
||||
which \
|
||||
alsa-lib-devel \
|
||||
systemd-devel \
|
||||
libuuid-devel \
|
||||
uuid-devel \
|
||||
gnutls-devel \
|
||||
nettle-devel \
|
||||
opus-devel \
|
||||
patch \
|
||||
jsoncpp-devel \
|
||||
libnatpmp-devel \
|
||||
webkitgtk4-devel \
|
||||
cryptopp-devel \
|
||||
libva-devel \
|
||||
libvdpau-devel \
|
||||
msgpack-devel \
|
||||
NetworkManager-libnm-devel \
|
||||
openssl-devel \
|
||||
clutter-devel \
|
||||
clutter-gtk-devel \
|
||||
libappindicator-gtk3-devel \
|
||||
libnotify-devel \
|
||||
libupnp-devel \
|
||||
qrencode-devel \
|
||||
libargon2-devel \
|
||||
libsndfile-devel \
|
||||
libdrm \
|
||||
gperf \
|
||||
bison \
|
||||
clang18-devel \
|
||||
llvm18-devel \
|
||||
nodejs \
|
||||
flex \
|
||||
gstreamer1 gstreamer1-devel \
|
||||
gstreamer1-plugins-base-devel \
|
||||
gstreamer1-plugins-good \
|
||||
gstreamer1-plugins-bad-free-devel \
|
||||
nss-devel \
|
||||
libxcb* \
|
||||
libxkb* \
|
||||
libX11-devel \
|
||||
vulkan-devel \
|
||||
libXrender-devel \
|
||||
xcb-util-* \
|
||||
xz \
|
||||
xkeyboard-config \
|
||||
libnotify \
|
||||
wget \
|
||||
libstdc++-static \
|
||||
sqlite-devel \
|
||||
perl-generators \
|
||||
perl-English \
|
||||
libxshmfence-devel \
|
||||
ninja-build \
|
||||
cmake \
|
||||
fmt-devel \
|
||||
python3.10 \
|
||||
cups-devel \
|
||||
pipewire-devel
|
||||
|
||||
ADD extras/packaging/gnu-linux/scripts/build-package-rpm.sh /opt/build-package-rpm.sh
|
||||
|
||||
CMD ["/opt/build-package-rpm.sh"]
|
||||
@ -1,6 +1,6 @@
|
||||
FROM opensuse/leap:15.5
|
||||
|
||||
RUN zypper refresh
|
||||
RUN zypper --gpg-auto-import-keys refresh
|
||||
|
||||
RUN zypper --non-interactive install -y \
|
||||
dnf \
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM ubuntu:23.04
|
||||
FROM ubuntu:24.10
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
@ -18,5 +18,12 @@ RUN /opt/prebuild-package-debian.sh qt-deps
|
||||
COPY extras/packaging/gnu-linux/rules/debian/control /tmp/builddeps/debian/control
|
||||
RUN /opt/prebuild-package-debian.sh jami-deps
|
||||
|
||||
# Remove the libre2-dev package in order to force Qt to build using the bundled
|
||||
# version of the RE2 library. This is necessary because the system version of the
|
||||
# library on Ubuntu 24.10 (libre2-11) is not compatible with the one used in
|
||||
# Qt 6.6.1 due to an API change:
|
||||
# https://codereview.qt-project.org/c/qt/qtwebengine/+/516094
|
||||
RUN apt-get remove -y libre2-dev libre2-11
|
||||
|
||||
ADD extras/packaging/gnu-linux/scripts/build-package-debian.sh /opt/build-package-debian.sh
|
||||
CMD ["/opt/build-package-debian.sh"]
|
||||
@ -1,10 +1,18 @@
|
||||
From deeacfdb5a6d1d300d4ba991df76aa12e5dbaa42 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
|
||||
<sebastien.blin@savoirfairelinux.com>
|
||||
Date: Tue, 16 Apr 2024 09:54:32 -0400
|
||||
Subject: [PATCH] fix imp->importlib
|
||||
From 24fb774485f719df1e84dda31605d3f69202d69f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Fran=C3=A7ois-Simon=20Fauteux-Chapleau?=
|
||||
<francois-simon.fauteux-chapleau@savoirfairelinux.com>
|
||||
Date: Thu, 8 Aug 2024 14:59:17 -0400
|
||||
Subject: [PATCH] qtwebengine: enable building with Python 3.12
|
||||
|
||||
Replace the deprecated imp module by importlib:
|
||||
https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/524014
|
||||
https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/534568
|
||||
|
||||
Update six to fix html5lib import failure:
|
||||
https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/535605
|
||||
https://issues.chromium.org/issues/40286977
|
||||
---
|
||||
.../protobufs/binary_proto_generator.py | 8 ++++++--
|
||||
.../mojo/public/tools/mojom/mojom/fileutil.py | 1 -
|
||||
.../tools/mojom/mojom/fileutil_unittest.py | 5 +----
|
||||
.../mojom/mojom/generate/generator_unittest.py | 7 ++-----
|
||||
@ -14,11 +22,37 @@ Subject: [PATCH] fix imp->importlib
|
||||
.../mojo/public/tools/mojom/mojom/parse/lexer.py | 1 -
|
||||
.../tools/mojom/mojom/parse/lexer_unittest.py | 7 ++-----
|
||||
.../tools/mojom/mojom/parse/parser_unittest.py | 5 -----
|
||||
.../3rdparty/chromium/third_party/six/src/six.py | 16 ++++++++++++++++
|
||||
10 files changed, 23 insertions(+), 37 deletions(-)
|
||||
.../third_party/catapult/third_party/six/six.py | 16 ++++++++++++++++
|
||||
11 files changed, 29 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py b/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py
|
||||
index 2a1802dccdc..8b9de65ed0b 100755
|
||||
--- a/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py
|
||||
@@ -9,7 +9,7 @@
|
||||
"""
|
||||
from __future__ import print_function
|
||||
import abc
|
||||
-import imp
|
||||
+from importlib import util as imp_util
|
||||
import optparse
|
||||
import os
|
||||
import re
|
||||
@@ -68,7 +68,11 @@ class GoogleProtobufModuleImporter:
|
||||
raise ImportError(fullname)
|
||||
|
||||
filepath = self._fullname_to_filepath(fullname)
|
||||
- return imp.load_source(fullname, filepath)
|
||||
+ spec = imp_util.spec_from_file_location(fullname, filepath)
|
||||
+ loaded = imp_util.module_from_spec(spec)
|
||||
+ spec.loader.exec_module(loaded)
|
||||
+
|
||||
+ return loaded
|
||||
|
||||
class BinaryProtoGenerator:
|
||||
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py
|
||||
index 29daec367c..124f12c134 100644
|
||||
index 29daec367c5..124f12c134b 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py
|
||||
@@ -3,7 +3,6 @@
|
||||
@ -30,7 +64,7 @@ index 29daec367c..124f12c134 100644
|
||||
import sys
|
||||
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py
|
||||
index 48eaf4eca9..c93d22898d 100644
|
||||
index 48eaf4eca94..c93d22898d2 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py
|
||||
@@ -2,19 +2,16 @@
|
||||
@ -55,7 +89,7 @@ index 48eaf4eca9..c93d22898d 100644
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
try:
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py
|
||||
index 76cda3981f..7143e07c4d 100644
|
||||
index 76cda3981f3..7143e07c4d7 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py
|
||||
@@ -2,12 +2,11 @@
|
||||
@ -94,7 +128,7 @@ index 76cda3981f..7143e07c4d 100644
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py
|
||||
index 4259374513..558e71e119 100644
|
||||
index 4259374513f..558e71e1193 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py
|
||||
@@ -2,16 +2,12 @@
|
||||
@ -115,7 +149,7 @@ index 4259374513..558e71e119 100644
|
||||
"""Tests |parser.Parse()|."""
|
||||
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py
|
||||
index c36376712e..b289f7b11f 100644
|
||||
index c36376712e7..b289f7b11f6 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py
|
||||
@@ -2,14 +2,10 @@
|
||||
@ -148,7 +182,7 @@ index c36376712e..b289f7b11f 100644
|
||||
"""Tests various AST classes."""
|
||||
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py
|
||||
index 5fc582025e..2fa5d2be6a 100644
|
||||
index 5fc582025ee..2fa5d2be6ab 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py
|
||||
@@ -2,12 +2,11 @@
|
||||
@ -192,7 +226,7 @@ index 5fc582025e..2fa5d2be6a 100644
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py
|
||||
index 73ca15df94..1083a1af7b 100644
|
||||
index 73ca15df94c..1083a1af7bb 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py
|
||||
@@ -2,7 +2,6 @@
|
||||
@ -204,7 +238,7 @@ index 73ca15df94..1083a1af7b 100644
|
||||
import sys
|
||||
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
|
||||
index ce376da66e..bc9f835431 100644
|
||||
index ce376da66e0..bc9f8354316 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
|
||||
@@ -2,12 +2,11 @@
|
||||
@ -241,7 +275,7 @@ index ce376da66e..bc9f835431 100644
|
||||
# we'll do it anyway. (I'm pretty sure ply's lexer never cares about comparing
|
||||
# for object identity.)
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py
|
||||
index 0513343ec7..0a26307b1a 100644
|
||||
index 0513343ec7e..0a26307b1a3 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py
|
||||
@@ -2,16 +2,12 @@
|
||||
@ -268,10 +302,10 @@ index 0513343ec7..0a26307b1a 100644
|
||||
-
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/six/src/six.py b/qtwebengine/src/3rdparty/chromium/third_party/six/src/six.py
|
||||
index 5fe9f8e141..96b06f8ce7 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/third_party/six/src/six.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/third_party/six/src/six.py
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/catapult/third_party/six/six.py b/qtwebengine/src/3rdparty/chromium/third_party/catapult/third_party/six/six.py
|
||||
index 83f69783d1a..5e7f0ce4437 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/third_party/catapult/third_party/six/six.py
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/third_party/catapult/third_party/six/six.py
|
||||
@@ -71,6 +71,11 @@ else:
|
||||
MAXSIZE = int((1 << 63) - 1)
|
||||
del X
|
||||
@ -310,5 +344,5 @@ index 5fe9f8e141..96b06f8ce7 100644
|
||||
|
||||
|
||||
--
|
||||
2.43.0
|
||||
2.34.1
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
From cf208d11dc8a9a02160a57283596ec8bab964a09 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
Date: Mon, 27 May 2024 16:01:21 -0400
|
||||
Subject: [PATCH] qtwayland: downgrade wl-seat to avoid high-resolution
|
||||
scrolling events
|
||||
|
||||
---
|
||||
qtwayland/src/client/qwaylandinputdevice.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/qtwayland/src/client/qwaylandinputdevice.cpp b/qtwayland/src/client/qwaylandinputdevice.cpp
|
||||
index a4f8757e3c..ad0aa7941c 100644
|
||||
--- a/qtwayland/src/client/qwaylandinputdevice.cpp
|
||||
+++ b/qtwayland/src/client/qwaylandinputdevice.cpp
|
||||
@@ -383,7 +383,7 @@ QWaylandInputDevice::Touch::~Touch()
|
||||
}
|
||||
|
||||
QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id)
|
||||
- : QtWayland::wl_seat(display->wl_registry(), id, qMin(version, 9))
|
||||
+ : QtWayland::wl_seat(display->wl_registry(), id, qMin(version, 7))
|
||||
, mQDisplay(display)
|
||||
, mDisplay(display->wl_display())
|
||||
{
|
||||
--
|
||||
2.45.0
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
From 420b3e5ac2e91b7a99488ac34577e2798a84a68c Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Fran=C3=A7ois-Simon=20Fauteux-Chapleau?=
|
||||
<francois-simon.fauteux-chapleau@savoirfairelinux.com>
|
||||
Date: Tue, 6 Aug 2024 17:35:56 -0400
|
||||
Subject: [PATCH] qtbase: fix CMake error
|
||||
|
||||
For more information, see:
|
||||
https://github.com/qt/qtbase/commit/3411f2984a5325a35e3bed1f961e5973d8a565b9
|
||||
---
|
||||
qtbase/configure.cmake | 1 +
|
||||
qtbase/src/corelib/CMakeLists.txt | 1 -
|
||||
2 files changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/qtbase/configure.cmake b/qtbase/configure.cmake
|
||||
index 43de2aa026..37a82dcdb6 100644
|
||||
--- a/qtbase/configure.cmake
|
||||
+++ b/qtbase/configure.cmake
|
||||
@@ -18,6 +18,7 @@ if(TARGET ZLIB::ZLIB)
|
||||
set_property(TARGET ZLIB::ZLIB PROPERTY IMPORTED_GLOBAL TRUE)
|
||||
endif()
|
||||
|
||||
+qt_find_package(Threads PROVIDED_TARGETS Threads::Threads)
|
||||
qt_find_package(WrapOpenSSLHeaders PROVIDED_TARGETS WrapOpenSSLHeaders::WrapOpenSSLHeaders MODULE_NAME core)
|
||||
# openssl_headers
|
||||
# OPENSSL_VERSION_MAJOR is not defined for OpenSSL 1.1.1
|
||||
diff --git a/qtbase/src/corelib/CMakeLists.txt b/qtbase/src/corelib/CMakeLists.txt
|
||||
index 31b81734e8..b62e2f763b 100644
|
||||
--- a/qtbase/src/corelib/CMakeLists.txt
|
||||
+++ b/qtbase/src/corelib/CMakeLists.txt
|
||||
@@ -1,7 +1,6 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
-qt_find_package(Threads PROVIDED_TARGETS Threads::Threads)
|
||||
qt_find_package(WrapPCRE2 PROVIDED_TARGETS WrapPCRE2::WrapPCRE2)
|
||||
qt_find_package(WrapZLIB PROVIDED_TARGETS WrapZLIB::WrapZLIB)
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
From 4c7360faeb0fb7f1dfd995619fb8c596b4e15606 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Fran=C3=A7ois-Simon=20Fauteux-Chapleau?=
|
||||
<francois-simon.fauteux-chapleau@savoirfairelinux.com>
|
||||
Date: Thu, 8 Aug 2024 10:29:43 -0400
|
||||
Subject: [PATCH] qtwebengine: add missing chromium dependencies
|
||||
|
||||
For more information, see:
|
||||
https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/555586
|
||||
---
|
||||
chromium/content/public/browser/BUILD.gn | 1 +
|
||||
chromium/extensions/browser/api/declarative_net_request/BUILD.gn | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/content/public/browser/BUILD.gn b/qtwebengine/src/3rdparty/chromium/content/public/browser/BUILD.gn
|
||||
index b25bf5764e7..dfbfb2ec77b 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/content/public/browser/BUILD.gn
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/content/public/browser/BUILD.gn
|
||||
@@ -515,6 +515,7 @@ jumbo_source_set("browser_sources") {
|
||||
"//cc",
|
||||
"//components/services/storage/public/cpp",
|
||||
"//components/viz/host",
|
||||
+ "//components/spellcheck:buildflags",
|
||||
"//content/browser", # Must not be public_deps!
|
||||
"//device/fido",
|
||||
"//gpu",
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/extensions/browser/api/declarative_net_request/BUILD.gn b/qtwebengine/src/3rdparty/chromium/extensions/browser/api/declarative_net_request/BUILD.gn
|
||||
index 1fc492f5a0c..13a266e22f1 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/extensions/browser/api/declarative_net_request/BUILD.gn
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/extensions/browser/api/declarative_net_request/BUILD.gn
|
||||
@@ -23,6 +23,7 @@ source_set("declarative_net_request") {
|
||||
"//extensions/common",
|
||||
"//extensions/common/api",
|
||||
"//services/preferences/public/cpp",
|
||||
+ "//components/web_cache/browser",
|
||||
]
|
||||
|
||||
public_deps = [ "//extensions/browser:browser_sources" ]
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
From ab6d5bebaf68a9f4d00440b2adbaffe0e5b2ae6c Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Fran=C3=A7ois-Simon=20Fauteux-Chapleau?=
|
||||
<francois-simon.fauteux-chapleau@savoirfairelinux.com>
|
||||
Date: Thu, 8 Aug 2024 10:55:08 -0400
|
||||
Subject: [PATCH] qtwebengine: fix libxml2 build error
|
||||
|
||||
Version 2.12 of libxml2 introduced a change that broke chromium's build,
|
||||
see: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/523633
|
||||
---
|
||||
.../third_party/blink/renderer/core/xml/xslt_processor.h | 5 +++++
|
||||
.../blink/renderer/core/xml/xslt_processor_libxslt.cc | 4 ++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/blink/renderer/core/xml/xslt_processor.h b/qtwebengine/src/3rdparty/chromium/third_party/blink/renderer/core/xml/xslt_processor.h
|
||||
index d53835e9675..72536e4fd7d 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/third_party/blink/renderer/core/xml/xslt_processor.h
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/third_party/blink/renderer/core/xml/xslt_processor.h
|
||||
@@ -77,7 +77,12 @@ class XSLTProcessor final : public ScriptWrappable {
|
||||
|
||||
void reset();
|
||||
|
||||
+#if LIBXML_VERSION >= 21200
|
||||
+ static void ParseErrorFunc(void* user_data, const xmlError*);
|
||||
+#else
|
||||
static void ParseErrorFunc(void* user_data, xmlError*);
|
||||
+#endif
|
||||
+
|
||||
static void GenericErrorFunc(void* user_data, const char* msg, ...);
|
||||
|
||||
// Only for libXSLT callbacks
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc b/qtwebengine/src/3rdparty/chromium/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
|
||||
index 133e0b3355d..e8e6a09f485 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
|
||||
@@ -66,7 +66,11 @@ void XSLTProcessor::GenericErrorFunc(void*, const char*, ...) {
|
||||
// It would be nice to do something with this error message.
|
||||
}
|
||||
|
||||
+#if LIBXML_VERSION >= 21200
|
||||
+void XSLTProcessor::ParseErrorFunc(void* user_data, const xmlError* error) {
|
||||
+#else
|
||||
void XSLTProcessor::ParseErrorFunc(void* user_data, xmlError* error) {
|
||||
+#endif
|
||||
FrameConsole* console = static_cast<FrameConsole*>(user_data);
|
||||
if (!console)
|
||||
return;
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
From 6e0848a1c51c6494e3b7410c5fe38941d48fcb36 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Fran=C3=A7ois-Simon=20Fauteux-Chapleau?=
|
||||
<francois-simon.fauteux-chapleau@savoirfairelinux.com>
|
||||
Date: Wed, 16 Oct 2024 22:32:12 -0400
|
||||
Subject: [PATCH] qtwebengine: fix v8 build error
|
||||
|
||||
In file included from ../../../3rdparty/chromium/v8/src/heap/cppgc/sweeper.h:14,
|
||||
from ./../../../3rdparty/chromium/v8/src/heap/cppgc/sweeper.cc:5,
|
||||
from gen/v8/cppgc_base_jumbo_7.cc:5:
|
||||
../../../3rdparty/chromium/v8/src/heap/cppgc/stats-collector.h: In member function 'void cppgc::internal::StatsCollector::ForAllAllocationObservers(Callback)':
|
||||
../../../3rdparty/chromium/v8/src/heap/cppgc/stats-collector.h:401:48: error: cannot convert 'std::vector<cppgc::internal::StatsCollector::AllocationObserver*>::iterator' to 'const char*'
|
||||
401 | std::remove(allocation_observers_.begin(), allocation_observers_.end(),
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
|
||||
| |
|
||||
| std::vector<cppgc::internal::StatsCollector::AllocationObserver*>::iterator
|
||||
---
|
||||
.../src/3rdparty/chromium/v8/src/heap/cppgc/stats-collector.h | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/v8/src/heap/cppgc/stats-collector.h b/qtwebengine/src/3rdparty/chromium/v8/src/heap/cppgc/stats-collector.h
|
||||
index 2cf728489d..d8414ae3c6 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/v8/src/heap/cppgc/stats-collector.h
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/v8/src/heap/cppgc/stats-collector.h
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
+#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
--
|
||||
2.47.0
|
||||
|
||||
@ -1,2 +1,7 @@
|
||||
0001-replace_imp_by_importlib.patch
|
||||
0002-fix-binary-tokenizer.patch
|
||||
0001-qtwebengine-enable-building-with-Python-3.12.patch
|
||||
0002-fix-binary-tokenizer.patch
|
||||
0003-qtwayland-downgrade-wl-seat-to-avoid-high-resolution.patch
|
||||
0004-qtbase-fix-CMake-error.patch
|
||||
0005-qtwebengine-add-missing-chromium-dependencies.patch
|
||||
0006-qtwebengine-fix-libxml2-build-error.patch
|
||||
0007-qtwebengine-fix-v8-build-error.patch
|
||||
@ -22,7 +22,7 @@ Build-Depends: debhelper (>= 9),
|
||||
libpulse-dev,
|
||||
libasound2-dev,
|
||||
libexpat1-dev,
|
||||
libpcre3-dev,
|
||||
libpcre3-dev | libpcre2-dev,
|
||||
libyaml-cpp-dev,
|
||||
libboost-dev,
|
||||
libxext-dev,
|
||||
|
||||
@ -99,12 +99,12 @@ if [ -f /etc/os-release ]; then
|
||||
ENDTAG="ubuntu_20.04"
|
||||
elif [ "${UBUNTU_CODENAME}" = "jammy" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_22.04" ]; then
|
||||
ENDTAG="ubuntu_22.04"
|
||||
elif [ "${UBUNTU_CODENAME}" = "lunar" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_23.04" ]; then
|
||||
ENDTAG="ubuntu_23.04"
|
||||
elif [ "${UBUNTU_CODENAME}" = "mantic" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_23.10" ]; then
|
||||
ENDTAG="ubuntu_23.10"
|
||||
elif [ "${UBUNTU_CODENAME}" = "noble" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_24.04" ]; then
|
||||
ENDTAG="ubuntu_24.04"
|
||||
elif [ "${UBUNTU_CODENAME}" = "oracular" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_24.10" ]; then
|
||||
ENDTAG="ubuntu_24.10"
|
||||
elif [ "${ID}" = "debian" ] && \
|
||||
[ "$(command -v lsb_release)" ] && \
|
||||
[ "$(lsb_release -rs)" = "testing" ]; then
|
||||
|
||||
@ -30,6 +30,7 @@ Vendor: Savoir-faire Linux Inc.
|
||||
URL: https://jami.net/
|
||||
Source: jami-libqt-%{version}.tar.xz
|
||||
Patch0: 0001-fix-gcc14.patch
|
||||
Patch1: 0002-qtwebengine-add-missing-chromium-dependencies.patch
|
||||
|
||||
%global gst 0.10
|
||||
%if 0%{?fedora} || 0%{?rhel} > 7
|
||||
@ -65,7 +66,8 @@ This package contains Qt libraries for Jami.
|
||||
|
||||
%prep
|
||||
%setup -n qt-everywhere-src-%{version}
|
||||
%patch0 -p1
|
||||
%patch -P 0 -p1
|
||||
%patch -P 1 -p1
|
||||
|
||||
%build
|
||||
echo "Building Qt using %{job_count} parallel jobs"
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
From 04778c7f54c8a1a0e7fced75c5ef39ced82cece1 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Fran=C3=A7ois-Simon=20Fauteux-Chapleau?=
|
||||
<francois-simon.fauteux-chapleau@savoirfairelinux.com>
|
||||
Date: Sat, 12 Oct 2024 16:21:35 -0400
|
||||
Subject: [PATCH] qtwebengine: add missing chromium dependencies
|
||||
|
||||
For more information, see:
|
||||
https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/555586
|
||||
---
|
||||
chromium/content/public/browser/BUILD.gn | 1 +
|
||||
chromium/extensions/browser/api/declarative_net_request/BUILD.gn | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/content/public/browser/BUILD.gn b/qtwebengine/src/3rdparty/chromium/content/public/browser/BUILD.gn
|
||||
index b25bf5764e7..dfbfb2ec77b 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/content/public/browser/BUILD.gn
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/content/public/browser/BUILD.gn
|
||||
@@ -515,6 +515,7 @@ jumbo_source_set("browser_sources") {
|
||||
"//cc",
|
||||
"//components/services/storage/public/cpp",
|
||||
"//components/viz/host",
|
||||
+ "//components/spellcheck:buildflags",
|
||||
"//content/browser", # Must not be public_deps!
|
||||
"//device/fido",
|
||||
"//gpu",
|
||||
diff --git a/qtwebengine/src/3rdparty/chromium/extensions/browser/api/declarative_net_request/BUILD.gn b/qtwebengine/src/3rdparty/chromium/extensions/browser/api/declarative_net_request/BUILD.gn
|
||||
index 1fc492f5a0c..13a266e22f1 100644
|
||||
--- a/qtwebengine/src/3rdparty/chromium/extensions/browser/api/declarative_net_request/BUILD.gn
|
||||
+++ b/qtwebengine/src/3rdparty/chromium/extensions/browser/api/declarative_net_request/BUILD.gn
|
||||
@@ -23,6 +23,7 @@ source_set("declarative_net_request") {
|
||||
"//extensions/common",
|
||||
"//extensions/common/api",
|
||||
"//services/preferences/public/cpp",
|
||||
+ "//components/web_cache/browser",
|
||||
]
|
||||
|
||||
public_deps = [ "//extensions/browser:browser_sources" ]
|
||||
--
|
||||
2.47.0
|
||||
|
||||
@ -172,7 +172,7 @@ package-repositories:
|
||||
components: [main]
|
||||
suites: [jami]
|
||||
key-id: A295D773307D25A33AE72F2F64CD5FA175348F84
|
||||
url: https://dl.jami.net/nightly/ubuntu_20.04/
|
||||
url: https://dl.jami.net/internal/ubuntu_20.04/
|
||||
|
||||
parts:
|
||||
desktop-launch:
|
||||
@ -325,6 +325,12 @@ parts:
|
||||
- libgnutls28-dev # TLS
|
||||
- gnutls-bin
|
||||
- libssl-dev
|
||||
- git # PipeWire build dependencies
|
||||
- libasound2-dev #
|
||||
- libdbus-1-dev # These packages are needed by the
|
||||
- libglib2.0-dev # install-pipewire-from-source.sh
|
||||
- ninja-build # script in order to build PipeWire
|
||||
- pkg-config # from source.
|
||||
stage-packages:
|
||||
- libgnutls30
|
||||
- libavutil56
|
||||
|
||||
@ -114,6 +114,8 @@ if [ ! -f "${RPM_PATH}" ]; then
|
||||
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc39.x86_64.rpm "${RPM_PATH}"
|
||||
elif [[ "${DISTRIBUTION}" == "fedora_40" ]]; then
|
||||
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc40.x86_64.rpm "${RPM_PATH}"
|
||||
elif [[ "${DISTRIBUTION}" == "fedora_41" ]]; then
|
||||
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc41.x86_64.rpm "${RPM_PATH}"
|
||||
elif [[ "${DISTRIBUTION}" == "alma_9" ]]; then
|
||||
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.el9.x86_64.rpm "${RPM_PATH}"
|
||||
else
|
||||
|
||||
@ -8,9 +8,6 @@ set -e
|
||||
OLD_WD=$(pwd)
|
||||
cd /tmp
|
||||
|
||||
# Install PipeWire's build dependencies
|
||||
apt-get install --yes gcc git libasound2-dev libdbus-1-dev libglib2.0-dev ninja-build pkg-config
|
||||
|
||||
# Get a version of Meson that's recent enough to build PipeWire 1.0.5 (the one available via apt is too old)
|
||||
wget -q https://github.com/mesonbuild/meson/releases/download/0.61.1/meson-0.61.1.tar.gz
|
||||
echo "feb2cefb325b437dbf36146df7c6b87688ddff0b0205caa31dc64055c6da410c meson-0.61.1.tar.gz" | sha256sum --check
|
||||
|
||||
@ -99,6 +99,12 @@ for ARCH in "${ARCHS[@]}"; do
|
||||
echo "$ARCH"
|
||||
cd "$DAEMON"
|
||||
HOST="${ARCH}-apple-darwin"
|
||||
SDKROOT=$(xcrun --sdk macosx --show-sdk-path)
|
||||
|
||||
CC="xcrun -sdk macosx clang"
|
||||
CXX="xcrun -sdk macosx clang++"
|
||||
CFLAGS="-arch $ARCH -isysroot $SDKROOT"
|
||||
CXXFLAGS="-std=c++17 $CFLAGS"
|
||||
CONFIGURE_FLAGS=" --without-dbus --host=${HOST} -with-contrib=$DAEMON/contrib/${ARCH}-apple-darwin${OS_VER} --prefix=${INSTALL}/daemon/$ARCH"
|
||||
|
||||
if [ "${debug}" = "true" ]; then
|
||||
@ -113,7 +119,11 @@ for ARCH in "${ARCHS[@]}"; do
|
||||
mkdir -p "build-macos-${ARCH}"
|
||||
cd "build-macos-${ARCH}"
|
||||
|
||||
"$DAEMON"/configure $CONFIGURE_FLAGS ARCH="$ARCH" || exit 1
|
||||
"$DAEMON"/configure $CONFIGURE_FLAGS ARCH="$ARCH" \
|
||||
CC="$CC $CFLAGS" \
|
||||
CXX="$CXX $CXXFLAGS" \
|
||||
CFLAGS="$CFLAGS" \
|
||||
CXXFLAGS="$CXXFLAGS" || exit 1
|
||||
|
||||
echo "$CONFIGURE_FLAGS"
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M42 13.85V39q0 1.2-.9 2.1-.9.9-2.1.9H9q-1.2 0-2.1-.9Q6 40.2 6 39V9q0-1.2.9-2.1Q7.8 6 9 6h25.15Zm-3 1.35L32.8 9H9v30h30ZM24 35.75q2.15 0 3.675-1.525T29.2 30.55q0-2.15-1.525-3.675T24 25.35q-2.15 0-3.675 1.525T18.8 30.55q0 2.15 1.525 3.675T24 35.75ZM11.65 18.8h17.9v-7.15h-17.9ZM9 15.2V39 9Z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#e8eaed"><path d="M480-313 287-506l43-43 120 120v-371h60v371l120-120 43 43-193 193ZM220-160q-24 0-42-18t-18-42v-143h60v143h520v-143h60v143q0 24-18 42t-42 18H220Z"/></svg>
|
||||
|
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 268 B |
11
resources/icons/share_black_24dp.svg
Normal file
11
resources/icons/share_black_24dp.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<path d="M17.1,15.7c-0.8,0-1.5,0.3-2.1,0.8l-5.3-3.3C9.9,12.8,10,12.4,10,12c0-0.4-0.1-0.8-0.3-1.2l5.3-3.3c0.6,0.5,1.3,0.8,2.1,0.8
|
||||
c1.7,0,3.1-1.4,3.1-3.1S18.9,2,17.1,2C15.4,2,14,3.4,14,5.1c0,0.4,0.1,0.8,0.3,1.2L8.9,9.6C8.3,9.1,7.6,8.9,6.9,8.9
|
||||
c-1.7,0-3.1,1.4-3.1,3.1s1.4,3.1,3.1,3.1c0.8,0,1.5-0.3,2.1-0.8l5.3,3.3C14.1,18,14,18.4,14,18.9c0,1.7,1.4,3.1,3.1,3.1
|
||||
c1.7,0,3.1-1.4,3.1-3.1S18.9,15.7,17.1,15.7z M17.1,20.6c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8c1,0,1.8,0.8,1.8,1.8
|
||||
S18.1,20.6,17.1,20.6z M17.1,3.4c1,0,1.8,0.8,1.8,1.8s-0.8,1.8-1.8,1.8c-1,0-1.8-0.8-1.8-1.8S16.2,3.4,17.1,3.4z M6.9,13.8
|
||||
c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8S8.6,11,8.6,12S7.8,13.8,6.9,13.8z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1019 B |
@ -1,11 +1,13 @@
|
||||
<h4 align="left"><span style="font-weight:600"> Created by</span></h4>
|
||||
<p>%1</p>
|
||||
<h4 align="left"><span style="font-weight:600">%2</span></h4>
|
||||
<p>Abhishek Ojha<br>
|
||||
Adrien Béraud<br>
|
||||
Albert Babí<br>
|
||||
Alexandre Lision<br>
|
||||
Alexandr Sergheev<br>
|
||||
Alexandre Viau<br>
|
||||
Alexander Lussier-Cullen<br>
|
||||
Alexandr Sergheev<br>
|
||||
Alexandre Eberhardt<br>
|
||||
Alexandre Lision<br>
|
||||
Alexandre Viau<br>
|
||||
Aline Bonnet<br>
|
||||
Aline Gondim Santos<br>
|
||||
Alireza Toghiani<br>
|
||||
@ -18,7 +20,6 @@ Brando Tovar<br>
|
||||
Capucine Berthet<br>
|
||||
Charles-Francis Damedey<br>
|
||||
Cyrille Béraud<br>
|
||||
Dorina Mosku<br>
|
||||
Eden Abitbol<br>
|
||||
Édric Milaret<br>
|
||||
Éloi Bail<br>
|
||||
@ -33,11 +34,16 @@ Guillaume Roguez<br>
|
||||
Hadrien De Sousa<br>
|
||||
Hugo Lefeuvre<br>
|
||||
Julien Grossholtz<br>
|
||||
Julien Robert<br>
|
||||
Kateryna Kostiuk<br>
|
||||
Kessler DuPont-Teevin<br>
|
||||
Léo Banno-Cloutier<br>
|
||||
Léopold Chappuis<br>
|
||||
Liam Courdoson<br>
|
||||
Loïc Siret<br>
|
||||
Louis Maillard<br>
|
||||
Mathéo Joseph<br>
|
||||
Michel Schmit<br>
|
||||
Mingrui Zhang<br>
|
||||
Mohamed Chibani<br>
|
||||
Mohamed Amine Younes Bouacida<br>
|
||||
@ -57,6 +63,7 @@ Rayan Osseiran<br>
|
||||
Romain Bertozzi<br>
|
||||
Saher Azer<br>
|
||||
Sébastien Blin<br>
|
||||
Seva Ivanov<br>
|
||||
Silbino Gonçalves Matado<br>
|
||||
Simon Désaulniers<br>
|
||||
Simon Zeni<br>
|
||||
@ -64,9 +71,21 @@ Stepan Salenikovich<br>
|
||||
Thibault Wittemberg<br>
|
||||
Thomas Ballasi<br>
|
||||
Trevor Tabah<br>
|
||||
Vitalii Nikitchyn<br>
|
||||
Vsevolod Ivanov<br>
|
||||
Xavier Jouslin de Noray<br>
|
||||
Yang Wang<br></p>
|
||||
<h4 align="left"><span style="font-weight:600"> Artwork by</span></h4>
|
||||
Yang Wang<br>
|
||||
</p>
|
||||
<h4 align="left"><span style="font-weight:600"> %3</span></h4>
|
||||
<p>Charlotte Hoffmann<br>
|
||||
Marianne Forget<br></p>
|
||||
<h4 align="left"><span style="font-weight:600"> %4</span></h4>
|
||||
<p>Dorina Mosku<br>
|
||||
Cabrel Tambue<br>
|
||||
Loïc Bogino<br></p>
|
||||
<h4 align="left"><span style="font-weight:600"> %5</span></h4>
|
||||
<p>Anna<br>
|
||||
Elys<br>
|
||||
VeroJeanLuc<br>
|
||||
</p>
|
||||
<p>%6</p>
|
||||
|
||||
@ -145,6 +145,16 @@ ApplicationWindow {
|
||||
LRCInstance.selectConversation(convUid);
|
||||
}
|
||||
}
|
||||
ListElement {
|
||||
label: "Account ID"
|
||||
type: "combobox"
|
||||
getDataModel: () => AccountListModel
|
||||
displayRole: AccountList.Username
|
||||
onIndexChanged: function(model, index) {
|
||||
const accountId = JamiQmlUtils.getModelData(model, index, AccountList.ID);
|
||||
LRCInstance.currentAccountId = accountId;
|
||||
}
|
||||
}
|
||||
ListElement {
|
||||
label: "Force local preview"
|
||||
type: "checkbox"
|
||||
|
||||
@ -29,6 +29,35 @@ AccountListModel::AccountListModel(LRCInstance* instance, QObject* parent)
|
||||
: AbstractListModelBase(parent)
|
||||
{
|
||||
lrcInstance_ = instance;
|
||||
|
||||
// Avoid resetting/redrawing the model when the account status changes.
|
||||
QObject::connect(&lrcInstance_->accountModel(),
|
||||
&AccountModel::accountStatusChanged,
|
||||
this,
|
||||
[&](const QString& accountId) {
|
||||
auto accountList = lrcInstance_->accountModel().getAccountList();
|
||||
auto index = accountList.indexOf(accountId);
|
||||
if (index != -1) {
|
||||
QModelIndex modelIndex = QAbstractListModel::index(index, 0);
|
||||
Q_EMIT dataChanged(modelIndex, modelIndex /*, ALL ROLES */);
|
||||
}
|
||||
});
|
||||
// If there's a reorder, it's reasonable to reset the model for simplicity, instead
|
||||
// of computing the difference. The same goes for accounts being added and removed.
|
||||
// These operations will only occur when the list is hidden, unless dbus is used while
|
||||
// the list is visible.
|
||||
QObject::connect(&lrcInstance_->accountModel(),
|
||||
&AccountModel::accountsReordered,
|
||||
this,
|
||||
&AccountListModel::reset);
|
||||
QObject::connect(&lrcInstance_->accountModel(),
|
||||
&AccountModel::accountAdded,
|
||||
this,
|
||||
&AccountListModel::reset);
|
||||
QObject::connect(&lrcInstance_->accountModel(),
|
||||
&AccountModel::accountRemoved,
|
||||
this,
|
||||
&AccountListModel::reset);
|
||||
}
|
||||
|
||||
int
|
||||
@ -91,6 +120,7 @@ AccountListModel::roleNames() const
|
||||
void
|
||||
AccountListModel::reset()
|
||||
{
|
||||
// Used to invalidate proxy models.
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
@ -57,7 +57,6 @@ Popup {
|
||||
id: container
|
||||
|
||||
property color color: JamiTheme.secondaryBackgroundColor
|
||||
anchors.centerIn: parent
|
||||
leftPadding: popupMargins
|
||||
bottomPadding: action1.visible || action2.visible ? 10 :popupMargins
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ SBSMessageBase {
|
||||
bubble.border.color: CurrentConversation.color
|
||||
bubble.border.width: root.isActive ? 1.5 : 0
|
||||
bubble.color: JamiTheme.messageInBgColor
|
||||
bubble.opacity: 0.6
|
||||
bubble.opacity: 1
|
||||
|
||||
Connections {
|
||||
target: CurrentConversation
|
||||
@ -113,7 +113,7 @@ SBSMessageBase {
|
||||
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
Text {
|
||||
id: callLabel
|
||||
objectName: "callLabel"
|
||||
|
||||
@ -141,19 +141,19 @@ SBSMessageBase {
|
||||
}
|
||||
|
||||
JoinCallButton {
|
||||
id: joinCallInAudio
|
||||
objectName: "joinCallInAudio"
|
||||
id: joinCallWithAudio
|
||||
objectName: "joinCallWithAudio"
|
||||
Layout.topMargin: 4
|
||||
Layout.bottomMargin: 4
|
||||
|
||||
text: JamiStrings.joinInAudio
|
||||
text: JamiStrings.joinWithAudio
|
||||
onClicked: MessagesAdapter.joinCall(ActionUri, DeviceId, root.confId, true)
|
||||
}
|
||||
|
||||
JoinCallButton {
|
||||
id: joinCallInVideo
|
||||
objectName: "joinCallInVideo"
|
||||
text: JamiStrings.joinInVideo
|
||||
id: joinCallWithVideo
|
||||
objectName: "joinCallWithVideo"
|
||||
text: JamiStrings.joinWithVideo
|
||||
Layout.topMargin: 4
|
||||
Layout.bottomMargin: 4
|
||||
|
||||
|
||||
@ -40,9 +40,18 @@ Loader {
|
||||
property int seq: MsgSeq.single
|
||||
property string author: Author
|
||||
property string body: Body
|
||||
property int transferStatus: Status
|
||||
property var tid: TID
|
||||
property int transferStatus: TransferStatus
|
||||
onTidChanged: {
|
||||
if (tid === "") {
|
||||
sourceComponent = deletedMsgComp
|
||||
}
|
||||
}
|
||||
onTransferStatusChanged: {
|
||||
if (transferStatus === Interaction.Status.TRANSFER_FINISHED) {
|
||||
if (tid === "") {
|
||||
sourceComponent = deletedMsgComp
|
||||
return;
|
||||
} else if (transferStatus === Interaction.TransferStatus.TRANSFER_FINISHED) {
|
||||
mediaInfo = MessagesAdapter.getMediaInfo(root.body);
|
||||
if (Object.keys(mediaInfo).length !== 0 && WITH_WEBENGINE) {
|
||||
sourceComponent = localMediaMsgComp;
|
||||
@ -58,6 +67,54 @@ Loader {
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
onLoaded: opacity = 1
|
||||
|
||||
Component {
|
||||
id: deletedMsgComp
|
||||
|
||||
SBSMessageBase {
|
||||
id: deletedItem
|
||||
|
||||
isOutgoing: Author === CurrentAccount.uri
|
||||
showTime: root.showTime
|
||||
seq: root.seq
|
||||
author: Author
|
||||
readers: Readers
|
||||
timestamp: root.timestamp
|
||||
formattedTime: root.formattedTime
|
||||
formattedDay: root.formattedTime
|
||||
extraHeight: 0
|
||||
textContentWidth: textEditId.width
|
||||
textContentHeight: textEditId.height
|
||||
innerContent.children: [
|
||||
TextEdit {
|
||||
id: textEditId
|
||||
|
||||
anchors.right: isOutgoing ? parent.right : undefined
|
||||
anchors.rightMargin: isOutgoing ? timeWidth : 0
|
||||
bottomPadding: 6
|
||||
topPadding: 6
|
||||
leftPadding: 10
|
||||
text: UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author) + " " + JamiStrings.deletedMedia ;
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
width: Math.min((2 / 3) * parent.width, implicitWidth + 18, innerContent.width - senderMargin + 18)
|
||||
|
||||
font.pointSize: JamiTheme.smallFontSize
|
||||
font.hintingPreference: Font.PreferNoHinting
|
||||
renderType: Text.NativeRendering
|
||||
textFormat: Text.RichText
|
||||
clip: true
|
||||
readOnly: true
|
||||
color: getBaseColor()
|
||||
opacity: 0.5
|
||||
|
||||
function getBaseColor() {
|
||||
bubble.isDeleted = true
|
||||
return UtilsAdapter.luma(bubble.color) ? "white" : "dark"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: dataTransferMsgComp
|
||||
|
||||
@ -66,7 +123,7 @@ Loader {
|
||||
|
||||
transferId: Id
|
||||
property var transferStats: MessagesAdapter.getTransferStats(transferId, root.transferStatus)
|
||||
property bool canOpen: root.transferStatus === Interaction.Status.TRANSFER_FINISHED || isOutgoing
|
||||
property bool canOpen: root.transferStatus === Interaction.TransferStatus.TRANSFER_FINISHED || isOutgoing
|
||||
property real maxMsgWidth: root.width - senderMargin -
|
||||
2 * hPadding - avatarBlockWidth
|
||||
- buttonsLoader.width - 24 - 6 - 24
|
||||
@ -112,18 +169,18 @@ Loader {
|
||||
|
||||
sourceComponent: {
|
||||
switch (root.transferStatus) {
|
||||
case Interaction.Status.TRANSFER_CREATED:
|
||||
case Interaction.Status.TRANSFER_FINISHED:
|
||||
case Interaction.TransferStatus.TRANSFER_CREATED:
|
||||
case Interaction.TransferStatus.TRANSFER_FINISHED:
|
||||
iconSource = JamiResources.link_black_24dp_svg
|
||||
return terminatedComp
|
||||
case Interaction.Status.TRANSFER_CANCELED:
|
||||
case Interaction.Status.TRANSFER_ERROR:
|
||||
case Interaction.Status.TRANSFER_UNJOINABLE_PEER:
|
||||
case Interaction.Status.TRANSFER_TIMEOUT_EXPIRED:
|
||||
case Interaction.Status.TRANSFER_AWAITING_HOST:
|
||||
case Interaction.TransferStatus.TRANSFER_CANCELED:
|
||||
case Interaction.TransferStatus.TRANSFER_ERROR:
|
||||
case Interaction.TransferStatus.TRANSFER_UNJOINABLE_PEER:
|
||||
case Interaction.TransferStatus.TRANSFER_TIMEOUT_EXPIRED:
|
||||
case Interaction.TransferStatus.TRANSFER_AWAITING_HOST:
|
||||
iconSource = JamiResources.download_black_24dp_svg
|
||||
return optionsComp
|
||||
case Interaction.Status.TRANSFER_ONGOING:
|
||||
case Interaction.TransferStatus.TRANSFER_ONGOING:
|
||||
iconSource = JamiResources.close_black_24dp_svg
|
||||
return optionsComp
|
||||
default:
|
||||
@ -158,7 +215,7 @@ Loader {
|
||||
normalColor: JamiTheme.chatviewBgColor
|
||||
imageColor: JamiTheme.chatviewButtonColor
|
||||
onClicked: {
|
||||
if (root.transferStatus === Interaction.Status.TRANSFER_ONGOING) {
|
||||
if (root.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING) {
|
||||
return MessagesAdapter.cancelFile(transferId)
|
||||
} else {
|
||||
return MessagesAdapter.acceptFile(transferId)
|
||||
@ -191,7 +248,7 @@ Loader {
|
||||
onClicked: function (mouse) {
|
||||
if (canOpen) {
|
||||
dataTransferItem.hoveredLink = UtilsAdapter.urlFromLocalPath(location)
|
||||
Qt.openUrlExternally(new Url(dataTransferItem.hoveredLink))
|
||||
Qt.openUrlExternally(new URL(dataTransferItem.hoveredLink))
|
||||
} else {
|
||||
dataTransferItem.hoveredLink = ""
|
||||
}
|
||||
@ -223,11 +280,11 @@ Loader {
|
||||
: JamiTheme.chatviewTextColorDark
|
||||
}
|
||||
}
|
||||
}
|
||||
,ProgressBar {
|
||||
},
|
||||
ProgressBar {
|
||||
id: progressBar
|
||||
|
||||
visible: root.transferStatus === Interaction.Status.TRANSFER_ONGOING
|
||||
visible: root.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING
|
||||
height: visible * implicitHeight
|
||||
value: transferStats.progress / transferStats.totalSize
|
||||
width: transferItem.width
|
||||
|
||||
@ -73,7 +73,7 @@ BaseModalDialog {
|
||||
Layout.bottomMargin: 5
|
||||
|
||||
color: JamiTheme.textColor
|
||||
text: JamiStrings.confirmDeleteQuestion
|
||||
text: JamiStrings.confirmDeleteAccount
|
||||
|
||||
font.pointSize: JamiTheme.textFontSize
|
||||
font.kerning: true
|
||||
|
||||
@ -121,10 +121,7 @@ Item {
|
||||
font.pixelSize : text.length > 16 ? JamiTheme.jamiIdSmallFontSize : JamiTheme.bigFontSize
|
||||
property string registeredName: CurrentAccount.registeredName
|
||||
property string infohash: CurrentAccount.uri
|
||||
text: registeredName ? registeredName : infohash
|
||||
onRegisteredNameChanged: {
|
||||
text = registeredName ? registeredName : infohash
|
||||
}
|
||||
text: (btnId.clicked && registeredName) ? registeredName : infohash
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -154,7 +151,7 @@ Item {
|
||||
JamiIdControlButton {
|
||||
id: btnEdit
|
||||
anchors.leftMargin: JamiTheme.pushButtonMargins
|
||||
visible: CurrentAccount.registeredName === ""
|
||||
visible: CurrentAccount.registeredName === "" && CurrentAccount.enabled
|
||||
imageColor: enabled ? JamiTheme.tintedBlue : JamiTheme.buttonTintedBlack
|
||||
border.color: usernameTextEdit.editMode ? jamiId.contentColor : "transparent"
|
||||
enabled: {
|
||||
@ -231,11 +228,9 @@ Item {
|
||||
toolTipText: JamiStrings.identifierURI
|
||||
onClicked: {
|
||||
if (clicked) {
|
||||
usernameLabel.text = Qt.binding(function() {return CurrentAccount.uri} );
|
||||
usernameTextEdit.staticText = Qt.binding(function() {return CurrentAccount.uri} );
|
||||
btnId.toolTipText = JamiStrings.identifierRegisterName;
|
||||
} else {
|
||||
usernameLabel.text = Qt.binding(function() {return CurrentAccount.registeredName} );
|
||||
usernameTextEdit.staticText = Qt.binding(function() {return CurrentAccount.registeredName} );
|
||||
btnId.toolTipText = JamiStrings.identifierURI;
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ SplitView {
|
||||
// size (4 pixels). This is done to make it easier to grab small scroll-view handles that are
|
||||
// adjacent to the SplitView handle. Note: vertically oriented handles are not offset.
|
||||
readonly property real extraHandleSize: 4
|
||||
readonly property real handleXPosition: !isRTL ? 0 : -extraHandleSize
|
||||
readonly property real handleXPosition: !UtilsAdapter.isRTL ? 0 : -extraHandleSize
|
||||
readonly property real handleSize: handleRoot.defaultSize + extraHandleSize
|
||||
|
||||
x: control.orientation === Qt.Horizontal ? handleXPosition : 0
|
||||
|
||||
@ -164,7 +164,7 @@ BaseModalDialog {
|
||||
appWindow,
|
||||
"commoncomponents/JamiFileDialog.qml",
|
||||
{
|
||||
title: JamiStrings.selectAvatarImage,
|
||||
title: JamiStrings.selectProfilePicture,
|
||||
fileMode: JamiFileDialog.OpenFile,
|
||||
folder: StandardPaths.writableLocation(
|
||||
StandardPaths.PicturesLocation),
|
||||
|
||||
@ -278,7 +278,7 @@ Control {
|
||||
|
||||
anchors.right: isOutgoing ? bubble.left : undefined
|
||||
anchors.left: !isOutgoing ? bubble.right : undefined
|
||||
width: JamiTheme.emojiPushButtonSize * 2
|
||||
width: JamiTheme.emojiPushButtonSize * 4
|
||||
height: JamiTheme.emojiPushButtonSize
|
||||
anchors.verticalCenter: bubble.verticalCenter
|
||||
|
||||
@ -299,24 +299,24 @@ Control {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: isOutgoing ? optionButtonItem.right : undefined
|
||||
anchors.left: !isOutgoing ? optionButtonItem.left : undefined
|
||||
visible: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || bgHandler.hovered)
|
||||
visible: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || share.hovered || bgHandler.hovered)
|
||||
source: JamiResources.more_vert_24dp_svg
|
||||
width: optionButtonItem.width / 2
|
||||
width: optionButtonItem.width / 4
|
||||
height: optionButtonItem.height
|
||||
circled: false
|
||||
property bool isOpen: false
|
||||
property var obj: undefined
|
||||
|
||||
function bind() {
|
||||
function setBindings() {
|
||||
more.isOpen = false;
|
||||
visible = Qt.binding(() => CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || bgHandler.hovered));
|
||||
visible = Qt.binding(() => CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || share.hovered || bgHandler.hovered));
|
||||
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
|
||||
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (more.isOpen) {
|
||||
more.bind();
|
||||
more.setBindings();
|
||||
obj.close();
|
||||
} else {
|
||||
var component = Qt.createComponent("qrc:/commoncomponents/ShowMoreMenu.qml");
|
||||
@ -332,7 +332,7 @@ Control {
|
||||
});
|
||||
obj.open();
|
||||
more.isOpen = true;
|
||||
visible = true;
|
||||
visible = true; // the button stay visible as long the popup is open even if it's not hovered
|
||||
imageColor = JamiTheme.chatViewFooterImgHoverColor;
|
||||
normalColor = JamiTheme.hoveredButtonColor;
|
||||
}
|
||||
@ -348,19 +348,75 @@ Control {
|
||||
normalColor: JamiTheme.primaryBackgroundColor
|
||||
toolTipText: JamiStrings.reply
|
||||
source: JamiResources.reply_black_24dp_svg
|
||||
width: optionButtonItem.width / 2
|
||||
width: optionButtonItem.width / 4
|
||||
height: optionButtonItem.height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.rightMargin: 5
|
||||
anchors.right: isOutgoing ? more.left : undefined
|
||||
anchors.left: !isOutgoing ? more.right : undefined
|
||||
visible: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || more.hovered || bgHandler.hovered)
|
||||
visible: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || more.hovered || share.hovered || bgHandler.hovered)
|
||||
|
||||
onClicked: {
|
||||
MessagesAdapter.editId = "";
|
||||
MessagesAdapter.replyToId = Id;
|
||||
}
|
||||
}
|
||||
|
||||
PushButton {
|
||||
id: share
|
||||
objectName: "share"
|
||||
|
||||
circled: false
|
||||
imageColor: hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor
|
||||
normalColor: JamiTheme.primaryBackgroundColor
|
||||
toolTipText: JamiStrings.share
|
||||
source: JamiResources.share_black_24dp_svg
|
||||
|
||||
width: optionButtonItem.width / 4
|
||||
height: optionButtonItem.height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.rightMargin: 5
|
||||
anchors.right: isOutgoing ? reply.left : undefined
|
||||
anchors.left: !isOutgoing ? reply.right : undefined
|
||||
visible: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || more.hovered || bgHandler.hovered)
|
||||
property bool isOpen: false
|
||||
property var obj: undefined
|
||||
|
||||
function setBindings() { // when the popup is closed, setBindings is called to reset the icon's visual settings
|
||||
share.isOpen = false;
|
||||
visible = Qt.binding(() => CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || more.hovered || bgHandler.hovered));
|
||||
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
|
||||
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (share.isOpen) {
|
||||
share.setBindings();
|
||||
obj.close();
|
||||
} else {
|
||||
if (root.type === 2 || root.type === 5) {
|
||||
// 2=TEXT and 5=DATA_TRANSFER (any kind of file) defined in interaction.h
|
||||
var component = Qt.createComponent("qrc:/commoncomponents/ShareMessageMenu.qml");
|
||||
obj = component.createObject(share, {
|
||||
"isOutgoing": isOutgoing,
|
||||
"msgId": Id,
|
||||
"msgBody": Body,
|
||||
"type": root.type,
|
||||
"transferName": TransferName,
|
||||
"msgBubble": bubble,
|
||||
"listView": listView,
|
||||
"author": UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author),
|
||||
"formattedTime": formattedTime
|
||||
});
|
||||
obj.open();
|
||||
share.isOpen = true;
|
||||
visible = true; // the PushButton stay visible as long the popup is open even if it's not hovered
|
||||
imageColor = JamiTheme.chatViewFooterImgHoverColor;
|
||||
normalColor = JamiTheme.hoveredButtonColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageBubble {
|
||||
@ -382,7 +438,7 @@ Control {
|
||||
property bool bubbleHovered
|
||||
property string imgSource
|
||||
|
||||
width: (root.type === Interaction.Type.TEXT ? root.textContentWidth + (IsEmojiOnly || root.bigMsg ? 0 : root.timeWidth + root.editedWidth) : innerContent.childrenRect.width)
|
||||
width: (root.type === Interaction.Type.TEXT || isDeleted ? root.textContentWidth + (IsEmojiOnly || root.bigMsg ? 0 : root.timeWidth + root.editedWidth) : innerContent.childrenRect.width)
|
||||
height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0) + (root.bigMsg ? 15 : 0)
|
||||
|
||||
HoverHandler {
|
||||
@ -466,6 +522,11 @@ Control {
|
||||
MessagesAdapter.openUrl(root.hoveredLink);
|
||||
}
|
||||
}
|
||||
|
||||
onDoubleClicked: {
|
||||
MessagesAdapter.editId = "";
|
||||
MessagesAdapter.replyToId = Id;
|
||||
}
|
||||
property bool bubbleHovered: containsMouse || textHovered
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
|
||||
264
src/app/commoncomponents/ShareMessageMenu.qml
Normal file
264
src/app/commoncomponents/ShareMessageMenu.qml
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Savoir-faire Linux Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import net.jami.Constants 1.1
|
||||
import net.jami.Models 1.1
|
||||
import net.jami.Adapters 1.1
|
||||
import SortFilterProxyModel 0.2
|
||||
import "contextmenu"
|
||||
import "../commoncomponents"
|
||||
import "../mainview/components"
|
||||
|
||||
BaseContextMenu {
|
||||
id: mainMenu
|
||||
|
||||
height: 330 + Math.min(messageInput.height, textareaMaxHeight)
|
||||
width: 400
|
||||
|
||||
required property string msgId
|
||||
required property string msgBody
|
||||
required property bool isOutgoing
|
||||
required property int type
|
||||
required property string transferName
|
||||
required property Item msgBubble
|
||||
required property ListView listView
|
||||
required property string author
|
||||
required property string formattedTime
|
||||
|
||||
property var selectedUids: []
|
||||
property string shareToId: msgId
|
||||
property string fileLink: msgBody
|
||||
property int textareaMaxHeight: 350
|
||||
function xPosition(width) {
|
||||
// Use the width at function scope to retrigger property evaluation.
|
||||
const listViewWidth = listView.width;
|
||||
const parentX = parent.x;
|
||||
if (isOutgoing) {
|
||||
return parentX - width - 20;
|
||||
} else {
|
||||
return parentX + 20;
|
||||
}
|
||||
}
|
||||
|
||||
x: xPosition(width)
|
||||
y: parent.y
|
||||
|
||||
function xPositionProvider(width) {
|
||||
// Use the width at function scope to retrigger property evaluation.
|
||||
const listViewWidth = listView.width;
|
||||
if (isOutgoing) {
|
||||
return -5 - width;
|
||||
} else {
|
||||
const rightMargin = listViewWidth - (msgBubble.x + width);
|
||||
return width > rightMargin + 35 ? -5 - width : 35;
|
||||
}
|
||||
}
|
||||
function yPositionProvider(height) {
|
||||
const topOffset = msgBubble.mapToItem(listView, 0, 0).y;
|
||||
const listViewHeight = listView.height;
|
||||
const bottomMargin = listViewHeight - height - topOffset;
|
||||
if (bottomMargin < 0 || (topOffset < 0 && topOffset + height > 0)) {
|
||||
return 30 - height;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: shareConvProxyModel
|
||||
|
||||
sourceModel: ConversationsAdapter.convListProxyModel
|
||||
filterCaseSensitivity: Qt.CaseInsensitive
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: header
|
||||
|
||||
width: parent.width
|
||||
height: 0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: sendButton
|
||||
|
||||
height: JamiTheme.chatViewFooterButtonSize
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 10
|
||||
anchors.topMargin: 10
|
||||
anchors.top: header.bottom
|
||||
color: JamiTheme.transparentColor
|
||||
|
||||
PushButton {
|
||||
id: shareMessageButton
|
||||
|
||||
height: JamiTheme.chatViewFooterButtonSize
|
||||
width: scale * JamiTheme.chatViewFooterButtonSize
|
||||
anchors.right: parent.right
|
||||
|
||||
visible: true
|
||||
|
||||
radius: JamiTheme.chatViewFooterButtonRadius
|
||||
preferredSize: JamiTheme.chatViewFooterButtonIconSize - 6
|
||||
imageContainerWidth: 25
|
||||
imageContainerHeight: 25
|
||||
|
||||
toolTipText: JamiStrings.share
|
||||
|
||||
mirror: UtilsAdapter.isRTL
|
||||
|
||||
source: JamiResources.send_black_24dp_svg
|
||||
|
||||
hoverEnabled: enabled
|
||||
normalColor: enabled ? JamiTheme.chatViewFooterSendButtonColor : JamiTheme.chatViewFooterSendButtonDisableColor
|
||||
imageColor: enabled ? JamiTheme.chatViewFooterSendButtonImgColor : JamiTheme.chatViewFooterSendButtonImgColorDisable
|
||||
hoveredColor: JamiTheme.buttonTintedBlueHovered
|
||||
pressedColor: hoveredColor
|
||||
|
||||
opacity: 1
|
||||
scale: opacity
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
var selectedContacts = mainMenu.selectedUids;
|
||||
var hasText = messageInput.text && selectedContacts.length > 0;
|
||||
function sendMessageOrFile(uid) {
|
||||
if (Type === 2) {
|
||||
// 2=TEXT and 5=DATA_TRANSFER (any kind of file) defined in interaction.h
|
||||
MessagesAdapter.sendMessageToUid(msgBody, uid);
|
||||
} else {
|
||||
MessagesAdapter.sendFileToUid(fileLink, uid);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < selectedContacts.length; i++) {
|
||||
var uid = selectedContacts[i];
|
||||
sendMessageOrFile(uid);
|
||||
if (hasText) {
|
||||
MessagesAdapter.sendMessageToUid(messageInput.text, uid);
|
||||
}
|
||||
}
|
||||
messageInput.text = "";
|
||||
mainMenu.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: searchConv
|
||||
|
||||
height: 300
|
||||
width: parent.width
|
||||
anchors.top: header.bottom
|
||||
anchors.topMargin: 10
|
||||
|
||||
property int type: ContactList.CONVERSATION
|
||||
|
||||
color: JamiTheme.transparentColor
|
||||
ColumnLayout {
|
||||
id: contactPickerPopupRectColumnLayout
|
||||
|
||||
anchors.fill: parent
|
||||
Searchbar {
|
||||
id: contactPickerContactSearchBar
|
||||
|
||||
width: parent.width - 20 - JamiTheme.chatViewFooterButtonSize
|
||||
anchors.leftMargin: 10
|
||||
Layout.preferredHeight: 35
|
||||
placeHolderText: "Share to..."
|
||||
onSearchBarTextChanged: function (text) {
|
||||
shareConvProxyModel.filterRole = shareConvProxyModel.roleForName("Title");
|
||||
shareConvProxyModel.filterPattern = text;
|
||||
}
|
||||
}
|
||||
JamiListView {
|
||||
id: contactPickerListView
|
||||
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 255
|
||||
Layout.bottomMargin: JamiTheme.preferredMarginSize
|
||||
Layout.topMargin: 5
|
||||
|
||||
model: shareConvProxyModel
|
||||
|
||||
delegate: ConversationPickerItemDelegate {
|
||||
id: conversationDelegate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: messageInputContainer
|
||||
|
||||
height: Math.min(contentHeight, mainMenu.textareaMaxHeight)
|
||||
width: parent.width - 20
|
||||
contentHeight: messageInput.height
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10
|
||||
anchors.rightMargin: 10
|
||||
anchors.topMargin: 10
|
||||
anchors.top: searchConv.bottom
|
||||
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
clip: true
|
||||
|
||||
ScrollBar.vertical: JamiScrollBar {
|
||||
policy: ScrollBar.AsNeeded
|
||||
}
|
||||
|
||||
onContentHeightChanged: {
|
||||
if (contentHeight > height) {
|
||||
contentY = contentHeight - height;
|
||||
}
|
||||
}
|
||||
|
||||
TextArea {
|
||||
id: messageInput
|
||||
|
||||
height: contentHeight + 12
|
||||
width: parent.width
|
||||
placeholderText: "Add a comment"
|
||||
placeholderTextColor: JamiTheme.messageBarPlaceholderTextColor
|
||||
font.pointSize: JamiTheme.textFontSize + 2
|
||||
color: JamiTheme.textColor
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
background: Rectangle {
|
||||
color: JamiTheme.transparentColor
|
||||
radius: 5
|
||||
border.color: JamiTheme.chatViewFooterRectangleBorderColor
|
||||
border.width: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// destroy() and setBindings() are needed to unselect the share icon from SBSMessageBase
|
||||
|
||||
onAboutToHide: {
|
||||
mainMenu.destroy();
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
parent.setBindings();
|
||||
}
|
||||
}
|
||||
@ -153,7 +153,7 @@ BaseContextMenu {
|
||||
GeneralMenuItem {
|
||||
id: removeLocally
|
||||
|
||||
canTrigger: type === Interaction.Type.DATA_TRANSFER && Status === Interaction.Status.TRANSFER_FINISHED
|
||||
canTrigger: type === Interaction.Type.DATA_TRANSFER && TransferStatus === Interaction.TransferStatus.TRANSFER_FINISHED
|
||||
iconSource: JamiResources.trash_black_24dp_svg
|
||||
itemName: JamiStrings.removeLocally
|
||||
onClicked: {
|
||||
@ -175,7 +175,7 @@ BaseContextMenu {
|
||||
GeneralMenuItem {
|
||||
id: deleteMessage
|
||||
|
||||
canTrigger: root.isOutgoing && type === Interaction.Type.TEXT
|
||||
canTrigger: root.isOutgoing && (type === Interaction.Type.TEXT || type === Interaction.Type.DATA_TRANSFER)
|
||||
iconSource: JamiResources.delete_svg
|
||||
itemName: JamiStrings.deleteMessage
|
||||
onClicked: {
|
||||
@ -198,11 +198,13 @@ BaseContextMenu {
|
||||
root.loadMenuItems(menuItems);
|
||||
}
|
||||
|
||||
// destroy() and setBindings() are needed to unselect the share icon from SBSMessageBase
|
||||
|
||||
onAboutToHide: {
|
||||
root.destroy();
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
parent.bind();
|
||||
parent.setBindings();
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ ConversationListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s
|
||||
}
|
||||
} else {
|
||||
Q_FOREACH (const auto& filter, toFilter)
|
||||
if (rx.match(filter).hasMatch()) {
|
||||
if (rx.isValid() && rx.match(filter).hasMatch()) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -125,7 +125,11 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
|
||||
if (interaction.type == interaction::Type::UPDATE_PROFILE) {
|
||||
lastInteractionBody = interaction::getProfileUpdatedString();
|
||||
} else if (interaction.type == interaction::Type::DATA_TRANSFER) {
|
||||
lastInteractionBody = interaction.commit.value("displayName");
|
||||
if (interaction.commit.value("tid").isEmpty()) {
|
||||
lastInteractionBody = tr("Deleted media");
|
||||
} else {
|
||||
lastInteractionBody = interaction.commit.value("displayName");
|
||||
}
|
||||
} else if (interaction.type == lrc::api::interaction::Type::CALL) {
|
||||
const auto isOutgoing = interaction.authorUri == accInfo.profileInfo.uri;
|
||||
lastInteractionBody = interaction::getCallInteractionString(isOutgoing, interaction);
|
||||
|
||||
2
src/app/js/.clang-format
Normal file
2
src/app/js/.clang-format
Normal file
@ -0,0 +1,2 @@
|
||||
Language: JavaScript
|
||||
BasedOnStyle: Google
|
||||
279
src/app/js/markdownedition.js
Normal file
279
src/app/js/markdownedition.js
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// This file contains the functions that allow the user to format the text in
|
||||
// the message bar by adding bold, italic, underline, strikethrough, ordered
|
||||
// list, and unordered list styles.
|
||||
|
||||
function isStyle(ta, text, char1, char2) {
|
||||
const start = ta.selectionStart;
|
||||
const end = ta.selectionEnd;
|
||||
|
||||
if (char1 === '**') {
|
||||
return isStarStyle(ta, text, 'bold');
|
||||
}
|
||||
if (char1 === '*') {
|
||||
return isStarStyle(ta, text, 'italic');
|
||||
}
|
||||
const selectedText = text.substring(start - char1.length, end + char2.length);
|
||||
return (selectedText.startsWith(char1) && selectedText.endsWith(char2));
|
||||
}
|
||||
|
||||
function isStarStyle(ta, text, type) {
|
||||
const selectionStart = ta.selectionStart;
|
||||
const selectionEnd = ta.selectionEnd;
|
||||
|
||||
let start = selectionStart;
|
||||
while (start > 0 && text[start - 1] === '*') {
|
||||
start--;
|
||||
}
|
||||
let end = selectionEnd;
|
||||
while (end < text.length && text[end] === '*') {
|
||||
end++;
|
||||
}
|
||||
const starCount = Math.min(selectionStart - start, end - selectionEnd);
|
||||
if (type === 'italic') {
|
||||
return starCount === 1 || starCount === 3;
|
||||
}
|
||||
return starCount === 2 || starCount === 3;
|
||||
}
|
||||
|
||||
function addStyle(ta, text, char1, char2) {
|
||||
const start = ta.selectionStart;
|
||||
const end = ta.selectionEnd;
|
||||
|
||||
// Get the selected text with markdown effect
|
||||
var selectedText = text.substring(start - char1.length, end + char2.length);
|
||||
|
||||
// If the selected text is already formatted with the given characters, remove
|
||||
// them
|
||||
if (isStyle(ta, text, char1, char2)) {
|
||||
selectedText = text.substring(start, end);
|
||||
ta.text = text.substring(0, start - char1.length) + selectedText +
|
||||
text.substring(end + char2.length);
|
||||
ta.selectText(start - char1.length, end - char1.length);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, add the formatting characters to the selected text
|
||||
ta.text = text.substring(0, start) + char1 + text.substring(start, end) +
|
||||
char2 + text.substring(end);
|
||||
ta.selectText(start + char1.length, end + char1.length);
|
||||
}
|
||||
|
||||
function isPrefixSyle(ta, message, delimiter, isOrderedList) {
|
||||
const selectionStart = ta.selectionStart;
|
||||
const selectionEnd = ta.selectionEnd;
|
||||
|
||||
// Represents all the selected lines
|
||||
var multilineSelection;
|
||||
var newPrefix;
|
||||
var newSuffix;
|
||||
var newStartPos;
|
||||
var newEndPos;
|
||||
function nextIndexOf(text, char1, startPos) {
|
||||
return text.indexOf(char1, startPos + 1);
|
||||
}
|
||||
|
||||
// Get the previous index of the multilineSelection text
|
||||
if (message[selectionStart] === '\n')
|
||||
newStartPos = message.lastIndexOf('\n', selectionStart - 1);
|
||||
else
|
||||
newStartPos = message.lastIndexOf('\n', selectionStart);
|
||||
|
||||
// Get the next index of the multilineSelection text
|
||||
if (message[selectionEnd] === '\n' || message[selectionEnd] === undefined)
|
||||
newEndPos = selectionEnd;
|
||||
else
|
||||
newEndPos = nextIndexOf(message, '\n', selectionEnd);
|
||||
|
||||
// If the text is empty
|
||||
if (newStartPos === -1) newStartPos = 0;
|
||||
newPrefix = message.slice(0, newStartPos);
|
||||
multilineSelection = message.slice(newStartPos, newEndPos);
|
||||
newSuffix = message.slice(newEndPos);
|
||||
var isFirstLineSelected =
|
||||
!multilineSelection.startsWith('\n') || newPrefix === '';
|
||||
var getDelimiter_counter = 1;
|
||||
function getDelimiter() {
|
||||
return `${getDelimiter_counter++}. `;
|
||||
}
|
||||
function getHasCurrentMarkdown() {
|
||||
const linesQuantity = (multilineSelection.match(/\n/g) || []).length;
|
||||
const newLinesWithDelimitersQuantity =
|
||||
(multilineSelection.match(new RegExp(`\n${delimiter}`, 'g')) ||
|
||||
[]).length;
|
||||
if (newLinesWithDelimitersQuantity === linesQuantity &&
|
||||
!isFirstLineSelected)
|
||||
return true;
|
||||
return linesQuantity === newLinesWithDelimitersQuantity &&
|
||||
multilineSelection.startsWith(delimiter);
|
||||
}
|
||||
function getHasCurrentMarkdownBullet() {
|
||||
const linesQuantity = (multilineSelection.match(/\n/g) || []).length;
|
||||
const newLinesWithDelimitersQuantity =
|
||||
(multilineSelection.match(/\n\d+\. /g) || []).length;
|
||||
if (newLinesWithDelimitersQuantity === linesQuantity &&
|
||||
!isFirstLineSelected)
|
||||
return true;
|
||||
return linesQuantity === newLinesWithDelimitersQuantity &&
|
||||
(/^\d\. /).test(multilineSelection);
|
||||
}
|
||||
var newValue;
|
||||
var newStart;
|
||||
var newEnd;
|
||||
var count;
|
||||
var startPos;
|
||||
var multilineSelectionLength;
|
||||
if (!isOrderedList) {
|
||||
return getHasCurrentMarkdown();
|
||||
} else {
|
||||
return getHasCurrentMarkdownBullet();
|
||||
}
|
||||
}
|
||||
|
||||
function addPrefixStyle(ta, message, delimiter, isOrderedList) {
|
||||
const selectionStart = ta.selectionStart;
|
||||
const selectionEnd = ta.selectionEnd;
|
||||
|
||||
// Represents all the selected lines
|
||||
var multilineSelection;
|
||||
var newPrefix;
|
||||
var newSuffix;
|
||||
var newStartPos;
|
||||
var newEndPos;
|
||||
function nextIndexOf(text, char1, startPos) {
|
||||
return text.indexOf(char1, startPos + 1);
|
||||
}
|
||||
|
||||
// Get the previous index of the multilineSelection text
|
||||
if (message[selectionStart] === '\n')
|
||||
newStartPos = message.lastIndexOf('\n', selectionStart - 1);
|
||||
else
|
||||
newStartPos = message.lastIndexOf('\n', selectionStart);
|
||||
|
||||
// Get the next index of the multilineSelection text
|
||||
if (message[selectionEnd] === '\n' || message[selectionEnd] === undefined)
|
||||
newEndPos = selectionEnd;
|
||||
else
|
||||
newEndPos = nextIndexOf(message, '\n', selectionEnd);
|
||||
|
||||
// If the text is empty
|
||||
if (newStartPos === -1) newStartPos = 0;
|
||||
newPrefix = message.slice(0, newStartPos);
|
||||
multilineSelection = message.slice(newStartPos, newEndPos);
|
||||
newSuffix = message.slice(newEndPos);
|
||||
var isFirstLineSelected =
|
||||
!multilineSelection.startsWith('\n') || newPrefix === '';
|
||||
var getDelimiter_counter = 1;
|
||||
function getDelimiter() {
|
||||
return `${getDelimiter_counter++}. `;
|
||||
}
|
||||
function getHasCurrentMarkdown() {
|
||||
const linesQuantity = (multilineSelection.match(/\n/g) || []).length;
|
||||
const newLinesWithDelimitersQuantity =
|
||||
(multilineSelection.match(new RegExp(`\n${delimiter}`, 'g')) ||
|
||||
[]).length;
|
||||
if (newLinesWithDelimitersQuantity === linesQuantity &&
|
||||
!isFirstLineSelected)
|
||||
return true;
|
||||
return linesQuantity === newLinesWithDelimitersQuantity &&
|
||||
multilineSelection.startsWith(delimiter);
|
||||
}
|
||||
function getHasCurrentMarkdownBullet() {
|
||||
const linesQuantity = (multilineSelection.match(/\n/g) || []).length;
|
||||
const newLinesWithDelimitersQuantity =
|
||||
(multilineSelection.match(/\n\d+\. /g) || []).length;
|
||||
if (newLinesWithDelimitersQuantity === linesQuantity &&
|
||||
!isFirstLineSelected)
|
||||
return true;
|
||||
return linesQuantity === newLinesWithDelimitersQuantity &&
|
||||
(/^\d\. /).test(multilineSelection);
|
||||
}
|
||||
var newValue;
|
||||
var newStart;
|
||||
var newEnd;
|
||||
var count;
|
||||
var startPos;
|
||||
var multilineSelectionLength;
|
||||
if (!isOrderedList) {
|
||||
if (getHasCurrentMarkdown()) {
|
||||
// Clear first line from delimiter
|
||||
if (isFirstLineSelected)
|
||||
multilineSelection = multilineSelection.slice(delimiter.length);
|
||||
newValue = newPrefix +
|
||||
multilineSelection.replace(new RegExp(`\n${delimiter}`, 'g'), '\n') +
|
||||
newSuffix;
|
||||
count = 0;
|
||||
if (isFirstLineSelected) count++;
|
||||
count += (multilineSelection.match(/\n/g) || []).length;
|
||||
newStart = Math.max(selectionStart - delimiter.length, 0);
|
||||
newEnd = Math.max(selectionEnd - (delimiter.length * count), 0);
|
||||
} else {
|
||||
newValue = newPrefix +
|
||||
multilineSelection.replace(/\n/g, `\n${delimiter}`) + newSuffix;
|
||||
count = 0;
|
||||
if (isFirstLineSelected) {
|
||||
newValue = delimiter + newValue;
|
||||
count++;
|
||||
}
|
||||
count += (multilineSelection.match(new RegExp('\\n', 'g')) || []).length;
|
||||
newStart = selectionStart + delimiter.length;
|
||||
newEnd = selectionEnd + (delimiter.length * count);
|
||||
}
|
||||
} else if (getHasCurrentMarkdownBullet()) {
|
||||
if (message[selectionStart] === '\n')
|
||||
startPos = message.lastIndexOf('\n', selectionStart - 1) + 1;
|
||||
else
|
||||
startPos = message.lastIndexOf('\n', selectionStart) + 1;
|
||||
newStart = startPos;
|
||||
multilineSelection = multilineSelection.replace(/^\d+\.\s/gm, '');
|
||||
newValue = newPrefix + multilineSelection + newSuffix;
|
||||
multilineSelectionLength = multilineSelection.length;
|
||||
|
||||
// If the first line is not selected, we need to remove the first "\n" of
|
||||
// multilineSelection
|
||||
if (newStart) multilineSelectionLength = multilineSelection.length - 1;
|
||||
newEnd = Math.max(newStart + multilineSelectionLength, 0);
|
||||
} else {
|
||||
if (message[selectionStart] === '\n')
|
||||
startPos = message.lastIndexOf('\n', selectionStart - 1) + 1;
|
||||
else
|
||||
startPos = message.lastIndexOf('\n', selectionStart) + 1;
|
||||
newStart = startPos;
|
||||
|
||||
// If no text is selected
|
||||
if (selectionStart === selectionEnd) newStart = newStart + 3;
|
||||
if (isFirstLineSelected)
|
||||
multilineSelection = getDelimiter() + multilineSelection;
|
||||
const selectionArr = Array.from(multilineSelection);
|
||||
for (var i = 0; i < selectionArr.length; i++) {
|
||||
if (selectionArr[i] === '\n') selectionArr[i] = `\n${getDelimiter()}`;
|
||||
}
|
||||
multilineSelection = selectionArr.join('');
|
||||
newValue = newPrefix + multilineSelection + newSuffix;
|
||||
multilineSelectionLength = multilineSelection.length;
|
||||
|
||||
// If the first line is not selected, we meed to remove the first "\n" of
|
||||
// multilineSelection
|
||||
if (startPos) multilineSelectionLength = multilineSelection.length - 1;
|
||||
newEnd = Math.max(startPos + multilineSelectionLength, 0);
|
||||
}
|
||||
|
||||
ta.text = newValue;
|
||||
ta.selectText(newStart, newEnd);
|
||||
}
|
||||
@ -43,9 +43,8 @@ LRCInstance::LRCInstance(const QString& updateUrl,
|
||||
muteDaemon_ = muteDaemon;
|
||||
threadPool_->setMaxThreadCount(1);
|
||||
|
||||
connect(this, &LRCInstance::currentAccountIdChanged, [this] {
|
||||
// save to config, editing the accountlistmodel's underlying data
|
||||
accountModel().setTopAccount(currentAccountId_);
|
||||
// Update the current account when the account list changes.
|
||||
connect(&accountModel(), &AccountModel::accountsReordered, this, [this] {
|
||||
Q_EMIT accountListChanged();
|
||||
|
||||
profile::Info profileInfo;
|
||||
@ -62,6 +61,11 @@ LRCInstance::LRCInstance(const QString& updateUrl,
|
||||
set_currentAccountAvatarSet(!profileInfo.avatar.isEmpty());
|
||||
});
|
||||
|
||||
connect(this, &LRCInstance::currentAccountIdChanged, [this] {
|
||||
// This will trigger `AccountModel::accountsReordered`.
|
||||
accountModel().setTopAccount(currentAccountId_);
|
||||
});
|
||||
|
||||
connect(&accountModel(), &AccountModel::profileUpdated, this, [this](const QString& id) {
|
||||
if (id != currentAccountId_)
|
||||
return;
|
||||
|
||||
@ -22,6 +22,7 @@ import Qt5Compat.GraphicalEffects
|
||||
import net.jami.Models 1.1
|
||||
import net.jami.Adapters 1.1
|
||||
import net.jami.Constants 1.1
|
||||
import net.jami.Helpers 1.1
|
||||
import "../../commoncomponents"
|
||||
|
||||
BaseModalDialog {
|
||||
@ -63,23 +64,21 @@ BaseModalDialog {
|
||||
source: JamiTheme.darkTheme ? JamiResources.logo_jami_standard_coul_white_svg : JamiResources.logo_jami_standard_coul_svg
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: JamiTheme.backgroundRectangleColor
|
||||
Control {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
radius: 5
|
||||
|
||||
ColumnLayout {
|
||||
id: sloganLayout
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
background: Rectangle {
|
||||
color: JamiTheme.backgroundRectangleColor
|
||||
radius: 5
|
||||
}
|
||||
|
||||
padding: 10
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 4
|
||||
TextEdit {
|
||||
id: jamiSlogansText
|
||||
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.margins: 10
|
||||
Layout.bottomMargin: 0
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: JamiTheme.menuFontSize
|
||||
@ -100,23 +99,18 @@ BaseModalDialog {
|
||||
}
|
||||
}
|
||||
TextEdit {
|
||||
id: jamiVersionText
|
||||
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.margins: 10
|
||||
Layout.topMargin: 0
|
||||
Layout.maximumWidth: JamiTheme.preferredDialogWidth - 2*JamiTheme.preferredMarginSize
|
||||
|
||||
font.pixelSize: JamiTheme.textFontSize
|
||||
padding: 0
|
||||
text: JamiStrings.version + ": " + UtilsAdapter.getVersionStr()
|
||||
readonly property bool isBeta: AppVersionManager.isCurrentVersionBeta()
|
||||
text: JamiStrings.buildID + ": " + UtilsAdapter.getBuildIDStr() + "\n" +
|
||||
JamiStrings.version + ": " + (isBeta ? "(Beta) " : "") + UtilsAdapter.getVersionStr()
|
||||
|
||||
selectByMouse: true
|
||||
readOnly: true
|
||||
|
||||
color: JamiTheme.faddedFontColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,24 +34,6 @@ Label {
|
||||
|
||||
property bool inSettings: viewCoordinator.currentViewName === "SettingsView"
|
||||
|
||||
// TODO: remove these refresh hacks use QAbstractItemModels correctly
|
||||
Connections {
|
||||
target: AccountAdapter
|
||||
|
||||
function onAccountStatusChanged(accountId) {
|
||||
AccountListModel.reset();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: LRCInstance
|
||||
|
||||
function onAccountListChanged() {
|
||||
root.update();
|
||||
AccountListModel.reset();
|
||||
}
|
||||
}
|
||||
|
||||
function togglePopup() {
|
||||
if (root.popup.opened) {
|
||||
root.popup.close();
|
||||
|
||||
@ -60,23 +60,6 @@ Popup {
|
||||
|
||||
property bool inSettings: viewCoordinator.currentViewName === "SettingsView"
|
||||
|
||||
// TODO: remove these refresh hacks use QAbstractItemModels correctly
|
||||
Connections {
|
||||
target: AccountAdapter
|
||||
|
||||
function onAccountStatusChanged(accountId) {
|
||||
AccountListModel.reset();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: LRCInstance
|
||||
|
||||
function onAccountListChanged() {
|
||||
AccountListModel.reset();
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: mainLayout
|
||||
anchors.fill: parent
|
||||
@ -257,11 +240,6 @@ Popup {
|
||||
color: JamiTheme.smartListHoveredColor
|
||||
}
|
||||
|
||||
// fake footer item as workaround for Qt 5.15 bug
|
||||
// https://bugreports.qt.io/browse/QTBUG-85302
|
||||
// don't use the clip trick and footer item overlay
|
||||
// explained here https://stackoverflow.com/a/64625149
|
||||
// as it causes other complexities in handling the drop shadow
|
||||
ItemDelegate {
|
||||
id: addAccountItem
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 35
|
||||
|
||||
placeHolderText: JamiStrings.addParticipant
|
||||
placeHolderText: JamiStrings.inviteMember
|
||||
|
||||
onSearchBarTextChanged: function(text){
|
||||
ContactAdapter.setSearchFilter(text);
|
||||
|
||||
@ -315,7 +315,7 @@ Control {
|
||||
checkable: true
|
||||
icon.source: checked ? JamiResources.videocam_off_24dp_svg : JamiResources.videocam_24dp_svg
|
||||
icon.color: checked ? "red" : "white"
|
||||
text: !checked ? JamiStrings.muteCamera : JamiStrings.unmuteCamera
|
||||
text: !checked ? JamiStrings.stopCamera : JamiStrings.startCamera
|
||||
checked: !CurrentCall.isCapturing
|
||||
property var menuAction: videoInputMenuAction
|
||||
enabled: CurrentAccount.videoEnabled_Video
|
||||
@ -339,7 +339,7 @@ Control {
|
||||
onTriggered: root.addToConferenceClicked()
|
||||
icon.source: JamiResources.add_people_black_24dp_svg
|
||||
icon.color: "white"
|
||||
text: JamiStrings.addParticipants
|
||||
text: JamiStrings.inviteMembers
|
||||
enabled: CurrentCall.isModerator && !CurrentCall.isSIP
|
||||
onEnabledChanged: CallOverlayModel.setEnabled(this, addPersonAction.enabled)
|
||||
},
|
||||
@ -437,7 +437,7 @@ Control {
|
||||
onTriggered: root.pluginsClicked()
|
||||
icon.source: JamiResources.plugins_24dp_svg
|
||||
icon.color: "white"
|
||||
text: JamiStrings.viewPlugin
|
||||
text: JamiStrings.viewExtension
|
||||
enabled: PluginAdapter.callMediaHandlersListCount
|
||||
onEnabledChanged: CallOverlayModel.setEnabled(this, pluginsAction.enabled)
|
||||
},
|
||||
|
||||
@ -133,6 +133,10 @@ Rectangle {
|
||||
target: CurrentConversation
|
||||
|
||||
function onIdChanged() {
|
||||
console.log(CurrentConversation.id);
|
||||
if (width < JamiTheme.mainViewMinWidth + extrasPanel.width) {
|
||||
extrasPanel.visible = false;
|
||||
}
|
||||
if (!chatViewHeader.interactionButtonsVisibility)
|
||||
extrasPanel.closePanel();
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ Rectangle {
|
||||
mirror: UtilsAdapter.isRTL
|
||||
|
||||
source: JamiResources.back_24dp_svg
|
||||
toolTipText: CurrentConversation.inCall ? JamiStrings.backCall : JamiStrings.hideChat
|
||||
toolTipText: CurrentConversation.inCall ? JamiStrings.returnToCall : JamiStrings.hideChat
|
||||
|
||||
onClicked: root.backClicked()
|
||||
}
|
||||
@ -147,7 +147,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
id: startAAudioCallButton
|
||||
id: startAudioCallButton
|
||||
|
||||
visible: interactionButtonsVisibility &&
|
||||
(!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm))
|
||||
@ -158,7 +158,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
id: startAVideoCallButton
|
||||
id: startVideoCallButton
|
||||
|
||||
visible: interactionButtonsVisibility &&
|
||||
CurrentAccount.videoEnabled_Video &&
|
||||
@ -170,23 +170,23 @@ Rectangle {
|
||||
}
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
id: addParticipantsButton
|
||||
id: inviteMembersButton
|
||||
|
||||
checkable: true
|
||||
checked: extrasPanel.isOpen(ChatView.AddMemberPanel)
|
||||
visible: interactionButtonsVisibility && addMemberVisibility
|
||||
source: JamiResources.add_people_24dp_svg
|
||||
toolTipText: JamiStrings.addParticipants
|
||||
toolTipText: JamiStrings.inviteMembers
|
||||
|
||||
onClicked: extrasPanel.switchToPanel(ChatView.AddMemberPanel)
|
||||
}
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
id: selectPluginButton
|
||||
id: selectExtensionsButton
|
||||
|
||||
visible: PluginAdapter.chatHandlersListCount && interactionButtonsVisibility
|
||||
source: JamiResources.plugins_24dp_svg
|
||||
toolTipText: JamiStrings.showPlugins
|
||||
toolTipText: JamiStrings.showExtensions
|
||||
|
||||
onClicked: pluginSelector()
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ BaseModalDialog {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 35
|
||||
|
||||
placeHolderText: type === ContactList.TRANSFER ? JamiStrings.transferTo : JamiStrings.addParticipant
|
||||
placeHolderText: type === ContactList.TRANSFER ? JamiStrings.transferTo : JamiStrings.inviteMember
|
||||
|
||||
onSearchBarTextChanged: function(text){
|
||||
ContactAdapter.setSearchFilter(text);
|
||||
|
||||
138
src/app/mainview/components/ConversationPickerItemDelegate.qml
Normal file
138
src/app/mainview/components/ConversationPickerItemDelegate.qml
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Savoir-faire Linux Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import net.jami.Adapters 1.1
|
||||
import net.jami.Constants 1.1
|
||||
import net.jami.Enums 1.1
|
||||
import net.jami.Models 1.1
|
||||
import "../../commoncomponents"
|
||||
|
||||
ItemDelegate {
|
||||
id: root
|
||||
|
||||
width: ListView.view.width
|
||||
height: JamiTheme.smartListItemHeight
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 15
|
||||
anchors.rightMargin: 15
|
||||
spacing: 10
|
||||
|
||||
ConversationAvatar {
|
||||
id: avatar
|
||||
objectName: "smartlistItemDelegateAvatar"
|
||||
|
||||
imageId: UID
|
||||
presenceStatus: Presence
|
||||
showPresenceIndicator: Presence !== undefined ? Presence : false
|
||||
|
||||
Layout.preferredWidth: JamiTheme.smartListAvatarSize
|
||||
Layout.preferredHeight: JamiTheme.smartListAvatarSize
|
||||
|
||||
Rectangle {
|
||||
id: overlayHighlighted
|
||||
visible: highlighted
|
||||
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(0, 0, 0, 0.5)
|
||||
radius: JamiTheme.smartListAvatarSize / 2
|
||||
|
||||
Image {
|
||||
id: highlightedImage
|
||||
|
||||
width: JamiTheme.smartListAvatarSize / 2
|
||||
height: JamiTheme.smartListAvatarSize / 2
|
||||
anchors.centerIn: parent
|
||||
|
||||
layer {
|
||||
enabled: true
|
||||
effect: ColorOverlay {
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
source: JamiResources.check_black_24dp_svg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
spacing: 0
|
||||
|
||||
// best name
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 20
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideMiddle
|
||||
text: Title === undefined ? "" : Title
|
||||
textFormat: TextEdit.PlainText
|
||||
font.pointSize: JamiTheme.mediumFontSize
|
||||
font.weight: UnreadMessagesCount ? Font.Bold : Font.Normal
|
||||
color: JamiTheme.textColor
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 20
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: JamiStrings.blocked
|
||||
textFormat: TextEdit.PlainText
|
||||
visible: IsBanned
|
||||
font.pointSize: JamiTheme.mediumFontSize
|
||||
font.weight: Font.Bold
|
||||
color: JamiTheme.textColor
|
||||
}
|
||||
}
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: Title === undefined ? "" : Title
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: {
|
||||
if (root.pressed || root.highlighted)
|
||||
return JamiTheme.smartListSelectedColor;
|
||||
else if (root.hovered)
|
||||
return JamiTheme.smartListHoveredColor;
|
||||
else
|
||||
return "transparent";
|
||||
}
|
||||
}
|
||||
|
||||
highlighted: {
|
||||
return mainMenu.selectedUids.includes(UID);
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
const currentSelectedUids = mainMenu.selectedUids;
|
||||
if (currentSelectedUids.includes(UID)) {
|
||||
mainMenu.selectedUids = currentSelectedUids.filter(uid => uid !== UID);
|
||||
} else {
|
||||
mainMenu.selectedUids = currentSelectedUids.concat(UID);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -43,7 +43,7 @@ ContextMenuAutoLoader {
|
||||
|
||||
property list<GeneralMenuItem> menuItems: [
|
||||
GeneralMenuItem {
|
||||
id: startVideoCallItem
|
||||
id: startVideoCall
|
||||
|
||||
canTrigger: CurrentAccount.videoEnabled_Video && !hasCall && !readOnly
|
||||
itemName: JamiStrings.startVideoCall
|
||||
|
||||
@ -60,7 +60,7 @@ JamiListView {
|
||||
|
||||
property var messageListModel: MessagesAdapter.mediaMessageListModel
|
||||
readonly property int documentType: Interaction.Type.DATA_TRANSFER
|
||||
readonly property int transferFinishedType: Interaction.Status.TRANSFER_FINISHED
|
||||
readonly property int transferFinishedType: Interaction.TransferStatus.TRANSFER_FINISHED
|
||||
readonly property int transferSuccesType: Interaction.Status.SUCCESS
|
||||
|
||||
onMessageListModelChanged: sourceModel = root.visible && messageListModel ? messageListModel : null
|
||||
|
||||
@ -37,27 +37,27 @@ Window {
|
||||
id: keyboardGeneralShortcutsModel
|
||||
|
||||
ListElement {
|
||||
shortcut: "Ctrl + J"
|
||||
shortcut: "Ctrl+J"
|
||||
description: qsTr("Open account list")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + L"
|
||||
shortcut: "Ctrl+L"
|
||||
description: qsTr("Focus conversations list")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + R"
|
||||
shortcut: "Ctrl+R"
|
||||
description: qsTr("Requests list")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + ↑"
|
||||
shortcut: "Ctrl+↑"
|
||||
description: qsTr("Previous conversation")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + ↓"
|
||||
shortcut: "Ctrl+↓"
|
||||
description: qsTr("Next conversation")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + F"
|
||||
shortcut: "Ctrl+F"
|
||||
description: qsTr("Search bar")
|
||||
}
|
||||
ListElement {
|
||||
@ -65,15 +65,15 @@ Window {
|
||||
description: qsTr("Full screen")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + +"
|
||||
shortcut: "Ctrl++"
|
||||
description: qsTr("Increase font size")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + -"
|
||||
shortcut: "Ctrl+-"
|
||||
description: qsTr("Decrease font size")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + 0"
|
||||
shortcut: "Ctrl+0"
|
||||
description: qsTr("Reset font size")
|
||||
}
|
||||
},
|
||||
@ -81,33 +81,13 @@ Window {
|
||||
id: keyboardConversationShortcutsModel
|
||||
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Shift + C"
|
||||
description: qsTr("Start an audio call")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Shift + X"
|
||||
description: qsTr("Start a video call")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Shift + L"
|
||||
description: qsTr("Clear history")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Shift + F"
|
||||
description: qsTr("Search messages/files")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Shift + B"
|
||||
description: qsTr("Block contact")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Shift + Delete"
|
||||
description: qsTr("Remove conversation")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Shift + A"
|
||||
shortcut: "Ctrl+Shift+A"
|
||||
description: qsTr("Accept contact request")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl+Shift+F"
|
||||
description: qsTr("Search messages/files")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "↑"
|
||||
description: qsTr("Edit last message")
|
||||
@ -116,50 +96,41 @@ Window {
|
||||
shortcut: "Esc"
|
||||
description: qsTr("Cancel message edition")
|
||||
}
|
||||
},
|
||||
ListModel {
|
||||
id: keyboardSettingsShortcutsModel
|
||||
|
||||
ListElement {
|
||||
shortcut: "Ctrl + M"
|
||||
description: qsTr("Media settings")
|
||||
shortcut: "Ctrl+Shift+L"
|
||||
description: qsTr("Clear history")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + G"
|
||||
description: qsTr("General settings")
|
||||
shortcut: "Ctrl+Shift+B"
|
||||
description: qsTr("Block contact")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Alt + I"
|
||||
description: qsTr("Account settings")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + P"
|
||||
description: qsTr("Plugin settings")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Shift + N"
|
||||
description: qsTr("Open account creation wizard")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "F10"
|
||||
shortcut2: ""
|
||||
description: qsTr("Open keyboard shortcut table")
|
||||
shortcut: "Ctrl+Shift+Delete"
|
||||
description: qsTr("Leave conversation")
|
||||
}
|
||||
},
|
||||
ListModel {
|
||||
id: keyboardCallsShortcutsModel
|
||||
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Y"
|
||||
description: qsTr("Answer an incoming call")
|
||||
shortcut: "Ctrl+Shift+C"
|
||||
description: qsTr("Start audio call")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + D"
|
||||
shortcut: "Ctrl+Shift+X"
|
||||
description: qsTr("Start video call")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl+Y"
|
||||
description: qsTr("Answer incoming call")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl+D"
|
||||
description: qsTr("End call")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Shift + D"
|
||||
description: qsTr("Decline the call request")
|
||||
shortcut: "Ctrl+Shift+D"
|
||||
description: qsTr("Decline call request")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "M"
|
||||
@ -170,7 +141,7 @@ Window {
|
||||
description: qsTr("Stop camera")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Mouse middle click"
|
||||
shortcut: "Ctrl+Mouse middle click"
|
||||
description: qsTr("Take tile screenshot")
|
||||
}
|
||||
},
|
||||
@ -178,48 +149,77 @@ Window {
|
||||
id: keyboardMarkdownShortcutsModel
|
||||
|
||||
ListElement {
|
||||
shortcut: "Ctrl + B"
|
||||
shortcut: "Ctrl+B"
|
||||
description: qsTr("Bold")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + I"
|
||||
shortcut: "Ctrl+I"
|
||||
description: qsTr("Italic")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Shift + Alt + X"
|
||||
shortcut: "Shift+Alt+X"
|
||||
description: qsTr("Strikethrough")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Alt + H"
|
||||
shortcut: "Ctrl+Alt+H"
|
||||
description: qsTr("Heading")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Alt + K"
|
||||
shortcut: "Ctrl+Alt+K"
|
||||
description: qsTr("Link")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl + Alt + C"
|
||||
shortcut: "Ctrl+Alt+C"
|
||||
description: qsTr("Code")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Shift + Alt + 9"
|
||||
shortcut: "Shift+Alt+9"
|
||||
description: qsTr("Quote")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Shift + Alt + 8"
|
||||
shortcut: "Shift+Alt+8"
|
||||
description: qsTr("Unordered list")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Shift + Alt + 7"
|
||||
shortcut: "Shift+Alt+7"
|
||||
description: qsTr("Ordered list")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Shift + Alt + T"
|
||||
description: qsTr("Show formatting")
|
||||
shortcut: "Shift+Alt+T"
|
||||
description: qsTr("Show/hide formatting")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Shift + Alt + P"
|
||||
description: qsTr("Show preview")
|
||||
shortcut: "Shift+Alt+P"
|
||||
description: qsTr("Show preview/Continue editing")
|
||||
}
|
||||
},
|
||||
ListModel {
|
||||
id: keyboardSettingsShortcutsModel
|
||||
|
||||
ListElement {
|
||||
shortcut: "Ctrl+Alt+I"
|
||||
description: qsTr("Open account settings")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl+G"
|
||||
description: qsTr("Open general settings")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl+M"
|
||||
description: qsTr("Open media settings")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl+E"
|
||||
description: qsTr("Open extensions settings")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "Ctrl+Shift+N"
|
||||
description: qsTr("Open account creation wizard")
|
||||
}
|
||||
ListElement {
|
||||
shortcut: "F10"
|
||||
shortcut2: ""
|
||||
description: qsTr("View keyboard shortcuts")
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -302,7 +302,7 @@ Window {
|
||||
focus: true
|
||||
|
||||
Repeater {
|
||||
model: [JamiStrings.generalSettingsTitle, JamiStrings.conversationKeyboardShortcuts, JamiStrings.callKeyboardShortcuts, JamiStrings.settings, JamiStrings.markdownKeyboardShortcuts]
|
||||
model: [JamiStrings.generalSettingsTitle, JamiStrings.conversationKeyboardShortcuts, JamiStrings.callKeyboardShortcuts, JamiStrings.markdownKeyboardShortcuts, JamiStrings.settings]
|
||||
|
||||
TabButton {
|
||||
id: tabButton
|
||||
|
||||
@ -25,6 +25,8 @@ import net.jami.Enums 1.1
|
||||
import net.jami.Constants 1.1
|
||||
import "../../commoncomponents"
|
||||
|
||||
import "qrc:/js/markdownedition.js" as MDE
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
@ -358,231 +360,6 @@ RowLayout {
|
||||
id: listViewTypo
|
||||
height: JamiTheme.chatViewFooterButtonSize
|
||||
|
||||
function isStyle(text, start, end, char1, char2, regex) {
|
||||
if (char1 === "**") {
|
||||
return isStarStyle(text, start, end, "bold");
|
||||
}
|
||||
if (char1 === "*") {
|
||||
return isStarStyle(text, start, end, "italic");
|
||||
}
|
||||
var selectedText = text.substring(start - char1.length, end + char2.length);
|
||||
return (selectedText.startsWith(char1) && selectedText.endsWith(char2));
|
||||
}
|
||||
|
||||
function isStarStyle(text, selectionStart, selectionEnd, type) {
|
||||
let start = selectionStart;
|
||||
while (start > 0 && text[start - 1] === "*") {
|
||||
start--;
|
||||
}
|
||||
let end = selectionEnd;
|
||||
while (end < text.length && text[end] === "*") {
|
||||
end++;
|
||||
}
|
||||
const starCount = Math.min(selectionStart - start, end - selectionEnd);
|
||||
if (type === "italic") {
|
||||
return starCount === 1 || starCount === 3;
|
||||
}
|
||||
return starCount === 2 || starCount === 3;
|
||||
}
|
||||
|
||||
function addStyle(text, start, end, char1, char2, regex) {
|
||||
// get the selected text with markdown effect
|
||||
var selectedText = text.substring(start - char1.length, end + char2.length);
|
||||
if (isStyle(text, start, end, char1, char2, regex)) {
|
||||
// If the selected text is already formatted with the given characters, remove them
|
||||
selectedText = text.substring(start, end);
|
||||
root.text = text.substring(0, start - char1.length) + selectedText + text.substring(end + char2.length);
|
||||
messageBarTextArea.selectText(start - char1.length, end - char1.length);
|
||||
} else {
|
||||
// Otherwise, add the formatting characters to the selected text
|
||||
root.text = text.substring(0, start) + char1 + text.substring(start, end) + char2 + text.substring(end);
|
||||
messageBarTextArea.selectText(start + char1.length, end + char1.length);
|
||||
}
|
||||
}
|
||||
|
||||
function isPrefixSyle(message, selectionStart, selectionEnd, delimiter, isOrderedList) {
|
||||
//represents all the selected lines
|
||||
var multilineSelection;
|
||||
var newPrefix;
|
||||
var newSuffix;
|
||||
var newStartPos;
|
||||
var newEndPos;
|
||||
function nextIndexOf(text, char1, startPos) {
|
||||
return text.indexOf(char1, startPos + 1);
|
||||
}
|
||||
|
||||
//get the previous index of the multilineSelection text
|
||||
if (message[selectionStart] === "\n")
|
||||
newStartPos = message.lastIndexOf('\n', selectionStart - 1);
|
||||
else
|
||||
newStartPos = message.lastIndexOf('\n', selectionStart);
|
||||
|
||||
//get the next index of the multilineSelection text
|
||||
if (message[selectionEnd] === "\n" || message[selectionEnd] === undefined)
|
||||
newEndPos = selectionEnd;
|
||||
else
|
||||
newEndPos = nextIndexOf(message, "\n", selectionEnd);
|
||||
|
||||
//if the text is empty
|
||||
if (newStartPos === -1)
|
||||
newStartPos = 0;
|
||||
newPrefix = message.slice(0, newStartPos);
|
||||
multilineSelection = message.slice(newStartPos, newEndPos);
|
||||
newSuffix = message.slice(newEndPos);
|
||||
var isFirstLineSelected = !multilineSelection.startsWith('\n') || newPrefix === "";
|
||||
var getDelimiter_counter = 1;
|
||||
function getDelimiter() {
|
||||
return `${getDelimiter_counter++}. `;
|
||||
}
|
||||
function getHasCurrentMarkdown() {
|
||||
const linesQuantity = (multilineSelection.match(/\n/g) || []).length;
|
||||
const newLinesWithDelimitersQuantity = (multilineSelection.match(new RegExp(`\n${delimiter}`, 'g')) || []).length;
|
||||
if (newLinesWithDelimitersQuantity === linesQuantity && !isFirstLineSelected)
|
||||
return true;
|
||||
return linesQuantity === newLinesWithDelimitersQuantity && multilineSelection.startsWith(delimiter);
|
||||
}
|
||||
function getHasCurrentMarkdownBullet() {
|
||||
const linesQuantity = (multilineSelection.match(/\n/g) || []).length;
|
||||
const newLinesWithDelimitersQuantity = (multilineSelection.match(/\n\d+\. /g) || []).length;
|
||||
if (newLinesWithDelimitersQuantity === linesQuantity && !isFirstLineSelected)
|
||||
return true;
|
||||
return linesQuantity === newLinesWithDelimitersQuantity && (/^\d\. /).test(multilineSelection);
|
||||
}
|
||||
var newValue;
|
||||
var newStart;
|
||||
var newEnd;
|
||||
var count;
|
||||
var startPos;
|
||||
var multilineSelectionLength;
|
||||
if (!isOrderedList) {
|
||||
return getHasCurrentMarkdown();
|
||||
} else {
|
||||
return getHasCurrentMarkdownBullet();
|
||||
}
|
||||
}
|
||||
|
||||
function addPrefixStyle(message, selectionStart, selectionEnd, delimiter, isOrderedList) {
|
||||
//represents all the selected lines
|
||||
var multilineSelection;
|
||||
var newPrefix;
|
||||
var newSuffix;
|
||||
var newStartPos;
|
||||
var newEndPos;
|
||||
function nextIndexOf(text, char1, startPos) {
|
||||
return text.indexOf(char1, startPos + 1);
|
||||
}
|
||||
|
||||
//get the previous index of the multilineSelection text
|
||||
if (message[selectionStart] === "\n")
|
||||
newStartPos = message.lastIndexOf('\n', selectionStart - 1);
|
||||
else
|
||||
newStartPos = message.lastIndexOf('\n', selectionStart);
|
||||
|
||||
//get the next index of the multilineSelection text
|
||||
if (message[selectionEnd] === "\n" || message[selectionEnd] === undefined)
|
||||
newEndPos = selectionEnd;
|
||||
else
|
||||
newEndPos = nextIndexOf(message, "\n", selectionEnd);
|
||||
|
||||
//if the text is empty
|
||||
if (newStartPos === -1)
|
||||
newStartPos = 0;
|
||||
newPrefix = message.slice(0, newStartPos);
|
||||
multilineSelection = message.slice(newStartPos, newEndPos);
|
||||
newSuffix = message.slice(newEndPos);
|
||||
var isFirstLineSelected = !multilineSelection.startsWith('\n') || newPrefix === "";
|
||||
var getDelimiter_counter = 1;
|
||||
function getDelimiter() {
|
||||
return `${getDelimiter_counter++}. `;
|
||||
}
|
||||
function getHasCurrentMarkdown() {
|
||||
const linesQuantity = (multilineSelection.match(/\n/g) || []).length;
|
||||
const newLinesWithDelimitersQuantity = (multilineSelection.match(new RegExp(`\n${delimiter}`, 'g')) || []).length;
|
||||
if (newLinesWithDelimitersQuantity === linesQuantity && !isFirstLineSelected)
|
||||
return true;
|
||||
return linesQuantity === newLinesWithDelimitersQuantity && multilineSelection.startsWith(delimiter);
|
||||
}
|
||||
function getHasCurrentMarkdownBullet() {
|
||||
const linesQuantity = (multilineSelection.match(/\n/g) || []).length;
|
||||
const newLinesWithDelimitersQuantity = (multilineSelection.match(/\n\d+\. /g) || []).length;
|
||||
if (newLinesWithDelimitersQuantity === linesQuantity && !isFirstLineSelected)
|
||||
return true;
|
||||
return linesQuantity === newLinesWithDelimitersQuantity && (/^\d\. /).test(multilineSelection);
|
||||
}
|
||||
var newValue;
|
||||
var newStart;
|
||||
var newEnd;
|
||||
var count;
|
||||
var startPos;
|
||||
var multilineSelectionLength;
|
||||
if (!isOrderedList) {
|
||||
if (getHasCurrentMarkdown()) {
|
||||
|
||||
// clear first line from delimiter
|
||||
if (isFirstLineSelected)
|
||||
multilineSelection = multilineSelection.slice(delimiter.length);
|
||||
newValue = newPrefix + multilineSelection.replace(new RegExp(`\n${delimiter}`, 'g'), '\n') + newSuffix;
|
||||
count = 0;
|
||||
if (isFirstLineSelected)
|
||||
count++;
|
||||
count += (multilineSelection.match(/\n/g) || []).length;
|
||||
newStart = Math.max(selectionStart - delimiter.length, 0);
|
||||
newEnd = Math.max(selectionEnd - (delimiter.length * count), 0);
|
||||
} else {
|
||||
newValue = newPrefix + multilineSelection.replace(/\n/g, `\n${delimiter}`) + newSuffix;
|
||||
count = 0;
|
||||
if (isFirstLineSelected) {
|
||||
newValue = delimiter + newValue;
|
||||
count++;
|
||||
}
|
||||
count += (multilineSelection.match(new RegExp('\\n', 'g')) || []).length;
|
||||
newStart = selectionStart + delimiter.length;
|
||||
newEnd = selectionEnd + (delimiter.length * count);
|
||||
}
|
||||
} else if (getHasCurrentMarkdownBullet()) {
|
||||
if (message[selectionStart] === "\n")
|
||||
startPos = message.lastIndexOf('\n', selectionStart - 1) + 1;
|
||||
else
|
||||
startPos = message.lastIndexOf('\n', selectionStart) + 1;
|
||||
newStart = startPos;
|
||||
multilineSelection = multilineSelection.replace(/^\d+\.\s/gm, '');
|
||||
newValue = newPrefix + multilineSelection + newSuffix;
|
||||
multilineSelectionLength = multilineSelection.length;
|
||||
|
||||
//if the first line is not selected, we need to remove the first "\n" of multilineSelection
|
||||
if (newStart)
|
||||
multilineSelectionLength = multilineSelection.length - 1;
|
||||
newEnd = Math.max(newStart + multilineSelectionLength, 0);
|
||||
} else {
|
||||
if (message[selectionStart] === "\n")
|
||||
startPos = message.lastIndexOf('\n', selectionStart - 1) + 1;
|
||||
else
|
||||
startPos = message.lastIndexOf('\n', selectionStart) + 1;
|
||||
newStart = startPos;
|
||||
|
||||
// if no text is selected
|
||||
if (selectionStart === selectionEnd)
|
||||
newStart = newStart + 3;
|
||||
if (isFirstLineSelected)
|
||||
multilineSelection = getDelimiter() + multilineSelection;
|
||||
const selectionArr = Array.from(multilineSelection);
|
||||
for (var i = 0; i < selectionArr.length; i++) {
|
||||
if (selectionArr[i] === '\n')
|
||||
selectionArr[i] = `\n${getDelimiter()}`;
|
||||
}
|
||||
multilineSelection = selectionArr.join('');
|
||||
newValue = newPrefix + multilineSelection + newSuffix;
|
||||
multilineSelectionLength = multilineSelection.length;
|
||||
|
||||
//if the first line is not selected, we meed to remove the first "\n" of multilineSelection
|
||||
if (startPos)
|
||||
multilineSelectionLength = multilineSelection.length - 1;
|
||||
newEnd = Math.max(startPos + multilineSelectionLength, 0);
|
||||
}
|
||||
root.text = newValue;
|
||||
messageBarTextArea.selectText(newStart, newEnd);
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: listViewTypoFirst
|
||||
|
||||
@ -600,70 +377,56 @@ RowLayout {
|
||||
height: JamiTheme.chatViewFooterButtonSize
|
||||
orientation: ListView.Horizontal
|
||||
interactive: false
|
||||
leftMargin: 5
|
||||
rightMargin: 5
|
||||
spacing: 5
|
||||
|
||||
property list<Action> menuTypoActionsFirst: [
|
||||
Action {
|
||||
id: boldAction
|
||||
property var iconSrc: JamiResources.bold_black_24dp_svg
|
||||
property var shortcutText: JamiStrings.bold
|
||||
property string iconSrc: JamiResources.bold_black_24dp_svg
|
||||
property string shortcutText: JamiStrings.bold
|
||||
property string shortcutKey: "Ctrl+B"
|
||||
property bool isStyle: listViewTypo.isStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "**", "**", /\\*\*.+\\*\*/)
|
||||
onTriggered: function clickAction() {
|
||||
listViewTypo.addStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "**", "**", /\\*\*.+\\*\*/);
|
||||
}
|
||||
property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "**", "**")
|
||||
onTriggered: MDE.addStyle(messageBarTextArea, root.text, "**", "**")
|
||||
},
|
||||
Action {
|
||||
id: italicAction
|
||||
property var iconSrc: JamiResources.italic_black_24dp_svg
|
||||
property var shortcutText: JamiStrings.italic
|
||||
property string iconSrc: JamiResources.italic_black_24dp_svg
|
||||
property string shortcutText: JamiStrings.italic
|
||||
property string shortcutKey: "Ctrl+I"
|
||||
property bool isStyle: listViewTypo.isStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "*", "*", /(?:\*.+\*|\*\*\*.+\*\*\*)/)
|
||||
onTriggered: function clickAction() {
|
||||
listViewTypo.addStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "*", "*", /(?:\*.+\*|\*\*\*.+\*\*\*)/);
|
||||
}
|
||||
property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "*", "*")
|
||||
onTriggered: MDE.addStyle(messageBarTextArea, root.text, "*", "*")
|
||||
},
|
||||
Action {
|
||||
id: strikethroughAction
|
||||
property var iconSrc: JamiResources.s_barre_black_24dp_svg
|
||||
property var shortcutText: JamiStrings.strikethrough
|
||||
property string iconSrc: JamiResources.s_barre_black_24dp_svg
|
||||
property string shortcutText: JamiStrings.strikethrough
|
||||
property string shortcutKey: "Shift+Alt+X"
|
||||
property bool isStyle: listViewTypo.isStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "~~", "~~", /\~\~.+\~\~/)
|
||||
onTriggered: function clickAction() {
|
||||
listViewTypo.addStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "~~", "~~", /\~\~.+\~\~/);
|
||||
}
|
||||
property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "~~", "~~")
|
||||
onTriggered: MDE.addStyle(messageBarTextArea, root.text, "~~", "~~")
|
||||
},
|
||||
Action {
|
||||
id: titleAction
|
||||
property var iconSrc: JamiResources.title_black_24dp_svg
|
||||
property var shortcutText: JamiStrings.heading
|
||||
property string iconSrc: JamiResources.title_black_24dp_svg
|
||||
property string shortcutText: JamiStrings.heading
|
||||
property string shortcutKey: "Ctrl+Alt+H"
|
||||
property bool isStyle: listViewTypo.isPrefixSyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "### ", false)
|
||||
onTriggered: function clickAction() {
|
||||
listViewTypo.addPrefixStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "### ", false);
|
||||
}
|
||||
property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "### ", false)
|
||||
onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "### ", false)
|
||||
},
|
||||
Action {
|
||||
id: linkAction
|
||||
property var iconSrc: JamiResources.link_web_black_24dp_svg
|
||||
property var shortcutText: JamiStrings.link
|
||||
property string iconSrc: JamiResources.link_web_black_24dp_svg
|
||||
property string shortcutText: JamiStrings.link
|
||||
property string shortcutKey: "Ctrl+Alt+K"
|
||||
property bool isStyle: listViewTypo.isStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "[", "](url)", /\[.+\]\(.+\)/)
|
||||
onTriggered: function clickAction() {
|
||||
listViewTypo.addStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "[", "](url)", /\[.+\]\(.+\)/);
|
||||
}
|
||||
property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "[", "](url)")
|
||||
onTriggered: MDE.addStyle(messageBarTextArea, root.text, "[", "](url)")
|
||||
},
|
||||
Action {
|
||||
id: codeAction
|
||||
property var iconSrc: JamiResources.code_black_24dp_svg
|
||||
property var shortcutText: JamiStrings.code
|
||||
property string iconSrc: JamiResources.code_black_24dp_svg
|
||||
property string shortcutText: JamiStrings.code
|
||||
property string shortcutKey: "Ctrl+Alt+C"
|
||||
property bool isStyle: listViewTypo.isStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "```", "```", /\`\`\`.+\`\`\`/)
|
||||
onTriggered: function clickAction() {
|
||||
listViewTypo.addStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "```", "```", /\`\`\`.+\`\`\`/);
|
||||
}
|
||||
property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "```", "```")
|
||||
onTriggered: MDE.addStyle(messageBarTextArea, root.text, "```", "```")
|
||||
}
|
||||
]
|
||||
|
||||
@ -795,8 +558,6 @@ RowLayout {
|
||||
height: JamiTheme.chatViewFooterButtonSize
|
||||
orientation: ListView.Horizontal
|
||||
interactive: false
|
||||
leftMargin: 10
|
||||
rightMargin: 10
|
||||
spacing: 10
|
||||
|
||||
Rectangle {
|
||||
@ -808,33 +569,27 @@ RowLayout {
|
||||
property list<Action> menuTypoActionsSecond: [
|
||||
Action {
|
||||
id: quoteAction
|
||||
property var iconSrc: JamiResources.quote_black_24dp_svg
|
||||
property var shortcutText: JamiStrings.quote
|
||||
property string iconSrc: JamiResources.quote_black_24dp_svg
|
||||
property string shortcutText: JamiStrings.quote
|
||||
property string shortcutKey: "Shift+Alt+9"
|
||||
property bool isStyle: listViewTypo.isPrefixSyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "> ", false)
|
||||
onTriggered: function clickAction() {
|
||||
listViewTypo.addPrefixStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "> ", false);
|
||||
}
|
||||
property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "> ", false)
|
||||
onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "> ", false)
|
||||
},
|
||||
Action {
|
||||
id: unorderedListAction
|
||||
property var iconSrc: JamiResources.bullet_point_black_24dp_svg
|
||||
property var shortcutText: JamiStrings.unorderedList
|
||||
property string iconSrc: JamiResources.bullet_point_black_24dp_svg
|
||||
property string shortcutText: JamiStrings.unorderedList
|
||||
property string shortcutKey: "Shift+Alt+8"
|
||||
property bool isStyle: listViewTypo.isPrefixSyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "- ", false)
|
||||
onTriggered: function clickAction() {
|
||||
listViewTypo.addPrefixStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "- ", false);
|
||||
}
|
||||
property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "- ", false)
|
||||
onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "- ", false)
|
||||
},
|
||||
Action {
|
||||
id: orderedListAction
|
||||
property var iconSrc: JamiResources.bullet_number_black_24dp_svg
|
||||
property var shortcutText: JamiStrings.orderedList
|
||||
property string iconSrc: JamiResources.bullet_number_black_24dp_svg
|
||||
property string shortcutText: JamiStrings.orderedList
|
||||
property string shortcutKey: "Shift+Alt+7"
|
||||
property bool isStyle: listViewTypo.isPrefixSyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "", true)
|
||||
onTriggered: function clickAction() {
|
||||
listViewTypo.addPrefixStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "", true);
|
||||
}
|
||||
property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "", true)
|
||||
onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "", true)
|
||||
}
|
||||
]
|
||||
|
||||
@ -945,8 +700,8 @@ RowLayout {
|
||||
property list<Action> menuActions: [
|
||||
Action {
|
||||
id: sendFile
|
||||
property var iconSrc: JamiResources.link_black_24dp_svg
|
||||
property var toolTip: JamiStrings.sendFile
|
||||
property string iconSrc: JamiResources.link_black_24dp_svg
|
||||
property string toolTip: JamiStrings.sendFile
|
||||
property bool show: true
|
||||
property bool needWebEngine: false
|
||||
property bool needVideoDevice: false
|
||||
@ -958,8 +713,8 @@ RowLayout {
|
||||
},
|
||||
Action {
|
||||
id: addEmoji
|
||||
property var iconSrc: JamiResources.emoji_black_24dp_svg
|
||||
property var toolTip: JamiStrings.addEmoji
|
||||
property string iconSrc: JamiResources.emoji_black_24dp_svg
|
||||
property string toolTip: JamiStrings.addEmoji
|
||||
property bool show: true
|
||||
property bool needWebEngine: true
|
||||
property bool needVideoDevice: false
|
||||
@ -1047,8 +802,8 @@ RowLayout {
|
||||
property list<Action> menuMoreButton: [
|
||||
Action {
|
||||
id: leaveAudioMessage
|
||||
property var iconSrc: JamiResources.message_audio_black_24dp_svg
|
||||
property var toolTip: JamiStrings.leaveAudioMessage
|
||||
property string iconSrc: JamiResources.message_audio_black_24dp_svg
|
||||
property string toolTip: JamiStrings.leaveAudioMessage
|
||||
property bool show: false
|
||||
property bool needWebEngine: false
|
||||
property bool needVideoDevice: false
|
||||
@ -1059,8 +814,8 @@ RowLayout {
|
||||
},
|
||||
Action {
|
||||
id: leaveVideoMessage
|
||||
property var iconSrc: JamiResources.message_video_black_24dp_svg
|
||||
property var toolTip: JamiStrings.leaveVideoMessage
|
||||
property string iconSrc: JamiResources.message_video_black_24dp_svg
|
||||
property string toolTip: JamiStrings.leaveVideoMessage
|
||||
property bool show: false
|
||||
property bool needWebEngine: false
|
||||
property bool needVideoDevice: true
|
||||
@ -1071,8 +826,8 @@ RowLayout {
|
||||
},
|
||||
Action {
|
||||
id: shareLocation
|
||||
property var iconSrc: JamiResources.localisation_sharing_send_pin_svg
|
||||
property var toolTip: JamiStrings.shareLocation
|
||||
property string iconSrc: JamiResources.localisation_sharing_send_pin_svg
|
||||
property string toolTip: JamiStrings.shareLocation
|
||||
property bool show: false
|
||||
property bool needWebEngine: true
|
||||
property bool needVideoDevice: false
|
||||
|
||||
@ -174,7 +174,7 @@ DualPaneView {
|
||||
Layout.preferredWidth: JamiTheme.preferredFieldWidth
|
||||
|
||||
staticText: ""
|
||||
placeholderText: JamiStrings.addADescription
|
||||
placeholderText: JamiStrings.addDescription
|
||||
|
||||
textColor: {
|
||||
if (UtilsAdapter.luma(root.color)) {
|
||||
@ -205,7 +205,7 @@ DualPaneView {
|
||||
preferredWidth: textSize.width + 2 * JamiTheme.buttontextWizzardPadding
|
||||
|
||||
primary: true
|
||||
text: JamiStrings.createTheSwarm
|
||||
text: JamiStrings.createSwarm
|
||||
|
||||
onClicked: createSwarmClicked(title.dynamicText, description.dynamicText, UtilsAdapter.tempCreationImage())
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
PushButton {
|
||||
id: joinCallInAudio
|
||||
id: joinCallWithAudio
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
Layout.rightMargin: JamiTheme.preferredMarginSize
|
||||
|
||||
@ -68,7 +68,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
PushButton {
|
||||
id: joinCallInVideo
|
||||
id: joinCallWithVideo
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
Layout.rightMargin: JamiTheme.preferredMarginSize
|
||||
|
||||
@ -98,7 +98,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
from: 0
|
||||
duration: JamiTheme.shortFadeDuration
|
||||
|
||||
@ -95,7 +95,7 @@ Popup {
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: JamiTheme.textColor
|
||||
|
||||
text: JamiStrings.choosePlugin
|
||||
text: JamiStrings.chooseExtension
|
||||
}
|
||||
|
||||
PushButton {
|
||||
@ -176,7 +176,7 @@ Popup {
|
||||
Layout.leftMargin: 5
|
||||
Layout.topMargin: 5
|
||||
|
||||
toolTipText: JamiStrings.goBackToPluginsList
|
||||
toolTipText: JamiStrings.goBackToExtensionsList
|
||||
|
||||
onClicked: {
|
||||
stack.pop(null, StackView.Immediate);
|
||||
@ -195,7 +195,7 @@ Popup {
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
color: JamiTheme.textColor
|
||||
text: JamiStrings.pluginPreferences
|
||||
text: JamiStrings.extensionPreferences
|
||||
}
|
||||
|
||||
PushButton {
|
||||
|
||||
@ -38,9 +38,9 @@ ItemDelegate {
|
||||
|
||||
highlighted: ListView.isCurrentItem
|
||||
property bool interactive: true
|
||||
property string lastInteractionDate: LastInteractionTimeStamp === undefined ? "" : LastInteractionTimeStamp
|
||||
|
||||
property string lastInteractionFormattedDate: MessagesAdapter.getBestFormattedDate(lastInteractionDate)
|
||||
property int lastInteractionTimeStamp: LastInteractionTimeStamp
|
||||
property string lastInteractionFormattedDate: MessagesAdapter.getBestFormattedDate(lastInteractionTimeStamp)
|
||||
|
||||
property bool showSharePositionIndicator: PositionManager.isPositionSharedToConv(accountId, UID)
|
||||
property bool showSharedPositionIndicator: PositionManager.isConvSharingPosition(accountId, UID)
|
||||
@ -58,7 +58,7 @@ ItemDelegate {
|
||||
Connections {
|
||||
target: MessagesAdapter
|
||||
function onTimestampUpdated() {
|
||||
lastInteractionFormattedDate = MessagesAdapter.getBestFormattedDate(lastInteractionDate);
|
||||
lastInteractionFormattedDate = MessagesAdapter.getBestFormattedDate(lastInteractionTimeStamp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ ItemDelegate {
|
||||
color: JamiTheme.textColor
|
||||
}
|
||||
RowLayout {
|
||||
visible: ContactType !== Profile.Type.TEMPORARY && !IsBanned && lastInteractionFormattedDate !== undefined && interactive
|
||||
visible: ContactType !== Profile.Type.TEMPORARY && !IsBanned && lastInteractionTimeStamp > 0 && interactive
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 20
|
||||
Layout.alignment: Qt.AlignTop
|
||||
@ -138,7 +138,7 @@ ItemDelegate {
|
||||
// last Interaction date
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: lastInteractionFormattedDate === undefined ? "" : lastInteractionFormattedDate
|
||||
text: lastInteractionFormattedDate
|
||||
textFormat: TextEdit.PlainText
|
||||
font.pointSize: JamiTheme.smallFontSize
|
||||
font.weight: UnreadMessagesCount ? Font.DemiBold : Font.Normal
|
||||
@ -164,7 +164,7 @@ ItemDelegate {
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 20
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: JamiStrings.banned
|
||||
text: JamiStrings.blocked
|
||||
textFormat: TextEdit.PlainText
|
||||
visible: IsBanned
|
||||
font.pointSize: JamiTheme.mediumFontSize
|
||||
|
||||
@ -139,7 +139,7 @@ Rectangle {
|
||||
Layout.rightMargin: 2 * JamiTheme.settingsMarginSize
|
||||
|
||||
staticText: CurrentConversation.description
|
||||
placeholderText: JamiStrings.addADescription
|
||||
placeholderText: JamiStrings.addDescription
|
||||
elidedText: descriptionLineButtonTextSize.elidedText
|
||||
|
||||
textColor: root.textColor
|
||||
@ -156,7 +156,7 @@ Rectangle {
|
||||
descriptionLineButton.editMode = activeFocus;
|
||||
}
|
||||
|
||||
infoTipLineText: JamiStrings.addADescription
|
||||
infoTipLineText: JamiStrings.addDescription
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -663,7 +663,7 @@ Rectangle {
|
||||
if (MemberRole === Member.Role.INVITED)
|
||||
return JamiStrings.invited;
|
||||
if (MemberRole === Member.Role.BANNED)
|
||||
return JamiStrings.banned;
|
||||
return JamiStrings.blocked;
|
||||
return "";
|
||||
}
|
||||
maxWidth: JamiTheme.preferredFieldWidth
|
||||
|
||||
@ -30,7 +30,7 @@ ContextMenuAutoLoader {
|
||||
|
||||
property list<GeneralMenuItem> menuItems: [
|
||||
GeneralMenuItem {
|
||||
id: startVideoCallItem
|
||||
id: startVideoCall
|
||||
itemName: JamiStrings.startVideoCall
|
||||
canTrigger: ConversationsAdapter.dialogId(participantUri) !== ""
|
||||
iconSource: JamiResources.videocam_24dp_svg
|
||||
|
||||
@ -46,7 +46,6 @@ function finishCreation() {
|
||||
}
|
||||
|
||||
function showKeyboardShortcutTableWindow() {
|
||||
keyboardShortcutTableWindowObject.show()
|
||||
var centerX = mainWindow.x + mainWindow.width / 2
|
||||
var centerY = mainWindow.y + mainWindow.height / 2
|
||||
|
||||
@ -54,6 +53,11 @@ function showKeyboardShortcutTableWindow() {
|
||||
keyboardShortcutTableWindowObject.height = 0.75 * appWindow.height
|
||||
keyboardShortcutTableWindowObject.x = centerX - keyboardShortcutTableWindowObject.width / 2
|
||||
keyboardShortcutTableWindowObject.y = centerY - keyboardShortcutTableWindowObject.height / 2
|
||||
|
||||
keyboardShortcutTableWindowObject.visible = true
|
||||
keyboardShortcutTableWindowObject.show()
|
||||
keyboardShortcutTableWindowObject.raise()
|
||||
keyboardShortcutTableWindowObject.requestActivate()
|
||||
}
|
||||
|
||||
// Destroy and reset selectScreenWindowObject when window is closed.
|
||||
|
||||
@ -165,6 +165,16 @@ MessagesAdapter::sendMessage(const QString& message)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MessagesAdapter::sendMessageToUid(const QString& message, const QString& convUid)
|
||||
{
|
||||
try {
|
||||
lrcInstance_->getCurrentConversationModel()->sendMessage(convUid, message, replyToId_);
|
||||
} catch (...) {
|
||||
qDebug() << "Exception during sendMessage:" << message;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MessagesAdapter::editMessage(const QString& convId, const QString& newBody, const QString& messageId)
|
||||
{
|
||||
@ -221,6 +231,21 @@ MessagesAdapter::sendFile(const QString& message)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MessagesAdapter::sendFileToUid(const QString& message, const QString& convUid)
|
||||
{
|
||||
QFileInfo fi(message);
|
||||
QString fileName = fi.fileName();
|
||||
try {
|
||||
lrcInstance_->getCurrentConversationModel()->sendFile(convUid,
|
||||
message,
|
||||
fileName,
|
||||
replyToId_);
|
||||
} catch (...) {
|
||||
qDebug() << "Exception during sendFile";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MessagesAdapter::joinCall(const QString& uri,
|
||||
const QString& deviceId,
|
||||
@ -312,8 +337,7 @@ MessagesAdapter::onPaste()
|
||||
QString path = QDir::temp().filePath(fileName);
|
||||
|
||||
if (!pixmap.save(path, "PNG")) {
|
||||
qDebug().noquote() << "Errors during QPixmap save"
|
||||
<< "\n";
|
||||
qDebug().noquote() << "Errors during QPixmap save" << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -335,40 +359,6 @@ MessagesAdapter::onPaste()
|
||||
}
|
||||
}
|
||||
|
||||
QString
|
||||
MessagesAdapter::getStatusString(int status)
|
||||
{
|
||||
switch (static_cast<interaction::Status>(status)) {
|
||||
case interaction::Status::SENDING:
|
||||
return QObject::tr("Sending");
|
||||
case interaction::Status::FAILURE:
|
||||
return QObject::tr("Failure");
|
||||
case interaction::Status::SUCCESS:
|
||||
return QObject::tr("Sent");
|
||||
case interaction::Status::TRANSFER_CREATED:
|
||||
return QObject::tr("Connecting");
|
||||
case interaction::Status::TRANSFER_ACCEPTED:
|
||||
return QObject::tr("Accept");
|
||||
case interaction::Status::TRANSFER_CANCELED:
|
||||
return QObject::tr("Canceled");
|
||||
case interaction::Status::TRANSFER_ERROR:
|
||||
case interaction::Status::TRANSFER_UNJOINABLE_PEER:
|
||||
return QObject::tr("Unable to make contact");
|
||||
case interaction::Status::TRANSFER_ONGOING:
|
||||
return QObject::tr("Ongoing");
|
||||
case interaction::Status::TRANSFER_AWAITING_PEER:
|
||||
return QObject::tr("Waiting for contact");
|
||||
case interaction::Status::TRANSFER_AWAITING_HOST:
|
||||
return QObject::tr("Incoming transfer");
|
||||
case interaction::Status::TRANSFER_TIMEOUT_EXPIRED:
|
||||
return QObject::tr("Timed out waiting for contact");
|
||||
case interaction::Status::TRANSFER_FINISHED:
|
||||
return QObject::tr("Finished");
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
QVariantMap
|
||||
MessagesAdapter::getTransferStats(const QString& msgId, int status)
|
||||
{
|
||||
|
||||
@ -126,6 +126,7 @@ public:
|
||||
Q_INVOKABLE void unbanContact(int index);
|
||||
Q_INVOKABLE void unbanConversation(const QString& convUid);
|
||||
Q_INVOKABLE void sendMessage(const QString& message);
|
||||
Q_INVOKABLE void sendMessageToUid(const QString& message, const QString& convUid);
|
||||
Q_INVOKABLE void editMessage(const QString& convId,
|
||||
const QString& newBody,
|
||||
const QString& messageId = "");
|
||||
@ -136,6 +137,7 @@ public:
|
||||
const QString& emoji,
|
||||
const QString& messageId);
|
||||
Q_INVOKABLE void sendFile(const QString& message);
|
||||
Q_INVOKABLE void sendFileToUid(const QString& message, const QString& convUid);
|
||||
Q_INVOKABLE void acceptFile(const QString& arg);
|
||||
Q_INVOKABLE void cancelFile(const QString& arg);
|
||||
Q_INVOKABLE void openUrl(const QString& url);
|
||||
@ -159,7 +161,6 @@ public:
|
||||
const QColor& linkColor = QColor(0x06, 0x45, 0xad),
|
||||
const QColor& backgroundColor = QColor(0x0, 0x0, 0x0));
|
||||
Q_INVOKABLE void onPaste();
|
||||
Q_INVOKABLE QString getStatusString(int status);
|
||||
Q_INVOKABLE QVariantMap getTransferStats(const QString& messageId, int);
|
||||
Q_INVOKABLE QVariant dataForInteraction(const QString& interactionId,
|
||||
int role = Qt::DisplayRole) const;
|
||||
|
||||
@ -34,7 +34,6 @@ Item {
|
||||
property string incomingAudioCallFrom: qsTr("Incoming audio call from {}")
|
||||
property string incomingVideoCallFrom: qsTr("Incoming video call from {}")
|
||||
property string startSwarm: qsTr("Start swarm")
|
||||
property string createSwarm: qsTr("Create swarm")
|
||||
property string invitations: qsTr("Invitations")
|
||||
property string description: qsTr("Jami is a universal communication platform, with privacy as its foundation, that relies on a free distributed network for everyone.")
|
||||
property string updateToSwarm: qsTr("Migrating to the Swarm technology will enable synchronizing this conversation across multiple devices and improve reliability. The legacy conversation history will be cleared in the process.")
|
||||
@ -45,9 +44,11 @@ Item {
|
||||
property string reconnectTry: qsTr("Trying to reconnect to the Jami daemon (jamid)…")
|
||||
|
||||
// AboutPopUp
|
||||
property string version: qsTr("Version") + (AppVersionManager.isCurrentVersionBeta() ? " (Beta)" : "")
|
||||
property string buildID: qsTr("Build ID")
|
||||
property string version: qsTr("Version")
|
||||
|
||||
property string declarationYear: "© 2015-2024"
|
||||
property string slogan: "Eleutheria"
|
||||
property string slogan: "Astarte"
|
||||
property string declaration: qsTr('Jami, a GNU package, is software for universal and distributed peer-to-peer communication that respects the freedom and privacy of its users. Visit <a href="https://jami.net" style="color: ' + JamiTheme.buttonTintedBlue + '">jami.net</a>' + ' to learn more.')
|
||||
property string noWarranty: qsTr('This program comes with absolutely no warranty. See the <a href="https://www.gnu.org/licenses/gpl-3.0.html" style="color: ' + JamiTheme.buttonTintedBlue + '">GNU General Public License</a>, version 3 or later for details.')
|
||||
property string contribute: qsTr('Contribute')
|
||||
@ -73,7 +74,7 @@ Item {
|
||||
property string authenticate: qsTr("Authenticate")
|
||||
property string deleteAccount: qsTr("Delete account")
|
||||
property string inProgress: qsTr("In progress…")
|
||||
property string authenticationFailed: qsTr("Authentication failed")
|
||||
property string authenticationFailed: qsTr("An error occurred while authenticating account.")
|
||||
property string password: qsTr("Password")
|
||||
property string username: qsTr("Username")
|
||||
property string alias: qsTr("Alias")
|
||||
@ -85,8 +86,8 @@ Item {
|
||||
property string enableCustomRingtone: qsTr("Enable custom ringtone")
|
||||
property string selectCustomRingtone: qsTr("Select custom ringtone")
|
||||
property string selectNewRingtone: qsTr("Select a new ringtone")
|
||||
property string certificateFile: qsTr("Certificate File (*.crt)")
|
||||
property string audioFile: qsTr("Audio File (*.wav *.ogg *.opus *.mp3 *.aiff *.wma)")
|
||||
property string certificateFile: qsTr("Certificate file (*.crt)")
|
||||
property string audioFile: qsTr("Audio file (*.wav *.ogg *.opus *.mp3 *.aiff *.wma)")
|
||||
property string pushToTalk: qsTr("Push-to-talk")
|
||||
property string enablePTT: qsTr("Enable push-to-talk")
|
||||
property string keyboardShortcut: qsTr("Keyboard shortcut")
|
||||
@ -117,11 +118,11 @@ Item {
|
||||
property string verifyCertificatesClient: qsTr("Verify server TLS certificates")
|
||||
property string tlsRequireConnections: qsTr("Require certificate for incoming TLS connections")
|
||||
property string disableSecureDlgCheck: qsTr("Disable secure dialog check for incoming TLS data")
|
||||
property string selectPrivateKey: qsTr("Select a private key")
|
||||
property string selectUserCert: qsTr("Select a user certificate")
|
||||
property string selectCACert: qsTr("Select a CA certificate")
|
||||
property string selectPrivateKey: qsTr("Select private key")
|
||||
property string selectUserCert: qsTr("Select user certificate")
|
||||
property string selectCACert: qsTr("Select CA certificate")
|
||||
property string selectCACertDefault: qsTr("Select")
|
||||
property string keyFile: qsTr("Key File (*.key)")
|
||||
property string keyFile: qsTr("Key file (*.key)")
|
||||
|
||||
// AdvancedConnectivitySettings
|
||||
property string connectivity: qsTr("Connectivity")
|
||||
@ -133,7 +134,7 @@ Item {
|
||||
property string turnAdress: qsTr("TURN address")
|
||||
property string turnUsername: qsTr("TURN username")
|
||||
property string turnPassword: qsTr("TURN password")
|
||||
property string turnRealm: qsTr("TURN Realm")
|
||||
property string turnRealm: qsTr("TURN realm")
|
||||
property string useSTUN: qsTr("Use STUN")
|
||||
property string stunAdress: qsTr("STUN address")
|
||||
|
||||
@ -174,14 +175,14 @@ Item {
|
||||
property string back: qsTr("Back")
|
||||
property string accountSettingsMenuTitle: qsTr("Account")
|
||||
property string generalSettingsTitle: qsTr("General")
|
||||
property string pluginSettingsTitle: qsTr("Extensions")
|
||||
property string extensionSettingsTitle: qsTr("Extensions")
|
||||
property string enableAccountSettingsTitle: qsTr("Enable account")
|
||||
property string manageAccountSettingsTitle: qsTr("Manage account")
|
||||
property string linkedDevicesSettingsTitle: qsTr("Linked devices")
|
||||
property string callSettingsTitle: qsTr("Call settings")
|
||||
property string chatSettingsTitle: qsTr("Chat")
|
||||
property string advancedSettingsTitle: qsTr("Advanced settings")
|
||||
property string audioVideoSettingsTitle: qsTr("Audio and Video")
|
||||
property string mediaSettingsTitle: qsTr("Media")
|
||||
|
||||
// AudioSettings
|
||||
property string audio: qsTr("Audio")
|
||||
@ -206,7 +207,7 @@ Item {
|
||||
property string mirrorLocalVideo: qsTr("Mirror local video")
|
||||
property string screenSharing: qsTr("Screen sharing")
|
||||
property string selectScreenSharingFPS: qsTr("Select screen sharing frame rate (frames per second)")
|
||||
property string noVideo: qsTr("no video")
|
||||
property string noCamera: qsTr("No camera available")
|
||||
|
||||
// BackupKeyPage
|
||||
property string whyBackupAccount: qsTr("Why should I back-up this account?")
|
||||
@ -218,8 +219,7 @@ Item {
|
||||
property string jamiArchiveFiles: qsTr("Jami archive files (*.gz)")
|
||||
property string allFiles: qsTr("All files (*)")
|
||||
|
||||
// BannedItemDelegate
|
||||
property string reinstateContact: qsTr("Reinstate as contact")
|
||||
// ContactItemDelegate
|
||||
property string name: qsTr("name")
|
||||
property string identifier: qsTr("Identifier")
|
||||
|
||||
@ -230,10 +230,10 @@ Item {
|
||||
property string unmute: qsTr("Unmute")
|
||||
property string pauseCall: qsTr("Pause call")
|
||||
property string resumeCall: qsTr("Resume call")
|
||||
property string muteCamera: qsTr("Mute camera")
|
||||
property string unmuteCamera: qsTr("Unmute camera")
|
||||
property string addParticipant: qsTr("Add participant")
|
||||
property string addParticipants: qsTr("Add participants")
|
||||
property string stopCamera: qsTr("Stop camera")
|
||||
property string startCamera: qsTr("Start camera")
|
||||
property string inviteMember: qsTr("Invite member")
|
||||
property string inviteMembers: qsTr("Invite members")
|
||||
property string details: qsTr("Details")
|
||||
property string chat: qsTr("Chat")
|
||||
property string moreOptions: qsTr("More options")
|
||||
@ -259,20 +259,20 @@ Item {
|
||||
property string paste: qsTr("Paste")
|
||||
|
||||
// ConversationContextMenu
|
||||
property string startVideoCall: qsTr("Start video call")
|
||||
property string startAudioCall: qsTr("Start audio call")
|
||||
property string startVideoCall: qsTr("Start video call")
|
||||
property string clearConversation: qsTr("Clear conversation")
|
||||
property string confirmAction: qsTr("Confirm action")
|
||||
property string removeConversation: qsTr("Remove conversation")
|
||||
property string confirmRmConversation: qsTr("Would you really like to remove this conversation?")
|
||||
property string confirmBlockConversation: qsTr("Would you really like to block this conversation?")
|
||||
property string removeConversation: qsTr("Leave conversation")
|
||||
property string confirmRmConversation: qsTr("Do you really want to leave this conversation?")
|
||||
property string confirmBlockConversation: qsTr("Do you really want to block this conversation?")
|
||||
property string removeContact: qsTr("Remove contact")
|
||||
property string blockContact: qsTr("Block contact")
|
||||
property string convDetails: qsTr("Conversation details")
|
||||
property string contactDetails: qsTr("Contact details")
|
||||
|
||||
// CallViewContextMenu
|
||||
property string sipInputPanel: qsTr("Sip input panel")
|
||||
property string sipInputPanel: qsTr("DTMF input panel")
|
||||
property string transferCall: qsTr("Transfer call")
|
||||
property string stopRec: qsTr("Stop recording")
|
||||
property string startRec: qsTr("Start recording")
|
||||
@ -283,7 +283,7 @@ Item {
|
||||
property string shareScreenArea: qsTr("Share screen area")
|
||||
property string shareFile: qsTr("Share file")
|
||||
property string selectShareMethod: qsTr("Select sharing method")
|
||||
property string viewPlugin: qsTr("View plugin")
|
||||
property string viewExtension: qsTr("View extension")
|
||||
property string advancedInformation: qsTr("Advanced information")
|
||||
property string noVideoDevice: qsTr("No video device")
|
||||
property string notAvailable: qsTr("Unavailable")
|
||||
@ -294,7 +294,7 @@ Item {
|
||||
property string screenshotTaken: qsTr("Screenshot saved to %1")
|
||||
property string fileSaved: qsTr("File saved to %1")
|
||||
|
||||
//advanced information
|
||||
// Advanced information
|
||||
property string renderersInformation: qsTr("Renderers information")
|
||||
property string callInformation: qsTr("Call information")
|
||||
property string peerNumber: qsTr("Peer number")
|
||||
@ -310,8 +310,8 @@ Item {
|
||||
// Share location/position
|
||||
property string shareLocation: qsTr("Share location")
|
||||
property string stopSharingLocation: qsTr("Stop sharing")
|
||||
property string locationServicesError: qsTr("Your precise location could not be determined.\nIn Device Settings, please turn on \"Location Services\".\nOther participants' location can still be received.")
|
||||
property string locationServicesClosedError: qsTr("Your precise location could not be determined. Please check your Internet connection.")
|
||||
property string locationServicesError: qsTr("An error occurred while sharing device location.\nEnable “Location Services” in device settings in order to use this feature.\nThe location of other members can still be received.")
|
||||
property string locationServicesClosedError: qsTr("An error occurred while sharing device location. Please check your Internet connection and try again.")
|
||||
property string stopAllSharings: qsTr("Turn off location sharing")
|
||||
property string shortStopAllSharings: qsTr("Turn off sharing")
|
||||
property string stopConvSharing: qsTr("Stop location sharing in this conversation (%1)")
|
||||
@ -338,17 +338,18 @@ Item {
|
||||
|
||||
// Chatview header
|
||||
property string hideChat: qsTr("Hide chat")
|
||||
property string placeAudioCall: qsTr("Place audio call")
|
||||
property string placeVideoCall: qsTr("Place video call")
|
||||
property string showPlugins: qsTr("Show available plugins")
|
||||
property string placeAudioCall: qsTr("Start audio call")
|
||||
property string placeVideoCall: qsTr("Start video call")
|
||||
property string showExtensions: qsTr("Show available extensions")
|
||||
property string addToConversations: qsTr("Add to conversations")
|
||||
property string backendError: qsTr("This is the error from the backend: %0")
|
||||
property string backendError: qsTr("A backend system error occurred: %0")
|
||||
property string disabledAccount: qsTr("The account is disabled")
|
||||
property string noNetworkConnectivity: qsTr("No network connectivity")
|
||||
property string deletedMessage: qsTr("deleted a message")
|
||||
property string backCall: qsTr("Back to Call")
|
||||
property string deletedMedia: qsTr("deleted a media")
|
||||
property string returnToCall: qsTr("Return to call")
|
||||
|
||||
//MessagesResearch
|
||||
// MessagesResearch
|
||||
property string jumpTo: qsTr("Jump to")
|
||||
property string messages: qsTr("Messages")
|
||||
property string files: qsTr("Files")
|
||||
@ -379,7 +380,7 @@ Item {
|
||||
property string invalidUsername: qsTr("Invalid username")
|
||||
property string nameAlreadyTaken: qsTr("Name already taken")
|
||||
property string usernameAlreadyTaken: qsTr("Username already taken")
|
||||
property string joinJamiNoPassword: qsTr("Are you sure you would like to join Jami without a username?\nIf yes, only a randomly generated 40-character identifier will be assigned to this account.")
|
||||
property string joinJamiNoPassword: qsTr("Do you really want to join Jami without a username?\nIf yes, only a randomly generated 40-character identifier will be assigned to this account.")
|
||||
property string usernameToolTip: qsTr("- 32 characters maximum\n- Alphabetical characters (A to Z and a to z)\n- Numeric characters (0 to 9)\n- Special characters allowed: dash (-)")
|
||||
|
||||
// Good to know
|
||||
@ -395,12 +396,12 @@ Item {
|
||||
property string sipAccount: qsTr("SIP account")
|
||||
property string proxy: qsTr("Proxy")
|
||||
property string server: qsTr("Server")
|
||||
property string configureExistingSIP: qsTr("Configure an existing SIP account")
|
||||
property string configureExistingSIP: qsTr("Configure existing SIP account")
|
||||
property string personalizeAccount: qsTr("Personalize account")
|
||||
property string addSip: qsTr("Add SIP account")
|
||||
property string tls: qsTr("TLS")
|
||||
property string udp: qsTr("UDP")
|
||||
property string displayName: qsTr("Display Name")
|
||||
property string displayName: qsTr("Display name")
|
||||
|
||||
// accountSettingsPages
|
||||
property string customizeAccountDescription: qsTr("Your profile is only shared with your contacts.\nYour picture and your nickname can be changed at all time in the settings of your account.")
|
||||
@ -416,11 +417,11 @@ Item {
|
||||
|
||||
// CurrentAccountSettings && AdvancedSettings
|
||||
property string backupSuccessful: qsTr("Backup successful")
|
||||
property string backupFailed: qsTr("Backup failed")
|
||||
property string backupFailed: qsTr("An error occurred while backing up account.")
|
||||
property string changePasswordSuccess: qsTr("Password changed successfully")
|
||||
property string changePasswordFailed: qsTr("Password change failed")
|
||||
property string changePasswordFailed: qsTr("An error occurred while changing account password.")
|
||||
property string setPasswordSuccess: qsTr("Password set successfully")
|
||||
property string setPasswordFailed: qsTr("Password set failed")
|
||||
property string setPasswordFailed: qsTr("An error occurred while setting account password.")
|
||||
property string changePassword: qsTr("Change password")
|
||||
property string setPassword: qsTr("Encrypt account")
|
||||
property string setAPassword: qsTr("Set a password")
|
||||
@ -431,8 +432,8 @@ Item {
|
||||
property string advancedAccountSettings: qsTr("Advanced account settings")
|
||||
property string encryptAccount: qsTr("Encrypt account with password")
|
||||
property string customizeProfile: qsTr("Customize profile")
|
||||
property string customizeProfileDescription: qsTr("This profile is only shared with this account's contacts.\nThe profile can be changed at all times from the account's settings.")
|
||||
property string encryptTitle: qsTr("Encrypt account with a password")
|
||||
property string customizeProfileDescription: qsTr("This profile is only shared with account contacts.\nThe profile can be changed in account settings.")
|
||||
property string encryptTitle: qsTr("Encrypt account with password")
|
||||
property string encryptDescription: qsTr("A Jami account is created and stored locally only on this device, as an archive containing your account keys. Access to this archive can optionally be protected by a password.")
|
||||
property string encryptWarning: qsTr("Please note that if you lose your password, it CANNOT be recovered!")
|
||||
property string enterNickname: qsTr("Enter a nickname, surname…")
|
||||
@ -450,17 +451,18 @@ Item {
|
||||
// LinkedDevices
|
||||
property string tipLinkNewDevice: qsTr("Link a new device to this account")
|
||||
property string linkDevice: qsTr("Exporting account…")
|
||||
property string removeDevice: qsTr("Remove Device")
|
||||
property string sureToRemoveDevice: qsTr("Are you sure you wish to remove this device?")
|
||||
property string yourPinIs: qsTr("Your PIN is:")
|
||||
property string linkDeviceNetWorkError: qsTr("Error connecting to the network.\nPlease try again later.")
|
||||
property string removeDevice: qsTr("Remove device")
|
||||
property string confirmRemoveDevice: qsTr("Do you really want to unlink selected device? To continue, enter account password and click Unlink.")
|
||||
property string yourPinIs: qsTr("Account PIN code is:")
|
||||
property string linkDeviceNetWorkError: qsTr("A network error occurred while linking device.\nPlease try again later.")
|
||||
|
||||
// BannedContacts
|
||||
property string banned: qsTr("Banned")
|
||||
property string bannedContacts: qsTr("Banned contacts")
|
||||
property string reinstateContact: qsTr("Reinstate as contact")
|
||||
property string blocked: qsTr("Blocked")
|
||||
property string blockedContacts: qsTr("Blocked contacts")
|
||||
|
||||
// DeleteAccountDialog
|
||||
property string confirmDeleteQuestion: qsTr("Would you really like to delete this account?")
|
||||
property string confirmDeleteAccount: qsTr("Do you really want to delete this account? To continue, click Delete.")
|
||||
property string deleteAccountInfos: qsTr("If your account has not been backed up or added to another device, your account and registered username will be IRREVOCABLY LOST.")
|
||||
|
||||
// DeviceItemDelegate
|
||||
@ -498,14 +500,14 @@ Item {
|
||||
// File transfer settings
|
||||
property string fileTransfer: qsTr("File transfer")
|
||||
property string autoAcceptFiles: qsTr("Automatically accept incoming files")
|
||||
property string acceptTransferBelow: qsTr("Accept transfer limit (in Mb)")
|
||||
property string acceptTransferTooltip: qsTr("in MB, 0 = unlimited")
|
||||
property string acceptTransferBelow: qsTr("Accept transfer limit (Mb)")
|
||||
property string acceptTransferTooltip: qsTr("MB, 0 = unlimited")
|
||||
|
||||
// JamiUserIdentity settings
|
||||
property string register: qsTr("Register")
|
||||
property string incorrectPassword: qsTr("Incorrect password")
|
||||
property string networkError: qsTr("Network error")
|
||||
property string somethingWentWrong: qsTr("Something went wrong")
|
||||
property string incorrectPassword: qsTr("Incorrect password.")
|
||||
property string networkError: qsTr("A network error occurred.")
|
||||
property string somethingWentWrong: qsTr("An unexpected error occurred.")
|
||||
|
||||
// Context Menu
|
||||
property string saveFile: qsTr("Save file")
|
||||
@ -518,20 +520,20 @@ Item {
|
||||
property string enableAutoUpdates: qsTr("Enable/Disable automatic updates")
|
||||
property string updatesTitle: qsTr("Updates")
|
||||
property string updateDialogTitle: qsTr("Update")
|
||||
property string updateFound: qsTr("A new version of Jami was found\nWould you like to update now?")
|
||||
property string updateFound: qsTr("A new version of Jami was found.\nDo you want to update Jami now?\nTo continue, click Update.")
|
||||
property string updateNotFound: qsTr("No new version of Jami was found")
|
||||
property string updateCheckError: qsTr("An error occured when checking for a new version")
|
||||
property string updateNetworkError: qsTr("Network error")
|
||||
property string updateSSLError: qsTr("SSL error")
|
||||
property string updateDownloadCanceled: qsTr("Installer download canceled")
|
||||
property string updateCheckError: qsTr("An error occurred while checking for a new version.")
|
||||
property string updateNetworkError: qsTr("A network error occurred.")
|
||||
property string updateSSLError: qsTr("An SSL error occurred.")
|
||||
property string updateDownloadCanceled: qsTr("Installer download was canceled by user.")
|
||||
property string updateDownloading: "Downloading"
|
||||
property string confirmBeta: qsTr("This will uninstall your current Release version and you can always download the latest Release version on our website")
|
||||
property string confirmBeta: qsTr("This will replace the Release version with the Beta version on this device. The latest Release version can always be downloaded from the Jami website.")
|
||||
property string networkDisconnected: qsTr("Network disconnected")
|
||||
property string accessError: qsTr("Content access error")
|
||||
property string contentNotFoundError: qsTr("Content not found")
|
||||
property string genericError: qsTr("Something went wrong")
|
||||
property string accessError: qsTr("An error occurred while accessing contents.")
|
||||
property string contentNotFoundError: qsTr("Content not found.")
|
||||
property string genericError: qsTr("An unexpected error occurred.")
|
||||
|
||||
//Troubleshoot Settings
|
||||
// Troubleshoot Settings
|
||||
property string troubleshootTitle: qsTr("Troubleshoot")
|
||||
property string troubleshootButton: qsTr("Open logs")
|
||||
property string troubleshootText: qsTr("Get logs")
|
||||
@ -546,9 +548,9 @@ Item {
|
||||
property string callRecording: qsTr("Call recording")
|
||||
property string alwaysRecordCalls: qsTr("Always record calls")
|
||||
|
||||
// KeyboardShortCutTable
|
||||
property string keyboardShortcutTableWindowTitle: qsTr("Keyboard Shortcut Table")
|
||||
property string keyboardShortcuts: qsTr("Keyboard Shortcuts")
|
||||
// Keyboard shortcuts
|
||||
property string keyboardShortcutTableWindowTitle: qsTr("Keyboard shortcuts")
|
||||
property string keyboardShortcuts: qsTr("Keyboard shortcuts")
|
||||
property string conversationKeyboardShortcuts: qsTr("Conversation")
|
||||
property string callKeyboardShortcuts: qsTr("Call")
|
||||
property string settings: qsTr("Settings")
|
||||
@ -557,11 +559,11 @@ Item {
|
||||
// View Logs
|
||||
property string logsViewTitle: qsTr("Debug")
|
||||
property string logsViewCopy: qsTr("Copy")
|
||||
property string logsViewReport: qsTr("Report Bug")
|
||||
property string logsViewReport: qsTr("Submit issue")
|
||||
property string logsViewClear: qsTr("Clear")
|
||||
property string cancel: qsTr("Cancel")
|
||||
property string logsViewCopied: qsTr("Copied to clipboard!")
|
||||
property string logsViewDisplay: qsTr("Receive Logs")
|
||||
property string logsViewDisplay: qsTr("View logs")
|
||||
|
||||
// ImportFromBackupPage
|
||||
property string archive: qsTr("Archive")
|
||||
@ -577,29 +579,29 @@ Item {
|
||||
// ImportFromDevicePage
|
||||
property string importButton: qsTr("Import")
|
||||
property string pin: qsTr("Enter the PIN code")
|
||||
property string importFromDeviceDescription: qsTr("A PIN is required to use an existing Jami account on this device.")
|
||||
property string importStep1: qsTr("Step 01")
|
||||
property string importStep2: qsTr("Step 02")
|
||||
property string importStep3: qsTr("Step 03")
|
||||
property string importStep4: qsTr("Step 04")
|
||||
property string importStep1Desc: qsTr("Go to the account management settings of a previous device")
|
||||
property string importStep2Desc: qsTr("Choose the account to link")
|
||||
property string importStep3Desc: qsTr("Select \"Link another device\"")
|
||||
property string importStep4Desc: qsTr("The PIN code will be available for 10 minutes")
|
||||
property string importFromDeviceDescription: qsTr("A PIN code is required to use an existing Jami account on this device.")
|
||||
property string importStep1: qsTr("Step 1")
|
||||
property string importStep2: qsTr("Step 2")
|
||||
property string importStep3: qsTr("Step 3")
|
||||
property string importStep4: qsTr("Step 4")
|
||||
property string importStep1Desc: qsTr("Go to the account management settings of a previous device.")
|
||||
property string importStep2Desc: qsTr("Choose the account to link.")
|
||||
property string importStep3Desc: qsTr("Select “Link another device.”")
|
||||
property string importStep4Desc: qsTr("The PIN code will expire in 10 minutes.")
|
||||
property string importPasswordDesc: qsTr("Fill if the account is password-encrypted.")
|
||||
|
||||
// LinkDevicesDialog
|
||||
property string pinTimerInfos: qsTr("The PIN and the account password should be entered in your device within 10 minutes.")
|
||||
property string pinTimerInfos: qsTr("The PIN code and the account password should be entered in your device within 10 minutes.")
|
||||
property string close: qsTr("Close")
|
||||
property string enterAccountPassword: qsTr("Enter account password")
|
||||
property string enterPasswordPinCode: qsTr("This account is password encrypted, enter the password to generate a PIN code.")
|
||||
property string addDevice: qsTr("Add Device")
|
||||
property string pinExpired: qsTr("PIN expired")
|
||||
property string pinExpired: qsTr("PIN code has expired.")
|
||||
property string onAnotherDevice: qsTr("On another device")
|
||||
property string onAnotherDeviceInstruction: qsTr("Install and launch Jami, select \"Import from another device\" and scan the QR code.")
|
||||
property string onAnotherDeviceInstruction: qsTr("Install and launch Jami, select “Import from another device” and scan the QR code.")
|
||||
property string linkNewDevice: qsTr("Link new device")
|
||||
property string linkingInstructions: qsTr("In Jami, scan QR code or manually enter the PIN.")
|
||||
property string pinValidity: qsTr("The PIN code is valid for: ")
|
||||
property string linkingInstructions: qsTr("In Jami, scan QR code or manually enter PIN code.")
|
||||
property string pinValidity: qsTr("The PIN code will expire in: ")
|
||||
|
||||
// PasswordDialog
|
||||
property string enterPassword: qsTr("Enter password")
|
||||
@ -611,14 +613,14 @@ Item {
|
||||
property string exportAccount: qsTr("Export")
|
||||
|
||||
// PhotoBoothView
|
||||
property string selectAvatarImage: qsTr("Select image as avatar")
|
||||
property string selectImage: qsTr("Select image")
|
||||
property string importFromFile: qsTr("Import avatar from image file")
|
||||
property string removeImage: qsTr("Remove image")
|
||||
property string selectProfilePicture: qsTr("Select image as profile picture")
|
||||
property string selectImage: qsTr("How do you want to set the profile picture?")
|
||||
property string importFromFile: qsTr("Import profile picture from image file")
|
||||
property string removeImage: qsTr("Remove profile picture")
|
||||
property string takePhoto: qsTr("Take photo")
|
||||
property string imageFiles: qsTr("Image Files (*.jpeg *.jpg *.png *.JPEG* .JPG *.PNG)")
|
||||
property string imageFiles: qsTr("Image files (*.jpeg *.jpg *.png *.JPEG* .JPG *.PNG)")
|
||||
|
||||
// Plugins
|
||||
// Extensions
|
||||
property string autoUpdate: qsTr("Auto update")
|
||||
property string disableAll: qsTr("Disable all")
|
||||
property string installed: qsTr("Installed")
|
||||
@ -626,33 +628,34 @@ Item {
|
||||
property string installing: qsTr("Installing")
|
||||
property string installManually: qsTr("Install manually")
|
||||
property string installMannuallyDescription: qsTr("Install an extension directly from your device.")
|
||||
property string pluginStoreTitle: qsTr("Available")
|
||||
property string pluginStoreNotAvailable: qsTr("Plugins store is not available")
|
||||
property string storeNotSupportedPlatform: qsTr("The Jami Extension Store currently has no extension available for the platform in use. Check again later!")
|
||||
property string pluginPreferences: qsTr("Preferences")
|
||||
property string installationFailed: qsTr("Installation failed")
|
||||
property string pluginInstallationFailed: qsTr("The installation of the plugin failed")
|
||||
property string extensionStoreTitle: qsTr("Available")
|
||||
property string extensionStoreNotAvailable: qsTr("The Jami Extension Store is not currently available. Please try again later.")
|
||||
property string storeNotSupportedPlatform: qsTr("There are no extensions currently available in the Jami Extension Store for the platform in use. Please check again later.")
|
||||
property string extensionPreferences: qsTr("Preferences")
|
||||
property string installationFailed: qsTr("Installation error")
|
||||
property string extensionInstallationFailed: qsTr("An error occurred while installing the extension.")
|
||||
property string reset: qsTr("Reset")
|
||||
property string uninstall: qsTr("Uninstall")
|
||||
property string resetPreferences: qsTr("Reset Preferences")
|
||||
property string selectPluginInstall: qsTr("Select a plugin to install")
|
||||
property string uninstallPlugin: qsTr("Uninstall plugin")
|
||||
property string pluginResetConfirmation: qsTr("Are you sure you wish to reset %1 preferences?")
|
||||
property string pluginUninstallConfirmation: qsTr("Are you sure you wish to uninstall %1?")
|
||||
property string goBackToPluginsList: qsTr("Go back to plugins list")
|
||||
property string selectFile: qsTr("Select a file")
|
||||
property string selectExtensionInstall: qsTr("Select extension to install")
|
||||
property string uninstallExtension: qsTr("Uninstall extension")
|
||||
property string confirmExtensionReset: qsTr("Do you really want to reset the preferences for the %1 extension?")
|
||||
property string confirmExtensionUninstall: qsTr("Do you really want to uninstall the %1 extension?")
|
||||
property string goBackToExtensionsList: qsTr("Go back to extensions list")
|
||||
property string selectFile: qsTr("Select file")
|
||||
property string select: qsTr("Select")
|
||||
property string chooseImageFile: qsTr("Choose image file")
|
||||
property string pluginFiles: qsTr("Plugin Files (*.jpl)")
|
||||
property string extensionFiles: qsTr("Extension files (*.jpl)")
|
||||
property string loadUnload: qsTr("Load/Unload")
|
||||
property string selectAnImage: qsTr("Select An Image to %1")
|
||||
property string editPreference: qsTr("Edit preference")
|
||||
property string onOff: qsTr("On/Off")
|
||||
property string choosePlugin: qsTr("Choose Plugin")
|
||||
property string versionPlugin: qsTr("Version %1")
|
||||
property string chooseExtension: qsTr("Choose extension")
|
||||
property string versionExtension: qsTr("Version %1")
|
||||
property string lastUpdate: qsTr("Last update %1")
|
||||
property string by: qsTr("By %1")
|
||||
property string proposedBy: qsTr("Proposed by %1")
|
||||
|
||||
// ProfilePage
|
||||
property string information: qsTr("Information")
|
||||
property string moreInformation: qsTr("More information")
|
||||
@ -662,9 +665,9 @@ Item {
|
||||
property string confirmRemovalRequest: qsTr("Enter the account password to confirm the removal of this device")
|
||||
|
||||
// SelectScreen
|
||||
property string selectScreen: qsTr("Select a screen to share")
|
||||
property string selectWindow: qsTr("Select a window to share")
|
||||
property string allScreens: qsTr("All Screens")
|
||||
property string selectScreen: qsTr("Select screen to share")
|
||||
property string selectWindow: qsTr("Select window to share")
|
||||
property string allScreens: qsTr("All screens")
|
||||
property string screens: qsTr("Screens")
|
||||
property string windows: qsTr("Windows")
|
||||
property string screen: qsTr("Screen %1")
|
||||
@ -682,7 +685,7 @@ Item {
|
||||
property string connectJAMSServer: qsTr("Connect to a JAMS server")
|
||||
property string createFromJAMS: qsTr("Create account from Jami Account Management Server (JAMS)")
|
||||
property string addSIPAccount: qsTr("Configure a SIP account")
|
||||
property string errorCreateAccount: qsTr("Error while creating your account. Check your credentials.")
|
||||
property string errorCreateAccount: qsTr("An error occurred while creating the account. Check credentials and try again.")
|
||||
property string createNewRV: qsTr("Create a rendezvous point")
|
||||
property string joinJami: qsTr("Join Jami")
|
||||
property string createNewJamiAccount: qsTr("Create new Jami account")
|
||||
@ -694,9 +697,9 @@ Item {
|
||||
property string welcomeToJami: qsTr("Welcome to Jami")
|
||||
|
||||
// SmartList
|
||||
property string clearText: qsTr("Clear Text")
|
||||
property string clearText: qsTr("Clear text")
|
||||
property string conversations: qsTr("Conversations")
|
||||
property string searchResults: qsTr("Search Results")
|
||||
property string searchResults: qsTr("Search results")
|
||||
|
||||
// SmartList context menu
|
||||
property string declineContactRequest: qsTr("Decline contact request")
|
||||
@ -706,15 +709,16 @@ Item {
|
||||
property string update: qsTr("Automatically check for updates")
|
||||
|
||||
// Generic dialog options
|
||||
property string optionOk: qsTr("Ok")
|
||||
property string optionOk: qsTr("OK")
|
||||
property string optionSave: qsTr("Save")
|
||||
property string optionCancel: qsTr("Cancel")
|
||||
property string optionUpgrade: qsTr("Upgrade")
|
||||
property string optionLater: qsTr("Later")
|
||||
property string optionDelete: qsTr("Delete")
|
||||
property string optionRemove: qsTr("Remove")
|
||||
property string optionLeave: qsTr("Leave")
|
||||
property string optionBlock: qsTr("Block")
|
||||
property string optionUnban: qsTr("Unban")
|
||||
property string optionUnblock: qsTr("Unblock")
|
||||
|
||||
// Conference moderation
|
||||
property string setModerator: qsTr("Set moderator")
|
||||
@ -735,8 +739,8 @@ Item {
|
||||
property string removeDefaultModerator: qsTr("Remove default moderator")
|
||||
|
||||
// Daemon reconnection
|
||||
property string reconnectDaemon: qsTr("Trying to reconnect to the Jami daemon (jamid)…")
|
||||
property string reconnectionFailed: qsTr("Could not re-connect to the Jami daemon (jamid).\nJami will now quit.")
|
||||
property string reconnectDaemon: qsTr("Attempting to reconnect to the Jami daemon (jamid)…")
|
||||
property string reconnectionFailed: qsTr("An error occurred while reconnecting to the Jami daemon (jamid).\nThe application will now exit.")
|
||||
|
||||
// Message view
|
||||
property string addEmoji: qsTr("Add emoji")
|
||||
@ -774,8 +778,8 @@ Item {
|
||||
property string edit: qsTr("Edit")
|
||||
property string edited: qsTr("Edited")
|
||||
property string joinCall: qsTr("Join call")
|
||||
property string joinInAudio: qsTr("Join in audio")
|
||||
property string joinInVideo: qsTr("Join in video")
|
||||
property string joinWithAudio: qsTr("Join with audio")
|
||||
property string joinWithVideo: qsTr("Join with video")
|
||||
property string startedACall: qsTr("Started a call")
|
||||
property string wantToJoin: qsTr("A call is in progress. Do you want to join the call?")
|
||||
property string needsHost: qsTr("Current host for this swarm seems unreachable. Do you want to host the call?")
|
||||
@ -790,28 +794,28 @@ Item {
|
||||
property string hideLocalVideo: qsTr("Hide local video")
|
||||
|
||||
// Invitation View
|
||||
property string invitationViewSentRequest: qsTr("%1 has sent you a request for a conversation.")
|
||||
property string invitationViewJoinConversation: qsTr("Hello,\nWould you like to join the conversation?")
|
||||
property string invitationViewAcceptedConversation: qsTr("You have accepted\nthe conversation request")
|
||||
property string invitationViewSentRequest: qsTr("%1 sent you a conversation invitation.")
|
||||
property string invitationViewJoinConversation: qsTr("Hello,\nDo you want to join this conversation?")
|
||||
property string invitationViewAcceptedConversation: qsTr("You have accepted\nthe conversation invitation.")
|
||||
property string invitationViewWaitingForSync: qsTr("Waiting until %1\nconnects to synchronize the conversation.")
|
||||
|
||||
// SwarmDetailsPanel
|
||||
property string members: qsTr("%1 Members")
|
||||
property string member: qsTr("Member")
|
||||
property string swarmName: qsTr("Swarm's name")
|
||||
property string contactName: qsTr("Contact's name")
|
||||
property string addADescription: qsTr("Add a description")
|
||||
property string swarmName: qsTr("Swarm name")
|
||||
property string contactName: qsTr("Contact name")
|
||||
property string addDescription: qsTr("Add description")
|
||||
|
||||
property string muteConversation: qsTr("Mute conversation")
|
||||
property string ignoreNotificationsTooltip: qsTr("Ignore all notifications from this conversation")
|
||||
property string chooseAColor: qsTr("Choose a color")
|
||||
property string chooseAColor: qsTr("Color")
|
||||
property string defaultCallHost: qsTr("Default host (calls)")
|
||||
property string leaveConversation: qsTr("Leave conversation")
|
||||
property string typeOfSwarm: qsTr("Type of swarm")
|
||||
property string typeOfSwarm: qsTr("Type")
|
||||
property string none: qsTr("None")
|
||||
|
||||
// NewSwarmPage
|
||||
property string createTheSwarm: qsTr("Create the swarm")
|
||||
property string createSwarm: qsTr("Create swarm")
|
||||
property string goToConversation: qsTr("Go to conversation")
|
||||
property string kickMember: qsTr("Kick member")
|
||||
property string reinstateMember: qsTr("Reinstate member")
|
||||
@ -864,20 +868,20 @@ Item {
|
||||
property string theme: qsTr("Theme")
|
||||
property string zoomLevel: qsTr("Text zoom level")
|
||||
|
||||
//Donation campaign
|
||||
// Donation campaign
|
||||
property string donationTipBoxText: qsTr("Free and private sharing. <a href=\"https://jami.net/whydonate/\">Donate</a> to expand it.")
|
||||
property string donation: qsTr("Donate")
|
||||
property string donationText: qsTr("If you enjoy using Jami and believe in our mission, would you make a donation?")
|
||||
property string notNow: qsTr("Not now")
|
||||
property string enableDonation: qsTr("Enable donation campaign")
|
||||
|
||||
//Chat setting page
|
||||
// Chat setting page
|
||||
property string enter: qsTr("Enter")
|
||||
property string shiftEnter: qsTr("Shift+Enter")
|
||||
property string textFormattingDescription: qsTr("Enter or Shift+Enter to insert a new line")
|
||||
property string textFormatting: qsTr("Text formatting")
|
||||
|
||||
//Connection monitoring
|
||||
// Connection monitoring
|
||||
property string connected: qsTr("Connected")
|
||||
property string connectingTLS: qsTr("Connecting TLS")
|
||||
property string connectingICE: qsTr("Connecting ICE")
|
||||
|
||||
@ -88,7 +88,7 @@ SidePanelBase {
|
||||
"visible": AppVersionManager.isUpdaterEnabled()
|
||||
}]
|
||||
}, {
|
||||
"title": JamiStrings.audioVideoSettingsTitle,
|
||||
"title": JamiStrings.mediaSettingsTitle,
|
||||
"icon": JamiResources.media_black_24dp_svg,
|
||||
"first": 12,
|
||||
"last": 14,
|
||||
@ -103,13 +103,13 @@ SidePanelBase {
|
||||
"title": JamiStrings.screenSharing
|
||||
}]
|
||||
}, {
|
||||
"title": JamiStrings.pluginSettingsTitle,
|
||||
"title": JamiStrings.extensionSettingsTitle,
|
||||
"icon": JamiResources.plugins_24dp_svg,
|
||||
"first": 15,
|
||||
"last": 15,
|
||||
"children": [{
|
||||
"id": 15,
|
||||
"title": JamiStrings.pluginSettingsTitle
|
||||
"title": JamiStrings.extensionSettingsTitle
|
||||
}]
|
||||
}];
|
||||
} else {
|
||||
@ -160,7 +160,7 @@ SidePanelBase {
|
||||
"title": JamiStrings.troubleshootTitle
|
||||
}]
|
||||
}, {
|
||||
"title": JamiStrings.audioVideoSettingsTitle,
|
||||
"title": JamiStrings.mediaSettingsTitle,
|
||||
"icon": JamiResources.media_black_24dp_svg,
|
||||
"first": 12,
|
||||
"last": 14,
|
||||
@ -175,13 +175,13 @@ SidePanelBase {
|
||||
"title": JamiStrings.screenSharing
|
||||
}]
|
||||
}, {
|
||||
"title": JamiStrings.pluginSettingsTitle,
|
||||
"title": JamiStrings.extensionSettingsTitle,
|
||||
"icon": JamiResources.plugins_24dp_svg,
|
||||
"first": 15,
|
||||
"last": 15,
|
||||
"children": [{
|
||||
"id": 15,
|
||||
"title": JamiStrings.pluginSettingsTitle
|
||||
"title": JamiStrings.extensionSettingsTitle
|
||||
}]
|
||||
}];
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ ColumnLayout {
|
||||
contactName: ContactName
|
||||
contactID: ContactID
|
||||
|
||||
btnImgSource: JamiStrings.optionUnban
|
||||
btnImgSource: JamiStrings.optionUnblock
|
||||
btnToolTip: JamiStrings.reinstateContact
|
||||
|
||||
onClicked: bannedListWidget.currentIndex = index
|
||||
|
||||
@ -10,10 +10,10 @@ import "../../commoncomponents"
|
||||
ColumnLayout {
|
||||
function installPlugin() {
|
||||
var dlg = viewCoordinator.presentDialog(appWindow, "commoncomponents/JamiFileDialog.qml", {
|
||||
"title": JamiStrings.selectPluginInstall,
|
||||
"title": JamiStrings.selectExtensionInstall,
|
||||
"fileMode": JamiFileDialog.OpenFile,
|
||||
"folder": StandardPaths.writableLocation(StandardPaths.DownloadLocation),
|
||||
"nameFilters": [JamiStrings.pluginFiles, JamiStrings.allFiles]
|
||||
"nameFilters": [JamiStrings.extensionFiles, JamiStrings.allFiles]
|
||||
});
|
||||
dlg.fileAccepted.connect(function (file) {
|
||||
var url = UtilsAdapter.getAbsPath(file.toString());
|
||||
@ -29,7 +29,7 @@ ColumnLayout {
|
||||
function presentErrorMessage() {
|
||||
viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
|
||||
"title": JamiStrings.installationFailed,
|
||||
"infoText": JamiStrings.pluginInstallationFailed,
|
||||
"infoText": JamiStrings.extensionInstallationFailed,
|
||||
"buttonStyles": [SimpleMessageDialog.ButtonStyle.TintedBlue],
|
||||
"buttonTitles": [JamiStrings.optionOk],
|
||||
"buttonCallBacks": [],
|
||||
|
||||
@ -53,7 +53,7 @@ BaseModalDialog {
|
||||
pinRectangle.visible = true
|
||||
exportedPIN.text = pin;
|
||||
} else {
|
||||
pinRectangle.success = false;
|
||||
infoLabel.success = false;
|
||||
infoLabel.visible = true;
|
||||
switch (status) {
|
||||
case NameDirectory.ExportOnRingStatus.WRONG_PASSWORD:
|
||||
|
||||
@ -44,7 +44,7 @@ ColumnLayout {
|
||||
} else {
|
||||
viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
|
||||
"title": JamiStrings.removeDevice,
|
||||
"infoText": JamiStrings.sureToRemoveDevice,
|
||||
"infoText": JamiStrings.confirmRemoveDevice,
|
||||
"buttonTitles": [JamiStrings.optionOk, JamiStrings.optionCancel],
|
||||
"buttonStyles": [SimpleMessageDialog.ButtonStyle.TintedBlue, SimpleMessageDialog.ButtonStyle.TintedBlack],
|
||||
"buttonCallBacks": [function () {
|
||||
|
||||
@ -387,7 +387,7 @@ SettingsPageBase {
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.preferredWidth: parent.width
|
||||
|
||||
text: JamiStrings.bannedContacts
|
||||
text: JamiStrings.blockedContacts
|
||||
color: JamiTheme.textColor
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
@ -60,7 +60,7 @@ ItemDelegate {
|
||||
function presentErrorMessage() {
|
||||
viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
|
||||
"title": JamiStrings.installationFailed,
|
||||
"infoText": JamiStrings.pluginInstallationFailed,
|
||||
"infoText": JamiStrings.extensionInstallationFailed,
|
||||
"buttonStyles": [SimpleMessageDialog.ButtonStyle.TintedBlue],
|
||||
"buttonTitles": [JamiStrings.optionOk],
|
||||
"buttonCallBacks": [],
|
||||
|
||||
@ -58,7 +58,7 @@ ItemDelegate {
|
||||
function presentErrorMessage() {
|
||||
viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
|
||||
"title": JamiStrings.installationFailed,
|
||||
"infoText": JamiStrings.pluginInstallationFailed,
|
||||
"infoText": JamiStrings.extensionInstallationFailed,
|
||||
"buttonStyles": [SimpleMessageDialog.ButtonStyle.TintedBlue],
|
||||
"buttonTitles": [JamiStrings.optionOk],
|
||||
"buttonCallBacks": []
|
||||
|
||||
@ -275,7 +275,7 @@ Rectangle {
|
||||
|
||||
onClicked: viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
|
||||
"title": JamiStrings.resetPreferences,
|
||||
"infoText": JamiStrings.pluginResetConfirmation.arg(pluginId),
|
||||
"infoText": JamiStrings.confirmExtensionReset.arg(pluginId),
|
||||
"buttonTitles": [JamiStrings.optionOk, JamiStrings.optionCancel],
|
||||
"buttonStyles": [SimpleMessageDialog.ButtonStyle.TintedBlue, SimpleMessageDialog.ButtonStyle.TintedBlack],
|
||||
"buttonCallBacks": [function () {
|
||||
|
||||
@ -204,7 +204,7 @@ Item {
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: JamiStrings.versionPlugin.arg(PluginVersion)
|
||||
text: JamiStrings.versionExtension.arg(PluginVersion)
|
||||
font.pixelSize: JamiTheme.headerFontSize
|
||||
font.kerning: true
|
||||
color: JamiTheme.textColor
|
||||
@ -273,13 +273,13 @@ Item {
|
||||
hoveredColor: JamiTheme.buttonTintedBlackHovered
|
||||
pressedColor: JamiTheme.buttonTintedBlackPressed
|
||||
tertiary: true
|
||||
toolTipText: JamiStrings.pluginUninstallConfirmation.arg(PluginId)
|
||||
toolTipText: JamiStrings.confirmExtensionUninstall.arg(PluginId)
|
||||
|
||||
text: JamiStrings.uninstall
|
||||
|
||||
onClicked: viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
|
||||
"title": JamiStrings.uninstallPlugin,
|
||||
"infoText": JamiStrings.pluginUninstallConfirmation.arg(PluginName),
|
||||
"title": JamiStrings.uninstallExtension,
|
||||
"infoText": JamiStrings.confirmExtensionUninstall.arg(PluginName),
|
||||
"buttonTitles": [JamiStrings.optionOk, JamiStrings.optionCancel],
|
||||
"buttonStyles": [SimpleMessageDialog.ButtonStyle.TintedBlue, SimpleMessageDialog.ButtonStyle.TintedBlack],
|
||||
"buttonCallBacks": [function () {
|
||||
|
||||
@ -25,7 +25,7 @@ import "../../commoncomponents"
|
||||
|
||||
SettingsPageBase {
|
||||
id: root
|
||||
title: JamiStrings.pluginSettingsTitle
|
||||
title: JamiStrings.extensionSettingsTitle
|
||||
onWidthChanged: resolvePanes()
|
||||
flickableContent: RowLayout {
|
||||
width: parent.width
|
||||
|
||||
@ -46,7 +46,7 @@ ColumnLayout {
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 20
|
||||
text: JamiStrings.pluginStoreTitle
|
||||
text: JamiStrings.extensionStoreTitle
|
||||
font.pixelSize: JamiTheme.settingsTitlePixelSize
|
||||
font.kerning: true
|
||||
color: JamiTheme.textColor
|
||||
@ -113,7 +113,7 @@ ColumnLayout {
|
||||
color: JamiTheme.textColor
|
||||
font.pixelSize: JamiTheme.bigFontSize
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: JamiStrings.pluginStoreNotAvailable
|
||||
text: JamiStrings.extensionStoreNotAvailable
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
|
||||
@ -111,7 +111,7 @@ SettingsPageBase {
|
||||
font.pointSize: 18
|
||||
font.capitalization: Font.AllUppercase
|
||||
color: "white"
|
||||
text: JamiStrings.noVideo
|
||||
text: JamiStrings.noCamera
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,14 +87,14 @@ TipsModel::reset()
|
||||
tips_.append({{"id", "1"},
|
||||
{"title", tr("What does Jami mean?")},
|
||||
{"desc",
|
||||
tr("The choice of the name Jami was inspired by the Swahili word 'jamii', which "
|
||||
"means 'community' as a noun and 'together' as an adverb.")},
|
||||
tr("The choice of the name Jami was inspired by the Swahili word “jamii”, which "
|
||||
"means “community” as a noun and “together” as an adverb.")},
|
||||
{"type", "tip"}});
|
||||
tips_.append({{"id", "2"},
|
||||
{"title", tr("What is the green dot next to my account?")},
|
||||
{"desc",
|
||||
tr("A red dot means that your account is disconnected from the network; it "
|
||||
"turns green when it's connected.")},
|
||||
"turns green when it’s connected.")},
|
||||
{"type", "tip"}});
|
||||
tips_.append(
|
||||
{{"id", "3"},
|
||||
@ -108,7 +108,7 @@ TipsModel::reset()
|
||||
{{"id", "4"},
|
||||
{"title", tr("Can I make a conference call?")},
|
||||
{"desc",
|
||||
tr("In a call, you can click on \"Add participants\" to add a contact to a call.")},
|
||||
tr("In a call, you can click on “Invite members” to add a contact to a call.")},
|
||||
{"type", "tip"}});
|
||||
tips_.append({{"id", "6"},
|
||||
{"title", tr("What is a Jami account?")},
|
||||
@ -124,7 +124,7 @@ TipsModel::reset()
|
||||
{"type", "tip"}});
|
||||
tips_.append(
|
||||
{{"id", "8"},
|
||||
{"title", tr("Why don't I have to use a password?")},
|
||||
{"title", tr("Why don’t I have to use a password?")},
|
||||
{"desc",
|
||||
tr("With Jami, your account is stored in a directory on your device. The password "
|
||||
"is only used to encrypt your account in order to protect you from someone "
|
||||
@ -132,7 +132,7 @@ TipsModel::reset()
|
||||
{"type", "tip"}});
|
||||
tips_.append(
|
||||
{{"id", "9"},
|
||||
{"title", tr("Why don't I have to register a username?")},
|
||||
{"title", tr("Why don’t I have to register a username?")},
|
||||
{"desc",
|
||||
tr("The most permanent, secure identifier is your Jami ID, but since these are difficult "
|
||||
"to use for some people, you also have the option of registering a username.")},
|
||||
|
||||
@ -420,8 +420,14 @@ Utils::contactPhoto(LRCInstance* instance,
|
||||
try {
|
||||
auto& accInfo = instance->accountModel().getAccountInfo(
|
||||
accountId.isEmpty() ? instance->get_currentAccountId() : accountId);
|
||||
auto contactInfo = accInfo.contactModel->getContact(contactUri);
|
||||
auto contactPhoto = accInfo.contactModel->avatar(contactUri);
|
||||
if (!contactPhoto.isEmpty()) {
|
||||
photo = imageFromBase64String(contactPhoto);
|
||||
if (!photo.isNull())
|
||||
return Utils::scaleAndFrame(photo, size);
|
||||
}
|
||||
// If no avatar is found, generate one
|
||||
auto contactInfo = accInfo.contactModel->getContact(contactUri);
|
||||
auto bestName = accInfo.contactModel->bestNameForContact(contactUri);
|
||||
if (accInfo.profileInfo.type == profile::Type::SIP
|
||||
&& contactInfo.profileInfo.type == profile::Type::TEMPORARY) {
|
||||
@ -429,12 +435,6 @@ Utils::contactPhoto(LRCInstance* instance,
|
||||
} else if (contactInfo.profileInfo.type == profile::Type::TEMPORARY
|
||||
&& contactInfo.profileInfo.uri.isEmpty()) {
|
||||
photo = Utils::fallbackAvatar(QString(), QString());
|
||||
} else if (!contactPhoto.isEmpty()) {
|
||||
photo = imageFromBase64String(contactPhoto);
|
||||
if (photo.isNull()) {
|
||||
auto avatarName = contactInfo.profileInfo.uri == bestName ? QString() : bestName;
|
||||
photo = Utils::fallbackAvatar("jami:" + contactInfo.profileInfo.uri, avatarName);
|
||||
}
|
||||
} else {
|
||||
auto avatarName = contactInfo.profileInfo.uri == bestName ? QString() : bestName;
|
||||
photo = Utils::fallbackAvatar("jami:" + contactInfo.profileInfo.uri, avatarName);
|
||||
@ -540,13 +540,20 @@ Utils::getCirclePhoto(const QImage original, int sizePhoto)
|
||||
Qt::KeepAspectRatioByExpanding,
|
||||
Qt::SmoothTransformation)
|
||||
.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
int margin = 0;
|
||||
int marginX = 0;
|
||||
int marginY = 0;
|
||||
|
||||
if (scaledPhoto.width() > sizePhoto) {
|
||||
margin = (scaledPhoto.width() - sizePhoto) / 2;
|
||||
marginX = (scaledPhoto.width() - sizePhoto) / 2;
|
||||
}
|
||||
if (scaledPhoto.height() > sizePhoto) {
|
||||
marginY = (scaledPhoto.height() - sizePhoto) / 2;
|
||||
}
|
||||
|
||||
painter.drawEllipse(0, 0, sizePhoto, sizePhoto);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
painter.drawImage(0, 0, scaledPhoto, margin, 0);
|
||||
painter.drawImage(0, 0, scaledPhoto, marginX, marginY);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
@ -612,7 +619,12 @@ Utils::getProjectCredits()
|
||||
return {};
|
||||
}
|
||||
QTextStream in(&projectCreditsFile);
|
||||
return in.readAll();
|
||||
return in.readAll().arg(
|
||||
QObject::tr("We would like to thank our contributors, whose efforts over many years have made this software what it is."),
|
||||
QObject::tr("Developers"), QObject::tr("Media"), QObject::tr("Community Management"), QObject::tr("Special thanks to"),
|
||||
QObject::tr("This is a list of people who have made a significant investment of time,\
|
||||
with useful results, into Jami. Any such contributors who wish to be added to the list \
|
||||
should contact us."));
|
||||
}
|
||||
|
||||
inline QString
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "systemtray.h"
|
||||
#include "utils.h"
|
||||
#include "version.h"
|
||||
#include "version_info.h"
|
||||
#include "global.h"
|
||||
|
||||
#include <api/datatransfermodel.h>
|
||||
@ -125,11 +126,17 @@ UtilsAdapter::getProjectCredits()
|
||||
}
|
||||
|
||||
const QString
|
||||
UtilsAdapter::getVersionStr()
|
||||
UtilsAdapter::getBuildIDStr()
|
||||
{
|
||||
return QString(VERSION_STRING);
|
||||
}
|
||||
|
||||
const QString
|
||||
UtilsAdapter::getVersionStr()
|
||||
{
|
||||
return APP_VERSION_STRING + "." + CORE_VERSION_STRING;
|
||||
}
|
||||
|
||||
void
|
||||
UtilsAdapter::setClipboardText(QString text)
|
||||
{
|
||||
|
||||
@ -96,6 +96,7 @@ public:
|
||||
Q_INVOKABLE void setToDefault(const Settings::Key key);
|
||||
|
||||
Q_INVOKABLE const QString getProjectCredits();
|
||||
Q_INVOKABLE const QString getBuildIDStr();
|
||||
Q_INVOKABLE const QString getVersionStr();
|
||||
Q_INVOKABLE void setClipboardText(QString text);
|
||||
Q_INVOKABLE const QString qStringFromFile(const QString& filename);
|
||||
|
||||
@ -275,6 +275,7 @@ set(LIBCLIENT_SOURCES
|
||||
# other
|
||||
avmodel.cpp
|
||||
pluginmodel.cpp
|
||||
interaction.cpp
|
||||
namedirectory.cpp
|
||||
renderer.cpp)
|
||||
|
||||
|
||||
@ -166,7 +166,6 @@ public Q_SLOTS:
|
||||
* @param ok
|
||||
*/
|
||||
void slotMigrationEnded(const QString& accountId, bool ok);
|
||||
|
||||
/**
|
||||
* Emit accountProfileReceived
|
||||
* @param accountId
|
||||
@ -176,7 +175,6 @@ public Q_SLOTS:
|
||||
void slotAccountProfileReceived(const QString& accountId,
|
||||
const QString& displayName,
|
||||
const QString& userPhoto);
|
||||
|
||||
/**
|
||||
* Emit new position
|
||||
* @param accountId
|
||||
@ -415,10 +413,6 @@ AccountModelPimpl::AccountModelPimpl(AccountModel& linked,
|
||||
&CallbacksHandler::migrationEnded,
|
||||
this,
|
||||
&AccountModelPimpl::slotMigrationEnded);
|
||||
connect(&callbacksHandler,
|
||||
&CallbacksHandler::accountProfileReceived,
|
||||
this,
|
||||
&AccountModelPimpl::slotAccountProfileReceived);
|
||||
connect(&callbacksHandler,
|
||||
&CallbacksHandler::newPosition,
|
||||
this,
|
||||
@ -434,8 +428,9 @@ AccountModelPimpl::updateAccounts()
|
||||
const auto previousAccountIdListSize = accountIdList.size();
|
||||
accountIdList = configurationManager.getAccountList();
|
||||
|
||||
// If this is just a reordering of the accounts, don't do anything
|
||||
// If this is just a reordering of the accounts, just notify the view.
|
||||
if (accountIdList.size() == previousAccountIdListSize) {
|
||||
Q_EMIT linked.accountsReordered();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -531,11 +526,12 @@ AccountModelPimpl::slotAccountStatusChanged(const QString& accountID,
|
||||
if (status != api::account::Status::INITIALIZING
|
||||
&& accountInfo.status == api::account::Status::INITIALIZING) {
|
||||
// Detect when a new account is generated (keys are ready). During
|
||||
// the generation, a Ring account got the "INITIALIZING" status.
|
||||
// the generation, an account got the "INITIALIZING" status.
|
||||
// When keys are generated, the status will change.
|
||||
// The account is already added and initialized. Just update details from daemon
|
||||
updateAccountDetails(accountInfo);
|
||||
// This will load swarms as the account was not loaded before.
|
||||
accountInfo.contactModel->initContacts();
|
||||
accountInfo.conversationModel->initConversations();
|
||||
Q_EMIT linked.accountAdded(accountID);
|
||||
} else if (!accountInfo.profileInfo.uri.isEmpty()) {
|
||||
@ -690,25 +686,6 @@ AccountModelPimpl::slotMigrationEnded(const QString& accountId, bool ok)
|
||||
Q_EMIT linked.migrationEnded(accountId, ok);
|
||||
}
|
||||
|
||||
void
|
||||
AccountModelPimpl::slotAccountProfileReceived(const QString& accountId,
|
||||
const QString& displayName,
|
||||
const QString& userPhoto)
|
||||
{
|
||||
LC_WARN << accountId << displayName;
|
||||
|
||||
auto account = accounts.find(accountId);
|
||||
if (account == accounts.end())
|
||||
return;
|
||||
auto& accountInfo = account->second.first;
|
||||
accountInfo.profileInfo.avatar = userPhoto;
|
||||
accountInfo.profileInfo.alias = displayName;
|
||||
|
||||
storage::vcard::setProfile(accountInfo.id, accountInfo.profileInfo);
|
||||
|
||||
Q_EMIT linked.profileUpdated(accountId);
|
||||
}
|
||||
|
||||
void
|
||||
AccountModelPimpl::slotNewPosition(const QString& accountId,
|
||||
const QString& peerId,
|
||||
@ -719,6 +696,24 @@ AccountModelPimpl::slotNewPosition(const QString& accountId,
|
||||
Q_EMIT linked.newPosition(accountId, peerId, body, timestamp, daemonId);
|
||||
}
|
||||
|
||||
void
|
||||
AccountModelPimpl::slotAccountProfileReceived(const QString& accountId,
|
||||
const QString& displayName,
|
||||
const QString& userPhoto)
|
||||
{
|
||||
LC_WARN << accountId << displayName;
|
||||
auto account = accounts.find(accountId);
|
||||
if (account == accounts.end() || userPhoto.isEmpty())
|
||||
return;
|
||||
// NOTE: This signal is still used for JAMS account where the avatar is
|
||||
// retrieven from the server. In this case we MUST save it.
|
||||
auto& accountInfo = account->second.first;
|
||||
accountInfo.profileInfo.avatar = userPhoto;
|
||||
accountInfo.profileInfo.alias = displayName;
|
||||
storage::vcard::setProfile(accountInfo.id, accountInfo.profileInfo);
|
||||
Q_EMIT linked.profileUpdated(accountId);
|
||||
}
|
||||
|
||||
void
|
||||
AccountModelPimpl::addToAccounts(const QString& accountId)
|
||||
{
|
||||
|
||||
@ -288,6 +288,10 @@ Q_SIGNALS:
|
||||
* @param accountID
|
||||
*/
|
||||
void accountRemoved(const QString& accountID);
|
||||
/**
|
||||
* Emitted when the account list order has changed.
|
||||
*/
|
||||
void accountsReordered();
|
||||
/**
|
||||
* Connect this signal to know when an account was updated.
|
||||
* @param accountID
|
||||
|
||||
@ -168,8 +168,12 @@ struct Info
|
||||
if (media[MediaAttributeKey::MEDIA_TYPE] == Details::MEDIA_TYPE_VIDEO) {
|
||||
if (media[MediaAttributeKey::SOURCE].startsWith(VideoProtocolPrefix::DISPLAY)
|
||||
|| media[MediaAttributeKey::SOURCE].startsWith(VideoProtocolPrefix::FILE)) {
|
||||
callInfo["is_sharing"] = true;
|
||||
callInfo["preview_id"] = media[MediaAttributeKey::SOURCE];
|
||||
if (media[MediaAttributeKey::MUTED] == TRUE_STR) {
|
||||
callInfo["is_sharing"] = false;
|
||||
} else {
|
||||
callInfo["is_sharing"] = true;
|
||||
previewId = media[MediaAttributeKey::SOURCE];
|
||||
}
|
||||
}
|
||||
if (media[MediaAttributeKey::ENABLED] == TRUE_STR
|
||||
&& media[MediaAttributeKey::MUTED] == FALSE_STR && previewId.isEmpty()) {
|
||||
|
||||
@ -62,6 +62,8 @@ public:
|
||||
const BehaviorController& behaviorController);
|
||||
~ContactModel();
|
||||
|
||||
void initContacts();
|
||||
|
||||
/**
|
||||
* Ask the daemon to add a contact.
|
||||
* @param contactInfo
|
||||
|
||||
@ -38,7 +38,7 @@ namespace api {
|
||||
class BehaviorController;
|
||||
|
||||
namespace datatransfer {
|
||||
class Info;
|
||||
struct Info;
|
||||
} // namespace datatransfer
|
||||
|
||||
/**
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include <ctime>
|
||||
#include "typedefs.h"
|
||||
@ -119,6 +120,12 @@ enum class Status {
|
||||
FAILURE,
|
||||
SUCCESS,
|
||||
DISPLAYED,
|
||||
COUNT__
|
||||
};
|
||||
Q_ENUM_NS(Status)
|
||||
|
||||
enum class TransferStatus {
|
||||
INVALID,
|
||||
TRANSFER_CREATED,
|
||||
TRANSFER_ACCEPTED,
|
||||
TRANSFER_CANCELED,
|
||||
@ -131,7 +138,7 @@ enum class Status {
|
||||
TRANSFER_FINISHED,
|
||||
COUNT__
|
||||
};
|
||||
Q_ENUM_NS(Status)
|
||||
Q_ENUM_NS(TransferStatus)
|
||||
|
||||
static inline const QString
|
||||
to_string(const Status& status)
|
||||
@ -147,26 +154,6 @@ to_string(const Status& status)
|
||||
return "SUCCESS";
|
||||
case Status::DISPLAYED:
|
||||
return "DISPLAYED";
|
||||
case Status::TRANSFER_CREATED:
|
||||
return "TRANSFER_CREATED";
|
||||
case Status::TRANSFER_ACCEPTED:
|
||||
return "TRANSFER_ACCEPTED";
|
||||
case Status::TRANSFER_CANCELED:
|
||||
return "TRANSFER_CANCELED";
|
||||
case Status::TRANSFER_ERROR:
|
||||
return "TRANSFER_ERROR";
|
||||
case Status::TRANSFER_UNJOINABLE_PEER:
|
||||
return "TRANSFER_UNJOINABLE_PEER";
|
||||
case Status::TRANSFER_ONGOING:
|
||||
return "TRANSFER_ONGOING";
|
||||
case Status::TRANSFER_AWAITING_HOST:
|
||||
return "TRANSFER_AWAITING_HOST";
|
||||
case Status::TRANSFER_AWAITING_PEER:
|
||||
return "TRANSFER_AWAITING_PEER";
|
||||
case Status::TRANSFER_TIMEOUT_EXPIRED:
|
||||
return "TRANSFER_TIMEOUT_EXPIRED";
|
||||
case Status::TRANSFER_FINISHED:
|
||||
return "TRANSFER_FINISHED";
|
||||
case Status::INVALID:
|
||||
case Status::COUNT__:
|
||||
default:
|
||||
@ -187,30 +174,68 @@ to_status(const QString& status)
|
||||
return Status::SUCCESS;
|
||||
else if (status == "DISPLAYED")
|
||||
return Status::DISPLAYED;
|
||||
else if (status == "TRANSFER_CREATED")
|
||||
return Status::TRANSFER_CREATED;
|
||||
else if (status == "TRANSFER_ACCEPTED")
|
||||
return Status::TRANSFER_ACCEPTED;
|
||||
else if (status == "TRANSFER_CANCELED")
|
||||
return Status::TRANSFER_CANCELED;
|
||||
else if (status == "TRANSFER_ERROR")
|
||||
return Status::TRANSFER_ERROR;
|
||||
else if (status == "TRANSFER_UNJOINABLE_PEER")
|
||||
return Status::TRANSFER_UNJOINABLE_PEER;
|
||||
else if (status == "TRANSFER_ONGOING")
|
||||
return Status::TRANSFER_ONGOING;
|
||||
else if (status == "TRANSFER_AWAITING_HOST")
|
||||
return Status::TRANSFER_AWAITING_HOST;
|
||||
else if (status == "TRANSFER_AWAITING_PEER")
|
||||
return Status::TRANSFER_AWAITING_PEER;
|
||||
else if (status == "TRANSFER_TIMEOUT_EXPIRED")
|
||||
return Status::TRANSFER_TIMEOUT_EXPIRED;
|
||||
else if (status == "TRANSFER_FINISHED")
|
||||
return Status::TRANSFER_FINISHED;
|
||||
else
|
||||
return Status::INVALID;
|
||||
}
|
||||
|
||||
static inline const QString
|
||||
to_string(const TransferStatus& status)
|
||||
{
|
||||
switch (status) {
|
||||
case TransferStatus::TRANSFER_CREATED:
|
||||
return "TRANSFER_CREATED";
|
||||
case TransferStatus::TRANSFER_ACCEPTED:
|
||||
return "TRANSFER_ACCEPTED";
|
||||
case TransferStatus::TRANSFER_CANCELED:
|
||||
return "TRANSFER_CANCELED";
|
||||
case TransferStatus::TRANSFER_ERROR:
|
||||
return "TRANSFER_ERROR";
|
||||
case TransferStatus::TRANSFER_UNJOINABLE_PEER:
|
||||
return "TRANSFER_UNJOINABLE_PEER";
|
||||
case TransferStatus::TRANSFER_ONGOING:
|
||||
return "TRANSFER_ONGOING";
|
||||
case TransferStatus::TRANSFER_AWAITING_HOST:
|
||||
return "TRANSFER_AWAITING_HOST";
|
||||
case TransferStatus::TRANSFER_AWAITING_PEER:
|
||||
return "TRANSFER_AWAITING_PEER";
|
||||
case TransferStatus::TRANSFER_TIMEOUT_EXPIRED:
|
||||
return "TRANSFER_TIMEOUT_EXPIRED";
|
||||
case TransferStatus::TRANSFER_FINISHED:
|
||||
return "TRANSFER_FINISHED";
|
||||
case TransferStatus::INVALID:
|
||||
case TransferStatus::COUNT__:
|
||||
default:
|
||||
return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
static inline TransferStatus
|
||||
to_transferStatus(const QString& status)
|
||||
{
|
||||
if (status == "TRANSFER_CREATED")
|
||||
return TransferStatus::TRANSFER_CREATED;
|
||||
else if (status == "TRANSFER_ACCEPTED")
|
||||
return TransferStatus::TRANSFER_ACCEPTED;
|
||||
else if (status == "TRANSFER_CANCELED")
|
||||
return TransferStatus::TRANSFER_CANCELED;
|
||||
else if (status == "TRANSFER_ERROR")
|
||||
return TransferStatus::TRANSFER_ERROR;
|
||||
else if (status == "TRANSFER_UNJOINABLE_PEER")
|
||||
return TransferStatus::TRANSFER_UNJOINABLE_PEER;
|
||||
else if (status == "TRANSFER_ONGOING")
|
||||
return TransferStatus::TRANSFER_ONGOING;
|
||||
else if (status == "TRANSFER_AWAITING_HOST")
|
||||
return TransferStatus::TRANSFER_AWAITING_HOST;
|
||||
else if (status == "TRANSFER_AWAITING_PEER")
|
||||
return TransferStatus::TRANSFER_AWAITING_PEER;
|
||||
else if (status == "TRANSFER_TIMEOUT_EXPIRED")
|
||||
return TransferStatus::TRANSFER_TIMEOUT_EXPIRED;
|
||||
else if (status == "TRANSFER_FINISHED")
|
||||
return TransferStatus::TRANSFER_FINISHED;
|
||||
else
|
||||
return TransferStatus::INVALID;
|
||||
}
|
||||
|
||||
enum class ContactAction { ADD, JOIN, LEAVE, BANNED, UNBANNED, INVALID };
|
||||
Q_ENUM_NS(ContactAction)
|
||||
|
||||
@ -366,6 +391,7 @@ public:
|
||||
* @var duration
|
||||
* @var type
|
||||
* @var status
|
||||
* @var transferStatus
|
||||
* @var isRead
|
||||
* @var commit
|
||||
* @var linkPreviewInfo
|
||||
@ -381,6 +407,7 @@ struct Info
|
||||
std::time_t duration = 0;
|
||||
Type type = Type::INVALID;
|
||||
Status status = Status::INVALID;
|
||||
TransferStatus transferStatus = TransferStatus::INVALID;
|
||||
bool isRead = false;
|
||||
MapStringString commit;
|
||||
QVariantMap linkPreviewInfo = {};
|
||||
@ -397,108 +424,37 @@ struct Info
|
||||
std::time_t duration,
|
||||
Type type,
|
||||
Status status,
|
||||
bool isRead)
|
||||
{
|
||||
this->authorUri = authorUri;
|
||||
this->body = body;
|
||||
this->timestamp = timestamp;
|
||||
this->duration = duration;
|
||||
this->type = type;
|
||||
this->status = status;
|
||||
this->isRead = isRead;
|
||||
}
|
||||
bool isRead,
|
||||
TransferStatus transferStatus = TransferStatus::INVALID);
|
||||
|
||||
static Info contact(const QString& authorUri, std::time_t timestamp);
|
||||
|
||||
Info(const Info& other) = default;
|
||||
Info(Info&& other) = default;
|
||||
Info& operator=(const Info& other) = delete;
|
||||
Info& operator=(Info&& other) = default;
|
||||
|
||||
bool sent() const
|
||||
{
|
||||
return status == Status::SUCCESS || status == Status::DISPLAYED || status == Status::TRANSFER_FINISHED;
|
||||
}
|
||||
bool sent() const;
|
||||
|
||||
void init(const MapStringString& message, const QString& accountURI)
|
||||
{
|
||||
type = to_type(message["type"]);
|
||||
if (message.contains("react-to") && type == Type::TEXT) {
|
||||
type = to_type("REACTION");
|
||||
react_to = message["react-to"];
|
||||
}
|
||||
authorUri = message["author"];
|
||||
void init(const MapStringString& message,
|
||||
const QString& accountURI,
|
||||
const QString& accountId,
|
||||
const QString& conversationId);
|
||||
|
||||
if (type == Type::TEXT) {
|
||||
body = message["body"];
|
||||
}
|
||||
timestamp = message["timestamp"].toInt();
|
||||
status = Status::SUCCESS;
|
||||
parentId = message["linearizedParent"];
|
||||
isRead = false;
|
||||
if (type == Type::CONTACT) {
|
||||
authorUri = accountURI == message["uri"] ? "" : message["uri"];
|
||||
} else if (type == Type::INITIAL) {
|
||||
if (message["mode"] == "0") {
|
||||
body = QObject::tr("Private conversation created");
|
||||
} else {
|
||||
body = QObject::tr("Swarm created");
|
||||
}
|
||||
} else if (type == Type::CALL) {
|
||||
duration = message["duration"].toInt() / 1000;
|
||||
if (message.contains("confId"))
|
||||
confId = message["confId"];
|
||||
}
|
||||
commit = message;
|
||||
}
|
||||
// NOTE: The `accountId` and `conversationId` arguments are only used for messages of
|
||||
// type DATA_TRANSFER. They can therefore be omitted if the caller knows that `message`
|
||||
// is of a different type. They must be provided otherwise, as failure to do so would
|
||||
// result in the `body` and `transferStatus` fields of the returned Info struct to
|
||||
// contain incorrect information whenever `message` is of type DATA_TRANSFER.
|
||||
Info(const MapStringString& message,
|
||||
const QString& accountURI,
|
||||
const QString& accountId = "",
|
||||
const QString& conversationId = "");
|
||||
|
||||
Info(const MapStringString& message, const QString& accountURI)
|
||||
{
|
||||
init(message, accountURI);
|
||||
}
|
||||
|
||||
Info(const SwarmMessage& msg, const QString& accountUri)
|
||||
{
|
||||
MapStringString msgBody;
|
||||
for (auto it = msg.body.cbegin(); it != msg.body.cend(); ++it) {
|
||||
const auto& key = it.key();
|
||||
const auto& value = it.value();
|
||||
msgBody.insert(key, value);
|
||||
}
|
||||
init(msgBody, accountUri);
|
||||
parentId = msg.linearizedParent;
|
||||
type = to_type(msg.type);
|
||||
for (const auto& edition : msg.editions)
|
||||
previousBodies.append(Body {edition.value("id"),
|
||||
edition.value("body"),
|
||||
QString(edition.value("timestamp")).toInt()});
|
||||
QMap<QString, QVariantList> mapStringEmoji;
|
||||
for (const auto& reaction : msg.reactions) {
|
||||
auto author = reaction.value("author");
|
||||
auto body = reaction.value("body");
|
||||
auto emoji = Emoji {reaction.value("id"), body};
|
||||
QVariant variant = QVariant::fromValue(emoji);
|
||||
mapStringEmoji[author].append(variant);
|
||||
}
|
||||
for (auto i = mapStringEmoji.begin(); i != mapStringEmoji.end(); i++)
|
||||
reactions.insert(i.key(), i.value());
|
||||
// Compute the status of the message.
|
||||
// Basically, we got the status per member.
|
||||
// We consider the message as sent if at least one member has received it or displayed if
|
||||
// someone displayed it.
|
||||
auto maxStatus = 0;
|
||||
status = Status::SENDING;
|
||||
for (const auto& member : msg.status.keys()) {
|
||||
if (member == accountUri)
|
||||
continue;
|
||||
auto stValue = msg.status.value(member);
|
||||
if (stValue > maxStatus) {
|
||||
maxStatus = stValue;
|
||||
status = maxStatus <= 1 ? Status::SENDING
|
||||
: (stValue == 2 ? Status::SUCCESS : Status::DISPLAYED);
|
||||
}
|
||||
if (maxStatus == 3)
|
||||
break;
|
||||
}
|
||||
}
|
||||
Info(const SwarmMessage& msg,
|
||||
const QString& accountUri,
|
||||
const QString& accountId,
|
||||
const QString& conversationId);
|
||||
};
|
||||
|
||||
static inline bool
|
||||
|
||||
@ -40,6 +40,7 @@ struct Info;
|
||||
X(Duration) \
|
||||
X(Type) \
|
||||
X(Status) \
|
||||
X(TransferStatus) \
|
||||
X(IsRead) \
|
||||
X(ContactAction) \
|
||||
X(ActionUri) \
|
||||
@ -54,6 +55,7 @@ struct Info;
|
||||
X(ReplyToAuthor) \
|
||||
X(TotalSize) \
|
||||
X(TransferName) \
|
||||
X(TID) \
|
||||
X(FileExtension) \
|
||||
X(Readers) \
|
||||
X(IsEmojiOnly) \
|
||||
@ -101,6 +103,7 @@ public:
|
||||
bool append(const QString& id, const interaction::Info& interaction);
|
||||
bool update(const QString& id, const interaction::Info& interaction);
|
||||
bool updateStatus(const QString& id, interaction::Status newStatus, const QString& newBody = {});
|
||||
bool updateTransferStatus(const QString& id, interaction::TransferStatus newStatus, const QString& newBody = {});
|
||||
QPair<bool, bool> addOrUpdate(const QString& id, const interaction::Info& interaction);
|
||||
|
||||
// Thread-safe access to interactions.
|
||||
|
||||
@ -482,14 +482,7 @@ beginConversationWithPeer(Database& db,
|
||||
db.insertInto("conversations",
|
||||
{{":id", "id"}, {":participant", "participant"}},
|
||||
{{":id", newConversationsId}, {":participant", peer_uri}});
|
||||
api::interaction::Info msg {isOutgoing ? "" : peer_uri,
|
||||
{},
|
||||
timestamp ? timestamp : std::time(nullptr),
|
||||
0,
|
||||
api::interaction::Type::CONTACT,
|
||||
isOutgoing ? api::interaction::Status::SUCCESS
|
||||
: api::interaction::Status::UNKNOWN,
|
||||
isOutgoing};
|
||||
api::interaction::Info msg = api::interaction::Info::contact(isOutgoing ? "" : peer_uri, timestamp);
|
||||
// Add first interaction
|
||||
addMessageToConversation(db, newConversationsId, msg);
|
||||
return newConversationsId;
|
||||
@ -696,9 +689,9 @@ updateDataTransferInteractionForDaemonId(Database& db,
|
||||
return;
|
||||
}
|
||||
auto body = result[0];
|
||||
auto status = api::interaction::to_status(result[1]);
|
||||
auto status = api::interaction::to_transferStatus(result[1]);
|
||||
interaction.body = body;
|
||||
interaction.status = status;
|
||||
interaction.transferStatus = status;
|
||||
}
|
||||
|
||||
QString
|
||||
@ -731,6 +724,16 @@ updateInteractionStatus(Database& db, const QString& id, api::interaction::Statu
|
||||
{{":id", id}});
|
||||
}
|
||||
|
||||
void
|
||||
updateInteractionTransferStatus(Database& db, const QString& id, api::interaction::TransferStatus newStatus)
|
||||
{
|
||||
db.update("interactions",
|
||||
{"status=:status"},
|
||||
{{":status", api::interaction::to_string(newStatus)}},
|
||||
"id=:id",
|
||||
{{":id", id}});
|
||||
}
|
||||
|
||||
void
|
||||
setInteractionRead(Database& db, const QString& id)
|
||||
{
|
||||
|
||||
@ -310,6 +310,7 @@ void updateInteractionBody(Database& db, const QString& id, const QString& newBo
|
||||
* @param isRead
|
||||
*/
|
||||
void updateInteractionStatus(Database& db, const QString& id, api::interaction::Status newStatus);
|
||||
void updateInteractionTransferStatus(Database& db, const QString& id, api::interaction::TransferStatus newStatus);
|
||||
|
||||
/**
|
||||
* Set interaction to the read state
|
||||
|
||||
@ -663,14 +663,6 @@ CallbacksHandler::slotKnownDevicesChanged(const QString& accountId, const MapStr
|
||||
Q_EMIT knownDevicesChanged(accountId, devices);
|
||||
}
|
||||
|
||||
void
|
||||
CallbacksHandler::slotDeviceRevokationEnded(const QString& accountId,
|
||||
const QString& deviceId,
|
||||
const int status)
|
||||
{
|
||||
Q_EMIT deviceRevocationEnded(accountId, deviceId, status);
|
||||
}
|
||||
|
||||
void
|
||||
CallbacksHandler::slotAccountProfileReceived(const QString& accountId,
|
||||
const QString& displayName,
|
||||
@ -679,6 +671,14 @@ CallbacksHandler::slotAccountProfileReceived(const QString& accountId,
|
||||
Q_EMIT accountProfileReceived(accountId, displayName, userPhoto);
|
||||
}
|
||||
|
||||
void
|
||||
CallbacksHandler::slotDeviceRevokationEnded(const QString& accountId,
|
||||
const QString& deviceId,
|
||||
const int status)
|
||||
{
|
||||
Q_EMIT deviceRevocationEnded(accountId, deviceId, status);
|
||||
}
|
||||
|
||||
void
|
||||
CallbacksHandler::slotExportOnRingEnded(const QString& accountId, int status, const QString& pin)
|
||||
{
|
||||
|
||||
@ -145,12 +145,6 @@ public:
|
||||
|
||||
QStringList getCallIds();
|
||||
|
||||
/**
|
||||
* Send the profile VCard into a call
|
||||
* @param callId
|
||||
*/
|
||||
void sendProfile(const QString& callId);
|
||||
|
||||
CallModel::CallInfoMap calls;
|
||||
CallModel::CallParticipantsModelMap participantsModel;
|
||||
const CallbacksHandler& callbacksHandler;
|
||||
@ -1550,7 +1544,6 @@ CallModelPimpl::slotCallStateChanged(const QString& accountId,
|
||||
|| previousStatus == call::Status::OUTGOING_RINGING) {
|
||||
call->startTime = std::chrono::steady_clock::now();
|
||||
Q_EMIT linked.callStarted(callId);
|
||||
sendProfile(callId);
|
||||
}
|
||||
// Add to calls if in pendingConferences_
|
||||
for (int i = 0; i < pendingConferencees_.size(); ++i) {
|
||||
@ -1783,31 +1776,6 @@ CallModelPimpl::slotConferenceChanged(const QString& accountId,
|
||||
Q_EMIT linked.currentCallChanged(currentCall_);
|
||||
}
|
||||
|
||||
void
|
||||
CallModelPimpl::sendProfile(const QString& callId)
|
||||
{
|
||||
auto vCard = linked.owner.accountModel->accountVCard(linked.owner.id);
|
||||
|
||||
std::random_device rdev;
|
||||
auto key = std::to_string(dis(rdev));
|
||||
|
||||
int i = 0;
|
||||
int total = vCard.size() / 1000 + (vCard.size() % 1000 ? 1 : 0);
|
||||
while (vCard.size()) {
|
||||
auto sizeLimit = std::min(1000, static_cast<int>(vCard.size()));
|
||||
MapStringString chunk;
|
||||
chunk[QString("%1; id=%2,part=%3,of=%4")
|
||||
.arg(lrc::vCard::PROFILE_VCF)
|
||||
.arg(key.c_str())
|
||||
.arg(QString::number(i + 1))
|
||||
.arg(QString::number(total))]
|
||||
= vCard.left(sizeLimit);
|
||||
vCard.remove(0, sizeLimit);
|
||||
++i;
|
||||
CallManager::instance().sendTextMessage(linked.owner.id, callId, chunk, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CallModelPimpl::onRemoteRecordingChanged(const QString& callId, const QString& peerUri, bool state)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user