mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-10-30 07:53:33 +08:00
Compare commits
138 Commits
stable/202
...
beta/20241
| Author | SHA1 | Date | |
|---|---|---|---|
| 9771e291c8 | |||
| b37720e27f | |||
| d3a7df2f18 | |||
| 6093689cc4 | |||
| d188284245 | |||
| a01b578099 | |||
| 04fca1fc75 | |||
| a5621a1af1 | |||
| a1c2b8adef | |||
| 7424227f00 | |||
| b69d703e56 | |||
| bfe9128755 | |||
| 8b17b9e3cf | |||
| c2d5c3b764 | |||
| 41f5d151d9 | |||
| 542bd54c6b | |||
| eb60b68747 | |||
| 950e32e9a6 | |||
| 6ddd6a7f9e | |||
| 9ab5e52c8d | |||
| 56401d4125 | |||
| 7fdd2f5740 | |||
| 0f7e33cf33 | |||
| 73258efdf7 | |||
| a29d5f791f | |||
| 5186c27325 | |||
| 7e926a3e23 | |||
| 93cde493d8 | |||
| cb829676e3 | |||
| 112c6a4d7a | |||
| 188f487695 | |||
| 0af01cc62d | |||
| a8acc71830 | |||
| eaf409d6d3 | |||
| 42e3eeabf6 | |||
| 41cb6528c2 | |||
| b6aa9eedfa | |||
| 3c1b2c22b2 | |||
| fb660b928f | |||
| 2f163846c7 | |||
| 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 | |||
| 3b9fb0bfca | |||
| 3673b0646c | |||
| 2e2f6423f8 | |||
| 28c1cbbb34 | |||
| 87c215deb7 | |||
| 77eddcd962 | |||
| 043a715c59 | |||
| 5bd3ead22d | |||
| a9aa1cac80 | |||
| 409ba70258 | |||
| dc50f19815 | |||
| d83895dcc9 | |||
| e24a3d6a4d | |||
| 06de33e1be | |||
| c8fbcd8c6b | |||
| 31269fe8fc | |||
| a676ad395a | |||
| 04c71d02e0 | |||
| 1fe60b9c33 | |||
| 51ef7a83da | |||
| 588a8abdac | |||
| 8a149b6c4f | |||
| 6105f4f7ce | |||
| 92341b27b6 | |||
| f39afdac4c | |||
| 690f2dd85c | |||
| bd45d6a406 | |||
| 5b92e4708a |
13
.gitignore
vendored
13
.gitignore
vendored
@ -1,9 +1,18 @@
|
||||
*.user
|
||||
doc/Doxyfile
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/**/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
**/.history
|
||||
|
||||
GeneratedFiles/
|
||||
.vs/
|
||||
.vscode/
|
||||
x64/
|
||||
x86/
|
||||
[wW]in32/
|
||||
|
||||
49
.vscode/launch.json
vendored
Normal file
49
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Jami-Client-Debug",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"linux":{
|
||||
"MIMode": "gdb",
|
||||
"program": "${workspaceFolder}/build/jami",
|
||||
"args": [
|
||||
"-d",
|
||||
],
|
||||
},
|
||||
"osx": {
|
||||
"MIMode": "lldb",
|
||||
"program": "${workspaceFolder}/build/Jami.app/Contents/MacOS/Jami",
|
||||
"environment": [
|
||||
{
|
||||
"name": "NO_COLOR",
|
||||
"value": "true",
|
||||
}
|
||||
],
|
||||
},
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "cmake-build",
|
||||
"externalConsole": false, // A macOS dev may want to set this to true.
|
||||
},
|
||||
{
|
||||
// Using this configuration will require manually reconfiguring the project using
|
||||
// build.py --no-libwrap, otherwise the daemon executable will not be built and the
|
||||
// client will not be built with ENABLE_LIBWRAP=False.
|
||||
"name": "Jami-Daemon-Debug",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"linux": {
|
||||
"MIMode": "gdb",
|
||||
"program": "${workspaceFolder}/daemon/bin/dbus/jamid",
|
||||
},
|
||||
"program": "",
|
||||
"args": [
|
||||
"-cdp",
|
||||
],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "cmake-build",
|
||||
}
|
||||
]
|
||||
}
|
||||
15
.vscode/settings.json
vendored
Normal file
15
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"C_Cpp.default.includePath": [
|
||||
"${default}",
|
||||
"${workspaceFolder}/**",
|
||||
"/usr/lib/libqt-jami/include/**",
|
||||
"/usr/lib64/qt-jami/include/**",
|
||||
],
|
||||
"C_Cpp.default.cppStandard": "c++17",
|
||||
"C_Cpp.default.cStandard": "c11",
|
||||
"cmake.configureOnOpen": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "xaver.clang-format",
|
||||
"files.eol": "\n",
|
||||
"cSpell.enabled": false,
|
||||
}
|
||||
93
.vscode/tasks.json
vendored
Normal file
93
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "run-tests",
|
||||
"type": "shell",
|
||||
"command": "ctest",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/build/tests",
|
||||
"env": {
|
||||
"HOME": "/tmp"
|
||||
}
|
||||
},
|
||||
"args": [
|
||||
"-V",
|
||||
"-R"
|
||||
],
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Run the tests using CTest."
|
||||
},
|
||||
{
|
||||
"label": "cmake-configure",
|
||||
"type": "shell",
|
||||
"command": "cmake",
|
||||
"args": [
|
||||
"-S", ".",
|
||||
"-B", "build",
|
||||
"-DCMAKE_BUILD_TYPE=Debug",
|
||||
"-DCMAKE_PREFIX_PATH=\"/usr/lib64/qt-jami;/usr/lib/libqt-jami\"",
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"detail": "Generate the build system files with CMake."
|
||||
},
|
||||
{
|
||||
"label": "cmake-configure-tests",
|
||||
"type": "shell",
|
||||
"command": "cmake",
|
||||
"args": [
|
||||
"-S", ".",
|
||||
"-B", "build",
|
||||
"-DBUILD_TESTING=${input:buildTestingInput}"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"detail": "Generate the build system files with CMake."
|
||||
},
|
||||
{
|
||||
"label": "cmake-build",
|
||||
"type": "shell",
|
||||
"command": "cmake",
|
||||
"args": [
|
||||
"--build", "build",
|
||||
"-j$(nproc)",
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"detail": "Compile the project using the generated build system.",
|
||||
"dependsOn": [
|
||||
"cmake-configure"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "cmake-clean",
|
||||
"type": "shell",
|
||||
"command": "rm",
|
||||
"args": [
|
||||
"-rf",
|
||||
"build"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"detail": "Clean the build directory."
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "buildTestingInput",
|
||||
"type": "pickString",
|
||||
"description": "Do you want to enable testing?",
|
||||
"options": ["True", "False"],
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -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})
|
||||
|
||||
25
INSTALL.md
25
INSTALL.md
@ -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
|
||||
|
||||
@ -288,7 +288,7 @@ Once the build has finished, you should then be able to use the Visual Studio So
|
||||
|
||||
**Set up**
|
||||
|
||||
- macOS minimum version 10.15
|
||||
- macOS minimum version 11.0
|
||||
- install python3
|
||||
- download xcode
|
||||
- install Qt 6.6
|
||||
@ -343,9 +343,24 @@ Built client could be find in `build/Jami`
|
||||
|
||||
- These environment variables will be temporarily set when using build-windows.py to run tests.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Build errors may occur if daemon dependencies have been updated since the last build, as the script may not fully detect or rebuild them in the correct order. For the same reason, you may also occasionally encounter linker errors.
|
||||
|
||||
To resolve this, clean and restart the installation to ensure a fresh rebuild of all components (delete all temporary files generated by the build process):
|
||||
|
||||
```bash
|
||||
./build.py --clean
|
||||
./build.py --install
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
Compile the client with with `-DCMAKE_BUILD_TYPE=Debug`.
|
||||
Compile the client with `-DCMAKE_BUILD_TYPE=Debug`. Then, if you want to enable logging when running `jami`, launch it with `-d` or `--debug`.
|
||||
|
||||
Then, if you want to enable logging when running `jami`, launch it
|
||||
with `-d` or `--debug`.
|
||||
To diagnose a crash, use GDB:
|
||||
|
||||
```sh
|
||||
./build.py --install --debug
|
||||
gdb -ex run --args ./jami --debug
|
||||
```
|
||||
|
||||
3
JamiInstaller/.gitignore
vendored
3
JamiInstaller/.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/obj
|
||||
/bin
|
||||
Components.wxs
|
||||
AppComponents.wxs
|
||||
CrtComponents.wxs
|
||||
|
||||
@ -3,13 +3,11 @@
|
||||
<?define Name="Jami" ?>
|
||||
<?define ExeName="Jami" ?>
|
||||
<?define AppName="Jami" ?>
|
||||
<?define Manufacturer="Savoir-Faire Linux"?>
|
||||
|
||||
<?if $(var.Configuration) = Release ?>
|
||||
<?define ReleaseDir="..\x64\Release"?>
|
||||
<?else?>
|
||||
<?define ReleaseDir="..\x64\Beta"?>
|
||||
<?endif ?>
|
||||
|
||||
<?define Manufacturer="Savoir-Faire Linux"?>
|
||||
<?define UcrtDir="C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x64"?>
|
||||
</Include>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-16"?>
|
||||
<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<DeployedProjects />
|
||||
<DirectoryMappings />
|
||||
<FileMappings />
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="4.0"
|
||||
DefaultTargets="Build"
|
||||
InitialTargets="EnsureWixToolsetInstalled"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x64</Platform>
|
||||
@ -16,7 +19,7 @@
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>HarvestPath=..\x64\Release</DefineConstants>
|
||||
<DefineConstants>AppHarvestPath=..\x64\Release;CrtHarvestPath=$(VC_CRT_Dir)</DefineConstants>
|
||||
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||
<CompilerAdditionalOptions>
|
||||
</CompilerAdditionalOptions>
|
||||
@ -26,7 +29,7 @@
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Beta|x64' ">
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>HarvestPath=..\x64\Beta</DefineConstants>
|
||||
<DefineConstants>AppHarvestPath=..\x64\Beta;CrtHarvestPath=$(VC_CRT_Dir)</DefineConstants>
|
||||
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||
<CompilerAdditionalOptions>
|
||||
</CompilerAdditionalOptions>
|
||||
@ -35,8 +38,8 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Product.wxs" />
|
||||
<Compile Include="StandardComponents.wxs" />
|
||||
<Compile Include="Components.wxs" />
|
||||
<Compile Include="AppComponents.wxs" />
|
||||
<Compile Include="CrtComponents.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Config.wxi" />
|
||||
@ -58,13 +61,36 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Localization.wxl" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
|
||||
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
|
||||
<Import Project="$(WixTargetsPath)"
|
||||
Condition=" '$(WixTargetsPath)' != '' " />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets"
|
||||
Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
|
||||
<Target Name="EnsureWixToolsetInstalled"
|
||||
Condition=" '$(WixTargetsImported)' != 'true' ">
|
||||
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
|
||||
</Target>
|
||||
<Target Name="BeforeBuild">
|
||||
<HeatDirectory Directory="..\x64\$(Configuration)" PreprocessorVariable="var.HarvestPath" OutputFile="Components.wxs" ComponentGroupName="HeatGenerated" DirectoryRefId="APPLICATIONFOLDER" AutogenerateGuids="true" ToolPath="$(WixToolPath)" SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" Transforms="HarvestFilter.xslt" />
|
||||
<HeatDirectory Directory="..\x64\$(Configuration)"
|
||||
PreprocessorVariable="var.AppHarvestPath"
|
||||
OutputFile="AppComponents.wxs"
|
||||
ComponentGroupName="AppHeatGenerated"
|
||||
DirectoryRefId="APPLICATIONFOLDER"
|
||||
AutogenerateGuids="true"
|
||||
ToolPath="$(WixToolPath)"
|
||||
SuppressFragments="true"
|
||||
SuppressRegistry="true"
|
||||
SuppressRootDirectory="true"
|
||||
Transforms="HarvestFilter.xslt" />
|
||||
<HeatDirectory Directory="$(VC_CRT_Dir)"
|
||||
PreprocessorVariable="var.CrtHarvestPath"
|
||||
OutputFile="CrtComponents.wxs"
|
||||
ComponentGroupName="CrtHeatGenerated"
|
||||
DirectoryRefId="APPLICATIONFOLDER"
|
||||
AutogenerateGuids="true"
|
||||
ToolPath="$(WixToolPath)"
|
||||
SuppressFragments="true"
|
||||
SuppressRegistry="true"
|
||||
SuppressRootDirectory="true" />
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
|
||||
@ -2,6 +2,14 @@
|
||||
<WixLocalization Culture="en-us"
|
||||
xmlns="http://schemas.microsoft.com/wix/2006/localization">
|
||||
<String Id="AdvancedWelcomeEulaDlgDescriptionPerMachine">By installing this software you agree to the terms in the license agreement</String>
|
||||
<UI Dialog="ExitDialog" Control="OptionalCheckBox" Width="10" Height="10" X="135" Y="110" />
|
||||
<UI Dialog="ExitDialog" Control="OptionalText" X="150" Y="110" />
|
||||
<UI Dialog="ExitDialog"
|
||||
Control="OptionalCheckBox"
|
||||
Width="10"
|
||||
Height="10"
|
||||
X="135"
|
||||
Y="110" />
|
||||
<UI Dialog="ExitDialog"
|
||||
Control="OptionalText"
|
||||
X="150"
|
||||
Y="110" />
|
||||
</WixLocalization>
|
||||
|
||||
@ -1,134 +1,220 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?include Config.wxi?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Product Id="*" Name="$(var.Name)" Language="1033" Version="$(fun.AutoVersion(1.0))" Manufacturer="$(var.Manufacturer)" UpgradeCode="7c45b52b-0390-4fe8-947a-3f13e82dd346">
|
||||
<Package InstallerVersion="301" Compressed="yes" InstallScope="perMachine" />
|
||||
<Product Id="*"
|
||||
Name="$(var.Name)"
|
||||
Language="1033"
|
||||
Version="$(fun.AutoVersion(1.0))"
|
||||
Manufacturer="$(var.Manufacturer)"
|
||||
UpgradeCode="7c45b52b-0390-4fe8-947a-3f13e82dd346">
|
||||
<Package InstallerVersion="301"
|
||||
Compressed="yes"
|
||||
InstallScope="perMachine" />
|
||||
|
||||
<MajorUpgrade Schedule="afterInstallInitialize" AllowDowngrades="yes"/>
|
||||
<MediaTemplate EmbedCab="yes" CompressionLevel="high" MaximumUncompressedMediaSize="4" />
|
||||
<MajorUpgrade Schedule="afterInstallInitialize"
|
||||
AllowDowngrades="yes"/>
|
||||
<MediaTemplate EmbedCab="yes"
|
||||
CompressionLevel="high"
|
||||
MaximumUncompressedMediaSize="4" />
|
||||
|
||||
<!--Disables interaction of the package with the Restart Manager.-->
|
||||
<Property Id="MSIRESTARTMANAGERCONTROL" Value="Disable" />
|
||||
<Property Id="MSIRESTARTMANAGERCONTROL"
|
||||
Value="Disable" />
|
||||
|
||||
<!--Icon File should be in release folder(not wix project), otherwise cannot be read-->
|
||||
<Icon Id="icon.ico" SourceFile="$(var.ReleaseDir)\jami.ico" />
|
||||
<Property Id="ARPPRODUCTICON" Value="icon.ico" />
|
||||
<Property Id="ARPNOMODIFY" Value="1" />
|
||||
<Icon Id="icon.ico"
|
||||
SourceFile="$(var.ReleaseDir)\jami.ico" />
|
||||
<Property Id="ARPPRODUCTICON"
|
||||
Value="icon.ico" />
|
||||
<Property Id="ARPNOMODIFY"
|
||||
Value="1" />
|
||||
|
||||
<!-- It seems that QtWebEngineProcess.exe versioning requires us to force reinstall. -->
|
||||
<Property Id="REINSTALLMODE" Value="dms" />
|
||||
<Property Id="REINSTALLMODE"
|
||||
Value="dms" />
|
||||
|
||||
<Feature Id="ProductFeature" Title="Main" Level="1" Absent="disallow">
|
||||
<ComponentGroupRef Id="StandardComponents" Primary="yes" />
|
||||
<ComponentGroupRef Id="HeatGenerated" />
|
||||
<Feature Id="ProductFeature"
|
||||
Title="Main"
|
||||
Level="1"
|
||||
Absent="disallow">
|
||||
<ComponentGroupRef Id="MainExecutable"
|
||||
Primary="yes" />
|
||||
<ComponentGroupRef Id="AppHeatGenerated" />
|
||||
<ComponentGroupRef Id="CrtHeatGenerated" />
|
||||
<ComponentRef Id="ApplicationShortcutDesktop" />
|
||||
<ComponentRef Id="ApplicationShortcutStartMenu" />
|
||||
<ComponentRef Id="RegistryEntries" />
|
||||
<ComponentRef Id="URLProtocolRegistryEntries" />
|
||||
</Feature>
|
||||
|
||||
<!--Visual C++ Redist merge module-->
|
||||
<DirectoryRef Id="TARGETDIR">
|
||||
<Merge Id="VCRedist" SourceFile="$(env.VCRedistMergeModule)" DiskId="1" Language="0" />
|
||||
</DirectoryRef>
|
||||
<Feature Id="VCRedist" Title="Visual C++ Runtime" AllowAdvertise="no" Display="hidden" Level="1">
|
||||
<MergeRef Id="VCRedist"/>
|
||||
</Feature>
|
||||
|
||||
<SetProperty After="FindRelatedProducts" Id="FirstInstall" Value="true">
|
||||
<SetProperty After="FindRelatedProducts"
|
||||
Id="FirstInstall"
|
||||
Value="true">
|
||||
NOT Installed AND NOT WIX_UPGRADE_DETECTED AND NOT WIX_DOWNGRADE_DETECTED
|
||||
</SetProperty>
|
||||
<SetProperty After="SetFirstInstall" Id="Upgrading" Value="true">
|
||||
<SetProperty After="SetFirstInstall"
|
||||
Id="Upgrading"
|
||||
Value="true">
|
||||
WIX_UPGRADE_DETECTED AND NOT (REMOVE="ALL")
|
||||
</SetProperty>
|
||||
<SetProperty After="RemoveExistingProducts" Id="RemovingForUpgrade" Sequence="execute" Value="true">
|
||||
(REMOVE="ALL") AND UPGRADINGPRODUCTCODE
|
||||
<SetProperty After="RemoveExistingProducts"
|
||||
Id="RemovingForUpgrade"
|
||||
Sequence="execute"
|
||||
Value="true"> (REMOVE="ALL") AND UPGRADINGPRODUCTCODE
|
||||
</SetProperty>
|
||||
<SetProperty After="SetUpgrading" Id="Uninstalling" Value="true">
|
||||
<SetProperty After="SetUpgrading"
|
||||
Id="Uninstalling"
|
||||
Value="true">
|
||||
Installed AND (REMOVE="ALL") AND NOT (WIX_UPGRADE_DETECTED OR UPGRADINGPRODUCTCODE)
|
||||
</SetProperty>
|
||||
<SetProperty After="SetUninstalling" Id="Maintenance" Value="true">
|
||||
<SetProperty After="SetUninstalling"
|
||||
Id="Maintenance"
|
||||
Value="true">
|
||||
Installed AND NOT Upgrading AND NOT Uninstalling AND NOT UPGRADINGPRODUCTCODE
|
||||
</SetProperty>
|
||||
|
||||
<!--SetDirectory of APPLICATIONFOLDER -->
|
||||
<SetDirectory Id="APPLICATIONFOLDER" Value="[ProgramFiles64Folder][ApplicationFolderName]">APPLICATIONFOLDER=""</SetDirectory>
|
||||
<SetProperty Id="ARPINSTALLLOCATION" Value="[APPLICATIONFOLDER]" After="CostFinalize" />
|
||||
<SetDirectory Id="APPLICATIONFOLDER"
|
||||
Value="[ProgramFiles64Folder][ApplicationFolderName]">APPLICATIONFOLDER=""</SetDirectory>
|
||||
<SetProperty Id="ARPINSTALLLOCATION"
|
||||
Value="[APPLICATIONFOLDER]"
|
||||
After="CostFinalize" />
|
||||
|
||||
<UIRef Id="CustomUI" />
|
||||
<WixVariable Id="WixUIInfoIcon" Value="icon.ico"/>
|
||||
<WixVariable Id="WixUIBannerBmp" Value="top-banner.bmp" />
|
||||
<WixVariable Id="WixUIDialogBmp" Value="main-banner.bmp" />
|
||||
<WixVariable Id="WixUISupportPerUser" Value="0" />
|
||||
<WixVariable Id="WixUIInfoIcon"
|
||||
Value="icon.ico"/>
|
||||
<WixVariable Id="WixUIBannerBmp"
|
||||
Value="top-banner.bmp" />
|
||||
<WixVariable Id="WixUIDialogBmp"
|
||||
Value="main-banner.bmp" />
|
||||
<WixVariable Id="WixUISupportPerUser"
|
||||
Value="0" />
|
||||
|
||||
<CustomAction Id="RemoveOldJamiFiles"
|
||||
Directory="APPLICATIONFOLDER"
|
||||
ExeCommand="cmd /c "del vc_redist.x64.exe; del uninstall.exe; del WinSparkle.dll;""
|
||||
Execute="deferred"
|
||||
Return="ignore"
|
||||
HideTarget="no"
|
||||
Impersonate="no"/>
|
||||
Directory="APPLICATIONFOLDER"
|
||||
ExeCommand="cmd /c "del vc_redist.x64.exe; del uninstall.exe; del WinSparkle.dll;""
|
||||
Execute="deferred"
|
||||
Return="ignore"
|
||||
HideTarget="no"
|
||||
Impersonate="no"/>
|
||||
|
||||
<Property Id="QtExecCmdLine"
|
||||
Value='"[APPLICATIONFOLDER]/$(var.ExeName).exe" --term'/>
|
||||
Value='"[APPLICATIONFOLDER]/$(var.ExeName).exe" --term'/>
|
||||
<CustomAction Id="TerminateAppProcess"
|
||||
BinaryKey="WixCA"
|
||||
DllEntry="CAQuietExec"
|
||||
Execute="immediate"
|
||||
Return="ignore"/>
|
||||
BinaryKey="WixCA"
|
||||
DllEntry="CAQuietExec"
|
||||
Execute="immediate"
|
||||
Return="ignore"/>
|
||||
</Product>
|
||||
|
||||
<Fragment Id="DirectoryStructure">
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="TARGETDIR"
|
||||
Name="SourceDir">
|
||||
<Directory Id="ProgramFiles64Folder">
|
||||
<Directory Id="APPLICATIONFOLDER" Name="$(var.Name)" />
|
||||
<Directory Id="APPLICATIONFOLDER"
|
||||
Name="$(var.Name)" />
|
||||
</Directory>
|
||||
<Directory Id="DesktopFolder" Name="Desktop" />
|
||||
<Directory Id="DesktopFolder"
|
||||
Name="Desktop" />
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" />
|
||||
</Directory>
|
||||
<Directory Id="WindowsFolder" Name="WINDOWS"/>
|
||||
<Directory Id="WindowsFolder"
|
||||
Name="WINDOWS"/>
|
||||
</Directory>
|
||||
</Fragment>
|
||||
|
||||
<Fragment>
|
||||
<ComponentGroup Id="MainExecutable"
|
||||
Directory="APPLICATIONFOLDER">
|
||||
<Component Id="cmp9CFEE34E3A162AB05264E8B756EC1DEC"
|
||||
Guid="*">
|
||||
<File Id="fileMain.exe"
|
||||
KeyPath="yes"
|
||||
Source="$(var.ReleaseDir)\$(var.ExeName).exe" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
|
||||
<Fragment Id="Shortcuts">
|
||||
<DirectoryRef Id="DesktopFolder">
|
||||
<Component Id="ApplicationShortcutDesktop" Guid="*" Win64="yes">
|
||||
<Shortcut Id="ApplicationShortcutDesktop" Name="$(var.Name)" Description="Launch $(var.Name)" Target="[#fileMain.exe]" WorkingDirectory="INSTALLFOLDER" />
|
||||
<RemoveFolder Id="DesktopFolder" On="uninstall" />
|
||||
<RegistryValue Root="HKCU" Key="Software\jami.net\$(var.Name)" Name="desktop" Type="integer" Value="1" KeyPath="yes" />
|
||||
<Component Id="ApplicationShortcutDesktop"
|
||||
Guid="*"
|
||||
Win64="yes">
|
||||
<Shortcut Id="ApplicationShortcutDesktop"
|
||||
Name="$(var.Name)"
|
||||
Description="Launch $(var.Name)"
|
||||
Target="[#fileMain.exe]"
|
||||
WorkingDirectory="INSTALLFOLDER" />
|
||||
<RemoveFolder Id="DesktopFolder"
|
||||
On="uninstall" />
|
||||
<RegistryValue Root="HKCU"
|
||||
Key="Software\jami.net\$(var.Name)"
|
||||
Name="desktop"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes" />
|
||||
<Condition>FirstInstall</Condition>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="ApplicationProgramsFolder">
|
||||
<Component Id="ApplicationShortcutStartMenu" Guid="*" Win64="yes">
|
||||
<Shortcut Id="ApplicationShortcutStartMenu" Name="$(var.Name)" Description="Launch $(var.Name)" Target="[#fileMain.exe]" WorkingDirectory="INSTALLFOLDER" />
|
||||
<RemoveFolder Id="StartMenuFolder" On="uninstall" />
|
||||
<RegistryValue Root="HKCU" Key="Software\jami.net\$(var.Name)" Name="startmenu" Type="integer" Value="1" KeyPath="yes" />
|
||||
<Component Id="ApplicationShortcutStartMenu"
|
||||
Guid="*"
|
||||
Win64="yes">
|
||||
<Shortcut Id="ApplicationShortcutStartMenu"
|
||||
Name="$(var.Name)"
|
||||
Description="Launch $(var.Name)"
|
||||
Target="[#fileMain.exe]"
|
||||
WorkingDirectory="INSTALLFOLDER" />
|
||||
<RemoveFolder Id="StartMenuFolder"
|
||||
On="uninstall" />
|
||||
<RegistryValue Root="HKCU"
|
||||
Key="Software\jami.net\$(var.Name)"
|
||||
Name="startmenu"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
</Fragment>
|
||||
|
||||
<Fragment Id="OtherRegistryEntries">
|
||||
<DirectoryRef Id="TARGETDIR">
|
||||
<Component Id="RegistryEntries" Guid="*" Win64="yes">
|
||||
<RegistryValue Root="HKCU" Key="Software\jami.net\$(var.AppName)" Name="hasRun" Type="integer" Value="0" KeyPath="yes" />
|
||||
<Component Id="RegistryEntries"
|
||||
Guid="*"
|
||||
Win64="yes">
|
||||
<RegistryValue Root="HKCU"
|
||||
Key="Software\jami.net\$(var.AppName)"
|
||||
Name="hasRun"
|
||||
Type="integer"
|
||||
Value="0"
|
||||
KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
</Fragment>
|
||||
|
||||
<Fragment Id="URLProtocol">
|
||||
<DirectoryRef Id="TARGETDIR">
|
||||
<Component Id="URLProtocolRegistryEntries" Guid="*" Win64="yes">
|
||||
<RegistryKey Root="HKCR" Key="jami" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
|
||||
<RegistryValue Type="string" Name="URL Protocol" Value="" />
|
||||
<RegistryValue Type="string" Value="URL:jami"/>
|
||||
<Component Id="URLProtocolRegistryEntries"
|
||||
Guid="*"
|
||||
Win64="yes">
|
||||
<RegistryKey Root="HKCR"
|
||||
Key="jami"
|
||||
ForceCreateOnInstall="yes"
|
||||
ForceDeleteOnUninstall="yes">
|
||||
<RegistryValue Type="string"
|
||||
Name="URL Protocol"
|
||||
Value="" />
|
||||
<RegistryValue Type="string"
|
||||
Value="URL:jami"/>
|
||||
<RegistryKey Key="DefaultIcon">
|
||||
<RegistryValue Type="string" Value="[APPLICATIONFOLDER]$(var.ExeName).exe" />
|
||||
<RegistryValue Type="string"
|
||||
Value="[APPLICATIONFOLDER]$(var.ExeName).exe" />
|
||||
</RegistryKey>
|
||||
<RegistryKey Key="shell\open\command">
|
||||
<RegistryValue Type="string" Value='"[APPLICATIONFOLDER]$(var.ExeName).exe" "%1"' />
|
||||
<RegistryValue Type="string"
|
||||
Value='"[APPLICATIONFOLDER]$(var.ExeName).exe" "%1"' />
|
||||
</RegistryKey>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
@ -137,47 +223,88 @@
|
||||
|
||||
<Fragment Id="UI">
|
||||
<UI Id="CustomUI">
|
||||
<Property Id="WixAppFolder" Value="WixPerMachineFolder" />
|
||||
<Property Id="WixAppFolder"
|
||||
Value="WixPerMachineFolder" />
|
||||
|
||||
<!--APPLICATIONFOLDER required by WixUI_Advanced, ApplicationFolderName reset APPLICATIONFOLDER path-->
|
||||
<Property Id="ApplicationFolderName" Value="$(var.Manufacturer)\$(var.AppName)" />
|
||||
<Property Id="ApplicationFolderName"
|
||||
Value="$(var.Manufacturer)\$(var.AppName)" />
|
||||
<UIRef Id="WixUI_Advanced" />
|
||||
|
||||
<!--Remove User Exit Dialog-->
|
||||
<Publish Dialog="AdvancedWelcomeEulaDlg" Control="Cancel" Property="AbortInstall" Value="1">1</Publish>
|
||||
<Publish Dialog="InstallDirDlg" Control="Cancel" Property="AbortInstall" Value="1">1</Publish>
|
||||
<Publish Dialog="FeaturesDlg" Control="Cancel" Property="AbortInstall" Value="1">1</Publish>
|
||||
<Publish Dialog="MaintenanceWelcomeDlg" Control="Cancel" Property="AbortInstall" Value="1">1</Publish>
|
||||
<Publish Dialog="MaintenanceTypeDlg" Control="Cancel" Property="AbortInstall" Value="1">1</Publish>
|
||||
<Publish Dialog="AdvancedWelcomeEulaDlg"
|
||||
Control="Cancel"
|
||||
Property="AbortInstall"
|
||||
Value="1">1</Publish>
|
||||
<Publish Dialog="InstallDirDlg"
|
||||
Control="Cancel"
|
||||
Property="AbortInstall"
|
||||
Value="1">1</Publish>
|
||||
<Publish Dialog="FeaturesDlg"
|
||||
Control="Cancel"
|
||||
Property="AbortInstall"
|
||||
Value="1">1</Publish>
|
||||
<Publish Dialog="MaintenanceWelcomeDlg"
|
||||
Control="Cancel"
|
||||
Property="AbortInstall"
|
||||
Value="1">1</Publish>
|
||||
<Publish Dialog="MaintenanceTypeDlg"
|
||||
Control="Cancel"
|
||||
Property="AbortInstall"
|
||||
Value="1">1</Publish>
|
||||
|
||||
<!--Launch Program If Checkbox is clicked-->
|
||||
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
|
||||
<Publish Dialog="ExitDialog"
|
||||
Control="Finish"
|
||||
Event="DoAction"
|
||||
Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
|
||||
|
||||
<InstallUISequence>
|
||||
<Show Dialog="UserExit" OnExit="cancel">NOT AbortInstall = 1</Show>
|
||||
<Custom Action="Overwrite_WixSetDefaultPerMachineFolder" After="WixSetDefaultPerMachineFolder" />
|
||||
<Show Dialog="UserExit"
|
||||
OnExit="cancel">NOT AbortInstall = 1</Show>
|
||||
<Custom Action="Overwrite_WixSetDefaultPerMachineFolder"
|
||||
After="WixSetDefaultPerMachineFolder" />
|
||||
</InstallUISequence>
|
||||
</UI>
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action='TerminateAppProcess' Before='InstallValidate'/>
|
||||
<Custom Action="RemoveOldJamiFiles" After="RemoveFiles" />
|
||||
<Custom Action="LaunchApplication_nonUI" After="InstallFinalize"> WIXNONUILAUNCH </Custom>
|
||||
<Custom Action="Overwrite_WixSetDefaultPerMachineFolder" After="WixSetDefaultPerMachineFolder" />
|
||||
<Custom Action='TerminateAppProcess'
|
||||
Before='InstallValidate'/>
|
||||
<Custom Action="RemoveOldJamiFiles"
|
||||
After="RemoveFiles" />
|
||||
<Custom Action="LaunchApplication_nonUI"
|
||||
After="InstallFinalize"> WIXNONUILAUNCH </Custom>
|
||||
<Custom Action="Overwrite_WixSetDefaultPerMachineFolder"
|
||||
After="WixSetDefaultPerMachineFolder" />
|
||||
</InstallExecuteSequence>
|
||||
|
||||
<!--License check box text, Launch check box text (auto check)-->
|
||||
<Property Id="WIXUI_EXITDIALOGOPTIONALTEXT" Value="Launch $(var.Name)" />
|
||||
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch $(var.Name)" />
|
||||
<Property Id="WIXUI_EXITDIALOGOPTIONALTEXT"
|
||||
Value="Launch $(var.Name)" />
|
||||
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT"
|
||||
Value="Launch $(var.Name)" />
|
||||
<!--CheckBox Default Set to One-->
|
||||
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1"/>
|
||||
<Property Id="LicenseAccepted" Value="1"/>
|
||||
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX"
|
||||
Value="1"/>
|
||||
<Property Id="LicenseAccepted"
|
||||
Value="1"/>
|
||||
|
||||
<Property Id="WixShellExecTarget" Value="[#fileMain.exe]" />
|
||||
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
|
||||
<CustomAction Id="LaunchApplication_nonUI" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes"/>
|
||||
<CustomAction Id="Overwrite_WixSetDefaultPerMachineFolder" Property="WixPerMachineFolder" Value="[ProgramFiles64Folder][ApplicationFolderName]" Execute="immediate" />
|
||||
<Property Id="WixShellExecTarget"
|
||||
Value="[#fileMain.exe]" />
|
||||
<CustomAction Id="LaunchApplication"
|
||||
BinaryKey="WixCA"
|
||||
DllEntry="WixShellExec"
|
||||
Impersonate="yes" />
|
||||
<CustomAction Id="LaunchApplication_nonUI"
|
||||
BinaryKey="WixCA"
|
||||
DllEntry="WixShellExec"
|
||||
Impersonate="yes"/>
|
||||
<CustomAction Id="Overwrite_WixSetDefaultPerMachineFolder"
|
||||
Property="WixPerMachineFolder"
|
||||
Value="[ProgramFiles64Folder][ApplicationFolderName]"
|
||||
Execute="immediate" />
|
||||
<!--License File-->
|
||||
<WixVariable Id="WixUILicenseRtf" Value="$(var.ReleaseDir)\License.rtf"/>
|
||||
<WixVariable Id="WixUILicenseRtf"
|
||||
Value="$(var.ReleaseDir)\License.rtf"/>
|
||||
</Fragment>
|
||||
|
||||
</Wix>
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Generated with WiX's heat tool using the command:
|
||||
heat.exe dir x64\Release -ag -cg ProductComponents -dr APPLICATIONFOLDER -srd -var var.ReleaseDir -out JamiInstaller\Components.wxs
|
||||
Includes:
|
||||
- the api-ms-win dlls missing parts of vc merge module for windows 7 support
|
||||
- Jami.exe with a named Id so we can reference it in Product.wxs to launch after install
|
||||
|
||||
We run heat in the prebuild step on x64\Release without Jami.exe (instead of an XSLT file), to harvest everything else.
|
||||
-->
|
||||
<?include Config.wxi?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Fragment>
|
||||
<ComponentGroup Id="StandardComponents">
|
||||
<Component Id="cmp9C61F84AF9761955FBF397AFAE21C11B" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil2089BEC9A7AB899CED5A5EE501789299" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-core-file-l1-2-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp03BB2697EE10869C4A329E3EA987EFAA" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil44C27F2C97596734BB3BEB7C21F7B71C" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-core-file-l2-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp6B6AA7AEA5A4D324A4EE7DAE1B1193E0" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil1D16BE23D323A1E37FC1FC7354A9305F" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-core-localization-l1-2-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmpB5454FB66442C9BFD2145AE30B32D7A9" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil031B78DF53F7A3AC109410907624FC3E" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-core-processthreads-l1-1-1.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp9F6D22CD9B1739E4F75F92F3A07E4CA1" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="filE9A3672FA504AA8E518DD72A02CD3E77" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-core-synch-l1-2-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp9451422B7074D46F019614C3DE73BD17" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil3C902CA2889BB8855D285C3FBABB334F" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-core-timezone-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp349250459EC2D8C328EED5138B073E7A" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil2466F3D9FBA095A007D0909040D4D688" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-conio-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmpCC880F2B054A87EF5FC68232652231BF" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil605A691486569535A1C3548F7DCE753C" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-convert-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmpD6CB40D5A5AFF2161B7B4B4F06F03301" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil09AE032A32E2E542A232F7941AC77320" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-environment-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmpC02538029646A27A9F786AD690EB3C8E" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil7DE9C3CADCA188356922B0CBD8E313E7" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-filesystem-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp8E50197B377636123F0F1F94FFB004E7" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil584F158D11B8A380C73F1EFE8BBA92B4" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-heap-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp7F729C94A363C73DC4D91B6F48E4F859" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil4BE19B924B98D56F3155B66496D574E5" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-locale-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp7C573E66B0904BA73880788F7057AF88" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="filE8495C446FA1237E92562498D20261AA" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-math-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp7A91CED53D8F6E5F20F2049B3B5CD143" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil06951EB208628753677745AF15CC12A5" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-multibyte-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp1CE713C705A95306A1D246AC3AB9DE25" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil8D102BB81768F998470C34797459E306" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-private-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp35840DFBF4D6AE827AFC4EF2A17BB3EB" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="filC6C457BD901F940DCB673D271728F9FE" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-process-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmpEBB86BDA48FE3B9E2043C1A80D26ACD5" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="filE1B2095225B01DEFA5DA9895B432FBCB" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-runtime-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp80C8534B553078EA8B86F100FF542776" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="filDAFE58019AD70832B8304DCEA534B5EE" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-stdio-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmpCFC348111B5343749A2273A62421C07C" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil1F1B38DB330CA413655F715578D4BE1A" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-string-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp7D5450E04EC419244107942A00DF7DDF" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="filEB03BCF3155C5BAE2C2EDBF036EB659D" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-time-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp5456679BDCC818B2E9476B416F71AAA5" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fil5B120DD384CABED37DFC2652C6462666" KeyPath="yes" Source="$(var.UcrtDir)\api-ms-win-crt-utility-l1-1-0.dll" />
|
||||
</Component>
|
||||
<Component Id="cmpF23755F862A15FFCBD109C85599B7F20" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="filD6887AD9110E4A8D49143C9A8F0B5843" KeyPath="yes" Source="$(var.UcrtDir)\ucrtbase.dll" />
|
||||
</Component>
|
||||
<Component Id="cmp9CFEE34E3A162AB05264E8B756EC1DEC" Directory="APPLICATIONFOLDER" Guid="*">
|
||||
<File Id="fileMain.exe" KeyPath="yes" Source="$(var.ReleaseDir)\$(var.ExeName).exe" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
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: 59a8e41ca8...ef441f56dd
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
|
||||
|
||||
@ -1,131 +1,240 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (C) 2015-2024 Savoir-faire Linux Inc. -->
|
||||
<component type="desktop-application">
|
||||
<id>net.jami.Jami</id>
|
||||
<metadata_license>CC-BY-SA-3.0</metadata_license>
|
||||
<project_license>GPL-3.0+</project_license>
|
||||
<name>Jami</name>
|
||||
<summary>Privacy-oriented voice, video, chat, and conference platform</summary>
|
||||
<summary xml:lang="hu">Adatvédelem-orientált hang-, video-, csevegés- és konferenciaplatform</summary>
|
||||
<icon type="stock">jami</icon>
|
||||
<description>
|
||||
<id>net.jami.Jami</id>
|
||||
<metadata_license>CC-BY-SA-3.0</metadata_license>
|
||||
<project_license>GPL-3.0+</project_license>
|
||||
<name>Jami</name>
|
||||
|
||||
<summary>Privacy-oriented voice, video, chat, and conference platform</summary>
|
||||
<summary xml:lang="hu">Adatvédelem-orientált hang-, video-, csevegés- és konferenciaplatform</summary>
|
||||
<icon type="stock">jami</icon>
|
||||
|
||||
<description>
|
||||
<p>
|
||||
An end-to-end encrypted secure and distributed voice, video, and
|
||||
chat communication platform that requires no central server and
|
||||
leaves the power of privacy and freedom in the hands of users.
|
||||
Jami [1], a GNU package, is software for universal and
|
||||
distributed peer-to-peer communication that respects the
|
||||
freedom and privacy of its users.
|
||||
</p>
|
||||
<p>
|
||||
Jami supports the following key features:
|
||||
Jami is the simplest and easiest way to connect with people
|
||||
(and devices) with instant messaging, audio and video calls
|
||||
over the Internet and LAN/WAN intranets.
|
||||
</p>
|
||||
<ul>
|
||||
<li>One-to-one conversations</li>
|
||||
<li>File sharing</li>
|
||||
<li>Audio calls and conferences</li>
|
||||
<li>Video calls and conferences</li>
|
||||
<li>Screen sharing in video calls and conferences</li>
|
||||
<li>Recording and sending audio messages</li>
|
||||
<li>Recording and sending video messages</li>
|
||||
<li>Functioning as a SIP phone software</li>
|
||||
</ul>
|
||||
<p>
|
||||
Client applications for GNU/Linux, Windows, macOS, iOS, Android,
|
||||
and Android TV are available, making Jami an interoperable and
|
||||
Jami is a free/libre, end-to-end encrypted, and private
|
||||
communication platform.
|
||||
</p>
|
||||
<p>
|
||||
Jami – which used to be known as Ring – is also an
|
||||
open-source alternative (to Facebook Messenger, Signal,
|
||||
Skype, Teams, Telegram, TikTok, Viber, WhatsApp, Zoom) that
|
||||
prioritizes the privacy of its users.
|
||||
</p>
|
||||
<p>
|
||||
Jami has a professional-looking design and is available for
|
||||
a wide range of platforms. Unlike the alternatives, calls
|
||||
using Jami are directly between users as it does not use
|
||||
servers to handle calls.
|
||||
</p>
|
||||
<p>
|
||||
This gives the greatest privacy as the distributed nature
|
||||
of Jami means your calls are only between participants.
|
||||
</p>
|
||||
<p>
|
||||
One-to-one and group conversations with Jami are enhanced
|
||||
with: instant messaging; audio and video calling;
|
||||
recording and sending audio and video messages;
|
||||
file transfers; screen sharing; and, location sharing.
|
||||
</p>
|
||||
<p>
|
||||
Jami can also function as a SIP client.
|
||||
</p>
|
||||
<p>
|
||||
Jami has multiple extensions [2] available:
|
||||
Audio Filter; Auto Answer; Green Screen; Watermark; and,
|
||||
Whisper Transcript.
|
||||
</p>
|
||||
<p>
|
||||
Jami can be easily deployed in organizations with the
|
||||
“Jami Account Management Server” (JAMS) [3], allowing users
|
||||
to connect with their corporate credentials or create local
|
||||
accounts. JAMS allows you to manage your own Jami community
|
||||
while taking advantage of Jami’s distributed network
|
||||
architecture.
|
||||
</p>
|
||||
<p>
|
||||
Jami is available for GNU/Linux, Windows, macOS, iOS,
|
||||
Android, and Android TV, making Jami an interoperable and
|
||||
cross-platform communication framework.
|
||||
</p>
|
||||
|
||||
<p xml:lang="hu">
|
||||
Végpontokig titkosított biztonságos és elosztott hang-, videó-
|
||||
és csevegés-kommunikációs platform, amely nem igényel központi
|
||||
kiszolgálót, és a felhasználók kezében hagyja a magánélet és a
|
||||
szabadság hatalmát.
|
||||
<p>
|
||||
Manage multiple SIP accounts, Jami accounts and JAMS
|
||||
accounts with the Jami client installed on one or multiple
|
||||
devices.
|
||||
</p>
|
||||
<p xml:lang="hu">
|
||||
A Jami a következő főbb funkciókat támogatja:
|
||||
<p>
|
||||
Jami is free, unlimited, private, advertising free,
|
||||
compatible, fast, autonomous, and anonymous.
|
||||
</p>
|
||||
<ul>
|
||||
<li xml:lang="hu">Személyes beszélgetések</li>
|
||||
<li xml:lang="hu">Fájlmegosztás</li>
|
||||
<li xml:lang="hu">Hanghívások és konferenciák</li>
|
||||
<li xml:lang="hu">Videohívások és konferenciák</li>
|
||||
<li xml:lang="hu">Képernyőmegosztás videohívásokban és
|
||||
konferenciákon</li>
|
||||
<li xml:lang="hu">Hangüzenetek rögzítése és küldése</li>
|
||||
<li xml:lang="hu">Videoüzenetek rögzítése és küldése</li>
|
||||
<li xml:lang="hu">SIP-telefonszoftverként működik</li>
|
||||
</ul>
|
||||
<p xml:lang="hu">
|
||||
Elérhetők a GNU/Linux, Windows, macOS, iOS, Android és Android TV
|
||||
ügyfélalkalmazásai, így a Jami interoperábilis és többplatformos
|
||||
kommunikációs keretrendszerré válik.
|
||||
<p>
|
||||
[1] https://jami.net/
|
||||
</p>
|
||||
<p>
|
||||
[2] https://jami.net/extensions/
|
||||
</p>
|
||||
<p>
|
||||
[3] https://jami.biz/
|
||||
</p>
|
||||
</description>
|
||||
|
||||
</description>
|
||||
<description xml:lang="hu">
|
||||
<p>
|
||||
A Jami [1], egy GNU-csomag, egy univerzális és elosztott
|
||||
társ-társ kommunikációra szolgáló szoftver, amely
|
||||
tiszteletben tartja a felhasználók szabadságát és
|
||||
magánéletét.
|
||||
</p>
|
||||
<p>
|
||||
A Jami a legegyszerűbb és legegyszerűbb módja annak, hogy
|
||||
azonnali üzenetküldéssel, hang- és videohívásokkal
|
||||
kapcsolódjon az emberekhez (és eszközökhöz) az interneten és
|
||||
a LAN/WAN intraneteken keresztül.
|
||||
</p>
|
||||
<p>
|
||||
A Jami egy ingyenes, teljes körűen titkosított és privát
|
||||
kommunikációs platform.
|
||||
</p>
|
||||
<p>
|
||||
A Jami – amelyet korábban Ring néven ismertek – egy nyílt
|
||||
forráskódú alternatíva is (a Facebook Messenger, a Signal,
|
||||
a Skype, a Teams, a Telegram, a TikTok, a Viber, a WhatsApp,
|
||||
a Zoom számára), amely előtérbe helyezi a felhasználók
|
||||
magánéletét.
|
||||
</p>
|
||||
<p>
|
||||
A Jami professzionális megjelenésű, és platformok széles
|
||||
skálájához elérhető. Az alternatívákkal ellentétben a Jami-t
|
||||
használó hívások közvetlenül a felhasználók között zajlanak,
|
||||
mivel nem használ kiszolgálókat a hívások kezelésére.
|
||||
</p>
|
||||
<p>
|
||||
Ez biztosítja a legnagyobb magánéletet, mivel a Jami
|
||||
elosztott jellege azt jelenti, hogy a hívások csak a
|
||||
résztvevők között zajlanak.
|
||||
</p>
|
||||
<p>
|
||||
A Jamival folytatott személyes és csoportos beszélgetéseket
|
||||
a következők javítják: azonnali üzenetküldés; hang- és
|
||||
videohívások; hang- és videoüzenetek rögzítése és küldése;
|
||||
fájlátvitel; képernyőmegosztás; és helymegosztás.
|
||||
</p>
|
||||
<p>
|
||||
A Jami SIP-ügyfélként is működhet.
|
||||
</p>
|
||||
<p>
|
||||
A Jami-nek több bővítménye [2] is elérhető: hangszűrő;
|
||||
automatikus válasz; zöld képernyő; vízjel; és, suttogó
|
||||
átirat.
|
||||
</p>
|
||||
<p>
|
||||
A Jami könnyen telepíthető a szervezetekben
|
||||
a „Jami fiókkezelő kiszolgálóval” (JAMS) [3], amely lehetővé
|
||||
teszi a felhasználók számára, hogy csatlakozzanak vállalati
|
||||
hitelesítő adataikhoz, vagy helyi fiókokat hozzanak létre.
|
||||
A JAMS lehetővé teszi saját Jami közösségének kezelését,
|
||||
miközben kihasználja a Jami elosztott hálózati
|
||||
architektúráját.
|
||||
</p>
|
||||
<p>
|
||||
A Jami elérhető GNU/Linux, Windows, macOS, iOS, Android és
|
||||
Android TV rendszereken, így a Jami egy interoperábilis és
|
||||
platformok közötti kommunikációs keretrendszer.
|
||||
</p>
|
||||
<p>
|
||||
Kezeljen több SIP-fiókot, Jami-fiókot és JAMS-fiókot az egy
|
||||
vagy több eszközre telepített Jami-ügyféllel.
|
||||
</p>
|
||||
<p>
|
||||
A Jami ingyenes, korlátlan, privát, reklámmentes,
|
||||
kompatibilis, gyors, autonóm és névtelen.
|
||||
</p>
|
||||
<p>
|
||||
[1] https://jami.net/hu/
|
||||
</p>
|
||||
<p>
|
||||
[2] https://jami.net/hu/extensions/
|
||||
</p>
|
||||
<p>
|
||||
[3] https://jami.biz/
|
||||
</p>
|
||||
</description>
|
||||
|
||||
<url type="homepage">https://jami.net/</url>
|
||||
<url type="bugtracker">https://git.jami.net/savoirfairelinux/jami-client-qt/issues</url>
|
||||
<url type="faq">https://jami.net/help/</url>
|
||||
<url type="help">https://docs.jami.net</url>
|
||||
<url type="donation">https://www.paypal.com/donate/?hosted_button_id=MGUDJLQZ4TP5W</url>
|
||||
<url type="translate">https://www.transifex.com/savoirfairelinux/jami</url>
|
||||
<url type="homepage">https://jami.net/</url>
|
||||
<url type="bugtracker">https://git.jami.net/savoirfairelinux/jami-client-qt/issues</url>
|
||||
<url type="faq">https://docs.jami.net/user/faq.html</url>
|
||||
<url type="help">https://forum.jami.net/</url>
|
||||
<url type="donation">https://jami.net/whydonate/</url>
|
||||
<url type="translate">https://www.transifex.com/savoirfairelinux/jami</url>
|
||||
|
||||
<!-- Maximum caption length is 60 characters -->
|
||||
<!-- Officially GIF is not an allowed video format, but it appears to work nonetheless -->
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<caption>Send Audio, Video and Chat messages</caption>
|
||||
<caption xml:lang="hu">Hang-, video- és csevegőüzeneteket küldhet</caption>
|
||||
<image type="source" width="1310" height="650">https://dl.jami.net/media-resources/screenshots/jami_linux_audiovideo.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Easily share desktop contents</caption>
|
||||
<caption xml:lang="hu">Könnyen megoszthatja az asztali tartalmat</caption>
|
||||
<image type="source" width="1016" height="659">https://dl.jami.net/media-resources/screenshots/jami_linux_screenshare.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Crystal clear audio calls between Jami users</caption>
|
||||
<caption xml:lang="hu">Kristálytiszta hanghívások a Jami felhasználók között</caption>
|
||||
<video container="webm" codec="vp9" width="600" height="400">https://dl.jami.net/media-resources/gifs_features/conversiongif_webm/audio-call_web.webm</video>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Conference calls with an unlimited participants</caption>
|
||||
<caption xml:lang="hu">Konferenciahívások korlátlan számú résztvevővel</caption>
|
||||
<video container="webm" codec="vp9" width="600" height="400">https://dl.jami.net/media-resources/gifs_features/conversiongif_webm/conference_web.webm</video>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Encrypted and secure text messaging, no servers</caption>
|
||||
<caption xml:lang="hu">Titkosított és biztonságos csevegési üzenetküldés, kiszolgálók nélkül</caption>
|
||||
<video container="webm" codec="vp9" width="600" height="400">https://dl.jami.net/media-resources/gifs_features/conversiongif_webm/chat_web.webm</video>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Send files of any size</caption>
|
||||
<caption xml:lang="hu">Bármilyen méretű fájl küldése</caption>
|
||||
<video container="webm" codec="vp9" width="600" height="400">https://dl.jami.net/media-resources/gifs_features/conversiongif_webm/files-share_web.webm</video>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<!-- Maximum caption length is 60 characters -->
|
||||
<!-- Officially GIF is not an allowed video format, but it appears to work nonetheless -->
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image type="source" width="1310" height="650">https://dl.jami.net/media-resources/screenshots/jami_linux_audiovideo.png</image>
|
||||
<caption>Send chat messages and talk with audio and video</caption>
|
||||
<caption xml:lang="hu">Csevegőüzenetek küldése, valamint hang- és videobeszélgetés</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image type="source" width="1016" height="659">https://dl.jami.net/media-resources/screenshots/jami_linux_screenshare.png</image>
|
||||
<caption>Screen sharing</caption>
|
||||
<caption xml:lang="hu">Képernyőmegosztás</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<video container="webm" codec="vp9" width="600" height="400">https://dl.jami.net/media-resources/gifs_features/conversiongif_webm/audio-call_web.webm</video>
|
||||
<caption>Crystal clear audio calls between Jami users</caption>
|
||||
<caption xml:lang="hu">Kristálytiszta hanghívások a Jami felhasználók között</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<video container="webm" codec="vp9" width="600" height="400">https://dl.jami.net/media-resources/gifs_features/conversiongif_webm/conference_web.webm</video>
|
||||
<caption>Conference calls with an unlimited number of participants</caption>
|
||||
<caption xml:lang="hu">Konferenciahívások korlátlan számú résztvevővel</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<video container="webm" codec="vp9" width="600" height="400">https://dl.jami.net/media-resources/gifs_features/conversiongif_webm/chat_web.webm</video>
|
||||
<caption>Encrypted and secure text messaging without servers</caption>
|
||||
<caption xml:lang="hu">Titkosított és biztonságos csevegési üzenetküldés, kiszolgálók nélkül</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<video container="webm" codec="vp9" width="600" height="400">https://dl.jami.net/media-resources/gifs_features/conversiongif_webm/files-share_web.webm</video>
|
||||
<caption>Transfer files of any size</caption>
|
||||
<caption xml:lang="hu">Bármilyen méretű fájl küldése</caption>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<launchable type="desktop-id">jami.desktop</launchable>
|
||||
<launchable type="desktop-id">jami.desktop</launchable>
|
||||
|
||||
<provides><binary>jami</binary></provides>
|
||||
<provides><binary>jami</binary></provides>
|
||||
|
||||
<!-- https://specifications.freedesktop.org/menu-spec/latest/apa.html -->
|
||||
<!-- https://specifications.freedesktop.org/menu-spec/latest/apas02.html -->
|
||||
<categories>
|
||||
<category>Chat</category>
|
||||
<category>Communication</category>
|
||||
<category>FileTransfer</category>
|
||||
<category>InstantMessaging</category>
|
||||
<category>Network</category>
|
||||
<category>P2P</category>
|
||||
<category>Productivity</category>
|
||||
</categories>
|
||||
<!-- https://specifications.freedesktop.org/menu-spec/latest/apa.html -->
|
||||
<!-- https://specifications.freedesktop.org/menu-spec/latest/apas02.html -->
|
||||
<categories>
|
||||
<category>Chat</category>
|
||||
<category>Communication</category>
|
||||
<category>FileTransfer</category>
|
||||
<category>InstantMessaging</category>
|
||||
<category>Network</category>
|
||||
<category>P2P</category>
|
||||
<category>Productivity</category>
|
||||
</categories>
|
||||
|
||||
<translation type="gettext">jami-client-qt</translation>
|
||||
<translation type="gettext">jami-client-qt</translation>
|
||||
|
||||
<content_rating type="oars-1.1">
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
<content_attribute id="social-audio">intense</content_attribute>
|
||||
</content_rating>
|
||||
<content_rating type="oars-1.1">
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
<content_attribute id="social-audio">intense</content_attribute>
|
||||
</content_rating>
|
||||
|
||||
<requires><id>net.jami.daemon</id></requires>
|
||||
<requires><id>net.jami.daemon</id></requires>
|
||||
|
||||
</component>
|
||||
|
||||
@ -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,11 +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"]
|
||||
|
||||
105
extras/packaging/gnu-linux/docker/Dockerfile_fedora_40
Normal file
105
extras/packaging/gnu-linux/docker/Dockerfile_fedora_40
Normal file
@ -0,0 +1,105 @@
|
||||
FROM fedora:40
|
||||
|
||||
RUN dnf clean all
|
||||
RUN dnf update -y
|
||||
|
||||
RUN dnf install -y dnf-command\(builddep\) rpmdevtools && \
|
||||
dnf install -y mock
|
||||
|
||||
RUN dnf groupinstall -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 \
|
||||
clang \
|
||||
clang-devel \
|
||||
llvm-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 \
|
||||
clang \
|
||||
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"]
|
||||
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,5 +1,5 @@
|
||||
ARG RISK=edge
|
||||
ARG UBUNTU=jammy
|
||||
ARG UBUNTU=focal
|
||||
|
||||
FROM ubuntu:$UBUNTU as builder
|
||||
ARG RISK
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM ubuntu:23.04
|
||||
FROM ubuntu:24.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
@ -10,6 +10,9 @@ RUN apt-get update && \
|
||||
python-is-python3 \
|
||||
wget
|
||||
|
||||
ADD extras/packaging/gnu-linux/scripts/install-gcc-debian.sh /opt/install-gcc-debian.sh
|
||||
RUN /opt/install-gcc-debian.sh 13
|
||||
|
||||
ADD extras/packaging/gnu-linux/scripts/prebuild-package-debian.sh /opt/prebuild-package-debian.sh
|
||||
|
||||
COPY extras/packaging/gnu-linux/rules/debian-qt/control /tmp/builddeps/debian/control
|
||||
29
extras/packaging/gnu-linux/docker/Dockerfile_ubuntu_24.10
Normal file
29
extras/packaging/gnu-linux/docker/Dockerfile_ubuntu_24.10
Normal file
@ -0,0 +1,29 @@
|
||||
FROM ubuntu:24.10
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get clean
|
||||
RUN apt-get update && \
|
||||
apt-get install -y -o Acquire::Retries=10 \
|
||||
devscripts \
|
||||
equivs \
|
||||
python-is-python3 \
|
||||
wget
|
||||
|
||||
ADD extras/packaging/gnu-linux/scripts/prebuild-package-debian.sh /opt/prebuild-package-debian.sh
|
||||
|
||||
COPY extras/packaging/gnu-linux/rules/debian-qt/control /tmp/builddeps/debian/control
|
||||
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"]
|
||||
@ -92,6 +92,7 @@ Build-Depends: debhelper (>= 9),
|
||||
libgl1-mesa-dri,
|
||||
# pkg-kde-tools (>= 0.15.17~),
|
||||
python3:any,
|
||||
python3-bs4,
|
||||
python3-html5lib,
|
||||
# qtbase5-private-dev (>= 5.15.2+dfsg~),
|
||||
xauth <!nocheck>,
|
||||
|
||||
@ -0,0 +1,348 @@
|
||||
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 ++-----
|
||||
.../mojom/mojom/generate/translate_unittest.py | 4 ----
|
||||
.../tools/mojom/mojom/parse/ast_unittest.py | 6 ------
|
||||
.../mojom/parse/conditional_features_unittest.py | 8 ++------
|
||||
.../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 -----
|
||||
.../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 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 @@
|
||||
# found in the LICENSE file.
|
||||
|
||||
import errno
|
||||
-import imp
|
||||
import os.path
|
||||
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 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 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
-import imp
|
||||
import os.path
|
||||
import shutil
|
||||
-import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from mojom import fileutil
|
||||
|
||||
-
|
||||
class FileUtilTest(unittest.TestCase):
|
||||
def testEnsureDirectoryExists(self):
|
||||
- """Test that EnsureDirectoryExists fuctions correctly."""
|
||||
+ """Test that EnsureDirectoryExists functions correctly."""
|
||||
|
||||
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 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 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
-import imp
|
||||
+import importlib.util
|
||||
import os.path
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
-
|
||||
def _GetDirAbove(dirname):
|
||||
"""Returns the directory "above" this file containing |dirname| (which must
|
||||
also be "above" this file)."""
|
||||
@@ -20,12 +19,11 @@ def _GetDirAbove(dirname):
|
||||
|
||||
|
||||
try:
|
||||
- imp.find_module("mojom")
|
||||
+ importlib.util.find_spec("mojom")
|
||||
except ImportError:
|
||||
sys.path.append(os.path.join(_GetDirAbove("pylib"), "pylib"))
|
||||
from mojom.generate import generator
|
||||
|
||||
-
|
||||
class StringManipulationTest(unittest.TestCase):
|
||||
"""generator contains some string utilities, this tests only those."""
|
||||
|
||||
@@ -69,6 +67,5 @@ class StringManipulationTest(unittest.TestCase):
|
||||
self.assertEquals("SNAKE_D3D11_CASE",
|
||||
generator.ToUpperSnakeCase("snakeD3d11Case"))
|
||||
|
||||
-
|
||||
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 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 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
-import imp
|
||||
-import os.path
|
||||
-import sys
|
||||
import unittest
|
||||
|
||||
from mojom.generate import module as mojom
|
||||
from mojom.generate import translate
|
||||
from mojom.parse import ast
|
||||
|
||||
-
|
||||
class TranslateTest(unittest.TestCase):
|
||||
"""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 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 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
-import imp
|
||||
-import os.path
|
||||
-import sys
|
||||
import unittest
|
||||
|
||||
from mojom.parse import ast
|
||||
|
||||
-
|
||||
class _TestNode(ast.NodeBase):
|
||||
"""Node type for tests."""
|
||||
|
||||
@@ -20,13 +16,11 @@ class _TestNode(ast.NodeBase):
|
||||
def __eq__(self, other):
|
||||
return super().__eq__(other) and self.value == other.value
|
||||
|
||||
-
|
||||
class _TestNodeList(ast.NodeListBase):
|
||||
"""Node list type for tests."""
|
||||
|
||||
_list_item_type = _TestNode
|
||||
|
||||
-
|
||||
class ASTTest(unittest.TestCase):
|
||||
"""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 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 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
-import imp
|
||||
+import importlib.util
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
-
|
||||
def _GetDirAbove(dirname):
|
||||
"""Returns the directory "above" this file containing |dirname| (which must
|
||||
also be "above" this file)."""
|
||||
@@ -18,9 +17,8 @@ def _GetDirAbove(dirname):
|
||||
if tail == dirname:
|
||||
return path
|
||||
|
||||
-
|
||||
try:
|
||||
- imp.find_module('mojom')
|
||||
+ importlib.util.find_spec("mojom")
|
||||
except ImportError:
|
||||
sys.path.append(os.path.join(_GetDirAbove('pylib'), 'pylib'))
|
||||
import mojom.parse.ast as ast
|
||||
@@ -29,7 +27,6 @@ import mojom.parse.parser as parser
|
||||
|
||||
ENABLED_FEATURES = frozenset({'red', 'green', 'blue'})
|
||||
|
||||
-
|
||||
class ConditionalFeaturesTest(unittest.TestCase):
|
||||
"""Tests |mojom.parse.conditional_features|."""
|
||||
|
||||
@@ -356,6 +353,5 @@ class ConditionalFeaturesTest(unittest.TestCase):
|
||||
conditional_features.RemoveDisabledDefinitions,
|
||||
definition, ENABLED_FEATURES)
|
||||
|
||||
-
|
||||
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 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 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
-import imp
|
||||
import os.path
|
||||
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 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 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
-import imp
|
||||
+import importlib.util
|
||||
import os.path
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
-
|
||||
def _GetDirAbove(dirname):
|
||||
"""Returns the directory "above" this file containing |dirname| (which must
|
||||
also be "above" this file)."""
|
||||
@@ -18,17 +17,15 @@ def _GetDirAbove(dirname):
|
||||
if tail == dirname:
|
||||
return path
|
||||
|
||||
-
|
||||
sys.path.insert(1, os.path.join(_GetDirAbove("mojo"), "third_party"))
|
||||
from ply import lex
|
||||
|
||||
try:
|
||||
- imp.find_module("mojom")
|
||||
+ importlib.util.find_spec("mojom")
|
||||
except ImportError:
|
||||
sys.path.append(os.path.join(_GetDirAbove("pylib"), "pylib"))
|
||||
import mojom.parse.lexer
|
||||
|
||||
-
|
||||
# This (monkey-patching LexToken to make comparison value-based) is evil, but
|
||||
# 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 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 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
-import imp
|
||||
-import os.path
|
||||
-import sys
|
||||
import unittest
|
||||
|
||||
from mojom.parse import ast
|
||||
from mojom.parse import lexer
|
||||
from mojom.parse import parser
|
||||
|
||||
-
|
||||
class ParserTest(unittest.TestCase):
|
||||
"""Tests |parser.Parse()|."""
|
||||
|
||||
@@ -1375,6 +1371,5 @@ class ParserTest(unittest.TestCase):
|
||||
r" *associated\? MyInterface& a;$"):
|
||||
parser.Parse(source3, "my_file.mojom")
|
||||
|
||||
-
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
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
|
||||
|
||||
+if PY34:
|
||||
+ from importlib.util import spec_from_loader
|
||||
+else:
|
||||
+ spec_from_loader = None
|
||||
+
|
||||
|
||||
def _add_doc(func, doc):
|
||||
"""Add documentation to a function."""
|
||||
@@ -186,6 +191,11 @@ class _SixMetaPathImporter(object):
|
||||
return self
|
||||
return None
|
||||
|
||||
+ def find_spec(self, fullname, path, target=None):
|
||||
+ if fullname in self.known_modules:
|
||||
+ return spec_from_loader(fullname, self)
|
||||
+ return None
|
||||
+
|
||||
def __get_module(self, fullname):
|
||||
try:
|
||||
return self.known_modules[fullname]
|
||||
@@ -223,6 +233,12 @@ class _SixMetaPathImporter(object):
|
||||
return None
|
||||
get_source = get_code # same as get_code
|
||||
|
||||
+ def create_module(self, spec):
|
||||
+ return self.load_module(spec.name)
|
||||
+
|
||||
+ def exec_module(self, module):
|
||||
+ pass
|
||||
+
|
||||
_importer = _SixMetaPathImporter(__name__)
|
||||
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp b/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp
|
||||
index 3488120543..120e47a76f 100644
|
||||
--- a/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp
|
||||
+++ b/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp
|
||||
@@ -472,7 +472,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
|
||||
}
|
||||
catch (const DeadlyImportError& e)
|
||||
{
|
||||
- if (!is64bits && (length > std::numeric_limits<std::uint32_t>::max())) {
|
||||
+ if (!is64bits && (length > std::numeric_limits<uint32_t>::max())) {
|
||||
throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", ai_to_string(version), ") of the FBX format. (", e.what(), ")");
|
||||
}
|
||||
throw;
|
||||
@ -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
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
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,10 +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
|
||||
|
||||
@ -16,6 +16,9 @@
|
||||
%define computed_job_count_ %(echo $(( %available_memory / %memory_required_per_core / %max_parallel_builds )))
|
||||
%define computed_job_count %max %computed_job_count_ 1
|
||||
%define job_count %min %cpu_count %computed_job_count
|
||||
# Exclude vendored Qt6 from dependency generator
|
||||
%define __provides_exclude_from ^%{_libdir}/qt-jami/.*$
|
||||
%define __requires_exclude ^libQt6.*$
|
||||
|
||||
Name: %{name}
|
||||
Version: %{version}
|
||||
@ -26,6 +29,8 @@ License: GPLv3+
|
||||
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
|
||||
@ -61,6 +66,8 @@ This package contains Qt libraries for Jami.
|
||||
|
||||
%prep
|
||||
%setup -n qt-everywhere-src-%{version}
|
||||
%patch -P 0 -p1
|
||||
%patch -P 1 -p1
|
||||
|
||||
%build
|
||||
echo "Building Qt using %{job_count} parallel jobs"
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
%define version RELEASE_VERSION
|
||||
%define release 0
|
||||
|
||||
# Exclude vendored Qt6 from dependency generator
|
||||
%define __requires_exclude ^libQt6.*$
|
||||
|
||||
Name: %{name}
|
||||
Version: %{version}
|
||||
Release: %{release}%{?dist}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
From 9721082687c9529fe6ae3c5304dcf079158e8a77 Mon Sep 17 00:00:00 2001
|
||||
From: Sam James <sam@gentoo.org>
|
||||
Date: Sun, 04 Jun 2023 04:15:16 +0100
|
||||
Subject: [PATCH] heap: Add missing <algorithm> include for std::remove
|
||||
|
||||
GCC 14 changes some internal includes within libstdc++ so this transient
|
||||
include gets lost. Include <algorithm> explicitly for std::remove.
|
||||
|
||||
Change-Id: Iab8a2c751a0f9c9dc6a770d6296ad6de724ef3bb
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4583222
|
||||
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
|
||||
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#88037}
|
||||
---
|
||||
|
||||
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>
|
||||
@ -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
|
||||
|
||||
@ -138,6 +138,10 @@ apps:
|
||||
autostart: jami.desktop
|
||||
common-id: net.jami.Jami
|
||||
desktop: usr/share/applications/jami.desktop
|
||||
environment:
|
||||
PIPEWIRE_CONFIG_NAME: "$SNAP/usr/share/pipewire/pipewire.conf"
|
||||
PIPEWIRE_MODULE_DIR: "$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pipewire-0.3"
|
||||
SPA_PLUGIN_DIR: "$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/spa-0.2"
|
||||
slots:
|
||||
- dbus-jami
|
||||
- dbus-ring
|
||||
@ -168,7 +172,7 @@ package-repositories:
|
||||
components: [main]
|
||||
suites: [jami]
|
||||
key-id: A295D773307D25A33AE72F2F64CD5FA175348F84
|
||||
url: https://dl.jami.net/nightly/ubuntu_22.04/
|
||||
url: https://dl.jami.net/internal/ubuntu_20.04/
|
||||
|
||||
parts:
|
||||
desktop-launch:
|
||||
@ -255,6 +259,8 @@ parts:
|
||||
sed -i -E 's|(tmpName) << (PACKAGE_NAME << "_shm_")|\1 << "snap.jami." << \2|' ./daemon/src/media/video/sinkclient.cpp
|
||||
sed -i -E 's|^Icon=.*|Icon=${SNAP}/usr/share/icons/hicolor/scalable/apps/jami.svg|' extras/data/jami.desktop
|
||||
override-build: |
|
||||
$SNAPCRAFT_PART_BUILD/extras/packaging/gnu-linux/scripts/install-pipewire-from-source.sh
|
||||
|
||||
cd $SNAPCRAFT_PART_BUILD/daemon/contrib
|
||||
mkdir -p native
|
||||
cd native
|
||||
@ -304,7 +310,6 @@ parts:
|
||||
- libswscale-dev
|
||||
- libva-dev
|
||||
- libvdpau-dev
|
||||
- libpipewire-0.3-dev
|
||||
- libargon2-0-dev # opendht
|
||||
- libexpat1-dev
|
||||
- libjsoncpp-dev
|
||||
@ -320,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
|
||||
@ -327,7 +338,7 @@ parts:
|
||||
- libegl1
|
||||
- libgbm1
|
||||
- libgudev-1.0-0
|
||||
- libjsoncpp25
|
||||
- libjsoncpp1
|
||||
- libllvm12
|
||||
- libminizip1
|
||||
- libnm0
|
||||
|
||||
@ -44,6 +44,23 @@ QUILT_REFRESH_ARGS="-p 1"
|
||||
|
||||
if [ ! -f "${qt_deb_path}" ] || [ "${FORCE_REBUILD_QT}" = "true" ]; then
|
||||
(
|
||||
|
||||
# HACK: For now on ubuntu 24.04 there is no python3.10 package
|
||||
# So create a PyEnv environment to install the required packages
|
||||
if cat /etc/os-release | grep -Eq "24.04"; then
|
||||
apt-get install git gcc make python3-pip libssl-dev curl libreadline-dev -y
|
||||
curl https://pyenv.run | bash
|
||||
export PYENV_ROOT="$HOME/.pyenv"
|
||||
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
|
||||
eval "$(pyenv init -)"
|
||||
pyenv install 3.10.0
|
||||
pyenv local 3.10.0
|
||||
|
||||
python -m pip install html5lib
|
||||
python -m pip install six
|
||||
fi
|
||||
|
||||
|
||||
flock 9 # block until the lock file is gone
|
||||
test -f "${qt_deb_path}" && exit 0 # check again
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ rpmdev-setuptree
|
||||
|
||||
# Copy the source tarball.
|
||||
cp --reflink=auto "/src/$RELEASE_TARBALL_FILENAME" /root/rpmbuild/SOURCES
|
||||
cp patches/*.patch /root/rpmbuild/SOURCES/
|
||||
|
||||
QT_JAMI_PREFIX="/usr/lib64/qt-jami"
|
||||
PATH="${QT_JAMI_PREFIX}/bin:${PATH}"
|
||||
@ -43,7 +44,7 @@ PKG_CONFIG_PATH="${QT_JAMI_PREFIX}/lib/pkgconfig:${PKG_CONFIG_PATH}"
|
||||
CMAKE_PREFIX_PATH="${QT_JAMI_PREFIX}/lib/cmake:${CMAKE_PREFIX_PATH}"
|
||||
QT_MAJOR=6
|
||||
QT_MINOR=6
|
||||
QT_PATCH=1
|
||||
QT_PATCH=3
|
||||
QT_RELEASE_PATCH=0
|
||||
|
||||
QT_MAJOR_MINOR=${QT_MAJOR}.${QT_MINOR}
|
||||
@ -52,7 +53,7 @@ QT_MAJOR_MINOR_PATCH=${QT_MAJOR}.${QT_MINOR}.${QT_PATCH}
|
||||
QT_TARBALL_URL=https://download.qt.io/archive/qt/$QT_MAJOR_MINOR/\
|
||||
$QT_MAJOR_MINOR_PATCH/single/qt-everywhere-src-$QT_MAJOR_MINOR_PATCH.tar.xz
|
||||
|
||||
QT_TARBALL_SHA256="dd3668f65645fe270bc615d748bd4dc048bd17b9dc297025106e6ecc419ab95d"
|
||||
QT_TARBALL_SHA256="69d0348fef415da98aa890a34651e9cfb232f1bffcee289b7b4e21386bf36104"
|
||||
QT_TARBALL_FILE_NAME=$(basename "$QT_TARBALL_URL")
|
||||
CACHED_QT_TARBALL=$TARBALLS/$QT_TARBALL_FILE_NAME
|
||||
|
||||
@ -111,6 +112,10 @@ if [ ! -f "${RPM_PATH}" ]; then
|
||||
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc38.x86_64.rpm "${RPM_PATH}"
|
||||
elif [[ "${DISTRIBUTION}" == "fedora_39" ]]; 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
|
||||
|
||||
35
extras/packaging/gnu-linux/scripts/install-pipewire-from-source.sh
Executable file
35
extras/packaging/gnu-linux/scripts/install-pipewire-from-source.sh
Executable file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# The purpose of this script is to build PipeWire from source in a snap based on core20 / Ubuntu 20.04
|
||||
# It must be called in the "override-build" section of the relevant part in snapcraft.yaml
|
||||
|
||||
set -e
|
||||
|
||||
OLD_WD=$(pwd)
|
||||
cd /tmp
|
||||
|
||||
# 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
|
||||
tar xzf meson-0.61.1.tar.gz
|
||||
|
||||
# Build PipeWire 1.0.5 and install it in the /usr directory of the build environment
|
||||
wget -q https://gitlab.freedesktop.org/pipewire/pipewire/-/archive/1.0.5/pipewire-1.0.5.tar.gz
|
||||
echo "c5a5de26d684a1a84060ad7b6131654fb2835e03fccad85059be92f8e3ffe993 pipewire-1.0.5.tar.gz" | sha256sum --check
|
||||
tar xzf pipewire-1.0.5.tar.gz
|
||||
cd pipewire-1.0.5
|
||||
../meson-0.61.1/meson.py setup builddir -Dsession-managers=media-session -Dalsa=disabled -Dprefix=/usr
|
||||
../meson-0.61.1/meson.py compile -C builddir
|
||||
../meson-0.61.1/meson.py install -C builddir
|
||||
|
||||
# The files installed by the previous command are only for the "Build" step of the snap
|
||||
# creation process (https://snapcraft.io/docs/how-snapcraft-builds). In order to ensure
|
||||
# that PipeWire is installed in the final snap archive, we also need to copy all the
|
||||
# required files under the $SNAPCRAFT_PART_INSTALL directory.
|
||||
../meson-0.61.1/meson.py configure builddir -Dprefix=$SNAPCRAFT_PART_INSTALL/usr/
|
||||
../meson-0.61.1/meson.py install -C builddir
|
||||
|
||||
# Cleanup
|
||||
cd /tmp
|
||||
rm -rf meson-0.61.1 meson-0.61.1.tar.gz pipewire-1.0.5 pipewire-1.0.5.tar.gz
|
||||
cd $OLD_WD
|
||||
@ -34,7 +34,7 @@ cat << EOFILE > ${REPO_FOLDER}/${SPARKLE_FILE}
|
||||
<pubDate>$DATE_RFC2822</pubDate>
|
||||
<sparkle:version>${BUILD}</sparkle:version>
|
||||
<sparkle:shortVersionString>${VERSION}</sparkle:shortVersionString>
|
||||
<sparkle:minimumSystemVersion>10.15.0</sparkle:minimumSystemVersion>
|
||||
<sparkle:minimumSystemVersion>11.0</sparkle:minimumSystemVersion>
|
||||
<enclosure url="${REPO_URL}/$(basename ${PACKAGE})" type="application/octet-stream" $(./sign_update ${PACKAGE}) />
|
||||
</item>
|
||||
$(echo -e "${ITEMS}")
|
||||
|
||||
@ -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,61 +1,89 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# Flags:
|
||||
|
||||
# -a: architecture to build. Accepted values arm64, x86_64, unified
|
||||
# Usage:
|
||||
# ./build_qrencode.sh -a <architecture>
|
||||
# Accepted architectures: arm64, x86_64, unified
|
||||
# If no architecture is specified, the script builds for the host architecture.
|
||||
|
||||
# Initialize variables
|
||||
arch=''
|
||||
while getopts "a:" OPT; do
|
||||
case "$OPT" in
|
||||
a)
|
||||
arch="${OPTARG}"
|
||||
;;
|
||||
\?)
|
||||
exit 1
|
||||
;;
|
||||
a)
|
||||
arch="${OPTARG}"
|
||||
;;
|
||||
\?)
|
||||
echo "Invalid option: -$OPTARG" >&2
|
||||
echo "Usage: $0 [-a architecture]"
|
||||
echo "Accepted architectures: arm64, x86_64, unified"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Determine architectures to build
|
||||
if [[ "$arch" == 'unified' ]]; then
|
||||
ARCHS=("arm64" "x86_64")
|
||||
elif [[ "$arch" == '' ]]; then
|
||||
ARCHS=("arm64")
|
||||
# Detect host architecture
|
||||
HOST_ARCH=$(uname -m)
|
||||
case "$HOST_ARCH" in
|
||||
x86_64|arm64)
|
||||
ARCHS=("$HOST_ARCH")
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported host architecture: $HOST_ARCH"
|
||||
echo "Supported architectures are: arm64, x86_64, unified"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
ARCHS=("$arch")
|
||||
# Validate specified architecture
|
||||
case "$arch" in
|
||||
x86_64|arm64)
|
||||
ARCHS=("$arch")
|
||||
;;
|
||||
*)
|
||||
echo "Invalid architecture specified: $arch"
|
||||
echo "Accepted architectures are: arm64, x86_64, unified"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
TOP="$(pwd)"
|
||||
QRENCODEDIR="${TOP}/3rdparty/libqrencode"
|
||||
if [ -z "$NPROC" ]; then
|
||||
NPROC=$(sysctl -n hw.ncpu || echo -n 1)
|
||||
fi
|
||||
BUILDDIR="${QRENCODEDIR}/build-libqrencode"
|
||||
LIBDIR="${QRENCODEDIR}/lib"
|
||||
INCLUDEDIR="${QRENCODEDIR}/include"
|
||||
|
||||
for ARCH in "${ARCHS[@]}"; do
|
||||
cd "$QRENCODEDIR" || exit 1
|
||||
BUILDDIR="$ARCH-libqrencode"
|
||||
mkdir "$BUILDDIR"
|
||||
make clean
|
||||
./autogen.sh
|
||||
./configure --host="$ARCH" --without-png --prefix="${QRENCODEDIR}/${BUILDDIR}" CFLAGS=" -arch $ARCH $CFLAGS"
|
||||
make -j"$NPROC"
|
||||
make install
|
||||
done
|
||||
mkdir -p "$QRENCODEDIR"/lib
|
||||
mkdir -p "$QRENCODEDIR"/include
|
||||
# Clean up build directory
|
||||
echo "Preparing clean build directory"
|
||||
rm -rf "$BUILDDIR"
|
||||
mkdir -p "$BUILDDIR"
|
||||
|
||||
if ((${#ARCHS[@]} == "2")); then
|
||||
echo "Making fat lib for ${ARCHS[0]} and ${ARCHS[1]}"
|
||||
LIBFILES="$QRENCODEDIR/${ARCHS[0]}-libqrencode/lib/*.a"
|
||||
for f in $LIBFILES; do
|
||||
libFile=${f##*/}
|
||||
echo "$libFile"
|
||||
lipo -create "$QRENCODEDIR/${ARCHS[0]}-libqrencode/lib/$libFile" \
|
||||
"$QRENCODEDIR/${ARCHS[1]}-libqrencode/lib/$libFile" \
|
||||
-output "${QRENCODEDIR}/lib/$libFile"
|
||||
done
|
||||
else
|
||||
echo "No need for fat lib"
|
||||
rsync -ar --delete "$QRENCODEDIR/${ARCHS[0]}-libqrencode/lib/"*.a "${QRENCODEDIR}/lib/"
|
||||
fi
|
||||
# Clean output directories
|
||||
rm -rf "$LIBDIR" "$INCLUDEDIR"
|
||||
mkdir -p "$LIBDIR"
|
||||
mkdir -p "$INCLUDEDIR"
|
||||
|
||||
rsync -ar --delete "$QRENCODEDIR/${ARCHS[0]}-libqrencode/include/"* "${QRENCODEDIR}/include/"
|
||||
# Convert architectures to semicolon-separated format for cmake
|
||||
ARCHS_SEMICOLON_SEPARATED=$(IFS=";"; echo "${ARCHS[*]}")
|
||||
|
||||
echo "Configuring CMake for architectures: ${ARCHS[*]}"
|
||||
cd "$BUILDDIR"
|
||||
cmake "$QRENCODEDIR" \
|
||||
-DCMAKE_OSX_ARCHITECTURES="$ARCHS_SEMICOLON_SEPARATED" \
|
||||
-DCMAKE_INSTALL_PREFIX="$QRENCODEDIR" \
|
||||
-DWITHOUT_PNG=ON \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-G "Xcode"
|
||||
|
||||
echo "Building libqrencode for architectures: ${ARCHS[*]}"
|
||||
cmake --build . --config Release
|
||||
|
||||
echo "Installing libqrencode to $LIBDIR and $INCLUDEDIR"
|
||||
cmake --install . --config Release
|
||||
|
||||
echo "Build and installation completed successfully, with outputs in $LIBDIR and $INCLUDEDIR."
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.15</string>
|
||||
<string>11.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -85,7 +85,7 @@ ApplicationWindow {
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
|
||||
Layout.topMargin: preferredMargin
|
||||
|
||||
text: connectionFailed ? JamiStrings.reconnectWarn : JamiStrings.reconnectTry
|
||||
text: connectionFailed ? JamiStrings.reconnectWarn : JamiStrings.reconnectAttempt
|
||||
font.pointSize: 11
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
@ -116,7 +116,8 @@ ApplicationWindow {
|
||||
function close(force = false) {
|
||||
// If we're in the onboarding wizard or 'MinimizeOnClose'
|
||||
// is set, then we can quit
|
||||
if (force || !UtilsAdapter.getAppValue(Settings.MinimizeOnClose) || !UtilsAdapter.getAccountListSize()) {
|
||||
var minimizeToTray = UtilsAdapter.getAppValue(Settings.MinimizeOnClose) && UtilsAdapter.isSystemTrayIconVisible();
|
||||
if (force || !minimizeToTray || !UtilsAdapter.getAccountListSize()) {
|
||||
Qt.quit();
|
||||
} else {
|
||||
layoutManager.closeToTray();
|
||||
@ -361,7 +362,7 @@ ApplicationWindow {
|
||||
|
||||
function onUpdateCheckReplyReceived(ok, found) {
|
||||
if (!ok) {
|
||||
// Show an error dialog describing that we could not successfully check for an update.
|
||||
// Show an error dialog describing that an update check failed.
|
||||
presentUpdateInfoDialog(JamiStrings.updateCheckError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ QtObject {
|
||||
if (!view.managed)
|
||||
view.presented();
|
||||
}, props)) {
|
||||
print("could not create view:", viewName);
|
||||
print("An error occurred while creating view:", viewName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ QtObject {
|
||||
} else
|
||||
view = rootView.pop(StackView.Immediate);
|
||||
if (!view) {
|
||||
print("could not pop view:", obj.objectName);
|
||||
print("An error occurred while attempting to pop view:", obj.objectName);
|
||||
resolveStack();
|
||||
return;
|
||||
}
|
||||
@ -194,7 +194,7 @@ QtObject {
|
||||
if (view.managed) {
|
||||
var objectName = view ? view.objectName : obj.objectName;
|
||||
if (!viewManager.destroyView(resources[objectName])) {
|
||||
print("could not destroy view:", objectName);
|
||||
print("An error occurred while attempting to destroy view:", objectName);
|
||||
} else {
|
||||
print("destroyed view:", objectName);
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ AccountAdapter::createJamiAccount(const QVariantMap& settings)
|
||||
&lrcInstance_->accountModel(),
|
||||
&lrc::api::AccountModel::accountAdded,
|
||||
[this, registeredName, settings](const QString& accountId) {
|
||||
lrcInstance_->accountModel().setAvatar(accountId, settings["avatar"].toString());
|
||||
lrcInstance_->accountModel().setAvatar(accountId, settings["avatar"].toString(), true,1);
|
||||
Utils::oneShotConnect(&lrcInstance_->accountModel(),
|
||||
&lrc::api::AccountModel::accountDetailsChanged,
|
||||
[this](const QString& accountId) {
|
||||
@ -303,13 +303,8 @@ AccountAdapter::setCurrentAccountAvatarFile(const QString& source)
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray ba;
|
||||
QBuffer bu(&ba);
|
||||
bu.open(QIODevice::WriteOnly);
|
||||
image.save(&bu, "PNG");
|
||||
auto str = QString::fromLocal8Bit(ba.toBase64());
|
||||
auto accountId = lrcInstance_->get_currentAccountId();
|
||||
lrcInstance_->accountModel().setAvatar(accountId, str);
|
||||
lrcInstance_->accountModel().setAvatar(accountId, source);
|
||||
});
|
||||
}
|
||||
|
||||
@ -318,7 +313,7 @@ AccountAdapter::setCurrentAccountAvatarBase64(const QString& data)
|
||||
{
|
||||
auto futureResult = QtConcurrent::run([this, data]() {
|
||||
auto accountId = lrcInstance_->get_currentAccountId();
|
||||
lrcInstance_->accountModel().setAvatar(accountId, data);
|
||||
lrcInstance_->accountModel().setAvatar(accountId, data, true, 1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ extern const QString defaultDownloadPath;
|
||||
|
||||
// Common key-value pairs for both APPSTORE and non-APPSTORE builds
|
||||
#define COMMON_KEYS \
|
||||
X(MinimizeOnClose, false) \
|
||||
X(MinimizeOnClose, true) \
|
||||
X(DownloadPath, defaultDownloadPath) \
|
||||
X(ScreenshotPath, {}) \
|
||||
X(EnableNotifications, true) \
|
||||
|
||||
@ -56,11 +56,15 @@ AvatarRegistry::addOrUpdateImage(const QString& id)
|
||||
}
|
||||
return uid;
|
||||
}
|
||||
|
||||
// HACK: There is still a timing issue with when this function is called.
|
||||
// The reason that avatar duplication was happening is that when the LRC account id is changed via
|
||||
// the account combobox, the ui updates itself and calls getUID for the avatars that it needs to
|
||||
// load, although by this point, the cache has not yet been cleared here. This ends up executing
|
||||
// after the getUID calls.
|
||||
void
|
||||
AvatarRegistry::connectAccount()
|
||||
{
|
||||
uidMap_.clear();
|
||||
clearCache();
|
||||
connect(lrcInstance_->getCurrentContactModel(),
|
||||
&ContactModel::profileUpdated,
|
||||
this,
|
||||
@ -93,3 +97,9 @@ AvatarRegistry::getUid(const QString& id)
|
||||
}
|
||||
return it.value();
|
||||
}
|
||||
|
||||
void
|
||||
AvatarRegistry::clearCache()
|
||||
{
|
||||
uidMap_.clear();
|
||||
}
|
||||
|
||||
@ -45,6 +45,8 @@ public:
|
||||
// add or update a specific image in the cache
|
||||
Q_SLOT QString addOrUpdateImage(const QString& id);
|
||||
|
||||
Q_INVOKABLE void clearCache();
|
||||
|
||||
Q_SIGNALS:
|
||||
void avatarUidChanged(const QString& id);
|
||||
|
||||
|
||||
@ -354,10 +354,11 @@ CallAdapter::onCallInfosChanged(const QString& accountId, const QString& callId)
|
||||
}
|
||||
|
||||
void
|
||||
CallAdapter::onCallAddedToConference(const QString& callId, const QString& confId)
|
||||
CallAdapter::onCallAddedToConference(const QString& callId, const QString& conversationId, const QString& confId)
|
||||
{
|
||||
Q_UNUSED(callId)
|
||||
Q_UNUSED(confId)
|
||||
Q_UNUSED(conversationId)
|
||||
saveConferenceSubcalls();
|
||||
}
|
||||
|
||||
@ -389,16 +390,13 @@ CallAdapter::hangUpACall(const QString& accountId, const QString& convUid)
|
||||
}
|
||||
|
||||
void
|
||||
CallAdapter::setCallMedia(const QString& accountId, const QString& convUid, bool video)
|
||||
CallAdapter::setCallMedia(const QString& accountId, const QString& convUid, bool videoMuted)
|
||||
{
|
||||
const auto& convInfo = lrcInstance_->getConversationFromConvUid(convUid, accountId);
|
||||
if (convInfo.uid.isEmpty())
|
||||
return;
|
||||
try {
|
||||
lrcInstance_->getAccountInfo(accountId).callModel->updateCallMediaList(convInfo.callId,
|
||||
video);
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
lrcInstance_->getAccountInfo(accountId).callModel->setVideoMuted(convInfo.callId, videoMuted);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@ -67,7 +67,7 @@ public:
|
||||
Q_INVOKABLE void placeAudioOnlyCall();
|
||||
Q_INVOKABLE void placeCall();
|
||||
Q_INVOKABLE void hangUpACall(const QString& accountId, const QString& convUid);
|
||||
Q_INVOKABLE void setCallMedia(const QString& accountId, const QString& convUid, bool video);
|
||||
Q_INVOKABLE void setCallMedia(const QString& accountId, const QString& convUid, bool videoMuted);
|
||||
Q_INVOKABLE void acceptACall(const QString& accountId, const QString& convUid);
|
||||
|
||||
Q_INVOKABLE void connectCallModel(const QString& accountId);
|
||||
@ -122,7 +122,7 @@ public Q_SLOTS:
|
||||
void onAccountChanged();
|
||||
void onCallStatusChanged(const QString& accountId, const QString& callId);
|
||||
void onCallStatusChanged(const QString& callId, int code);
|
||||
void onCallAddedToConference(const QString& callId, const QString& confId);
|
||||
void onCallAddedToConference(const QString& callId, const QString& conversationId, const QString& confId);
|
||||
void onCallStarted(const QString& callId);
|
||||
void onCallEnded(const QString& callId);
|
||||
void onCallInfosChanged(const QString& accountId, const QString& callId);
|
||||
|
||||
@ -362,36 +362,32 @@ CallOverlayModel::clearControls()
|
||||
}
|
||||
|
||||
void
|
||||
CallOverlayModel::registerFilter(QObject* object, QQuickItem* item)
|
||||
CallOverlayModel::setEventFilterActive(QObject* object, QQuickItem* item, bool isActive)
|
||||
{
|
||||
QQuickWindow* window = qobject_cast<QQuickWindow*>(object);
|
||||
if (!window || !item) {
|
||||
C_WARN << "Attempting to register an invalid object or item" << object << item;
|
||||
C_WARN << "Attempting to" << (isActive ? "register" : "unregister")
|
||||
<< "an invalid object or item" << window << item;
|
||||
return;
|
||||
}
|
||||
if (watchedItems_.contains(item)) {
|
||||
C_DBG << "Item already registered" << item;
|
||||
}
|
||||
watchedItems_.push_back(item);
|
||||
if (watchedItems_.size() == 1) {
|
||||
window->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CallOverlayModel::unregisterFilter(QObject* object, QQuickItem* item)
|
||||
{
|
||||
QQuickWindow* window = qobject_cast<QQuickWindow*>(object);
|
||||
if (!window || !item) {
|
||||
C_WARN << "Attempting to unregister an invalid object or item" << object << item;
|
||||
return;
|
||||
}
|
||||
if (!watchedItems_.contains(item)) {
|
||||
C_DBG << "Item not registered" << item;
|
||||
}
|
||||
watchedItems_.removeOne(item);
|
||||
if (watchedItems_.size() == 0) {
|
||||
window->removeEventFilter(this);
|
||||
if (isActive) {
|
||||
if (watchedItems_.contains(item)) {
|
||||
C_DBG << "Item already registered" << item;
|
||||
} else {
|
||||
watchedItems_.push_back(item);
|
||||
if (watchedItems_.size() == 1) {
|
||||
window->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!watchedItems_.contains(item)) {
|
||||
C_DBG << "Item not registered" << item;
|
||||
} else {
|
||||
watchedItems_.removeOne(item);
|
||||
if (watchedItems_.size() == 0) {
|
||||
window->removeEventFilter(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -137,8 +137,7 @@ public:
|
||||
Q_INVOKABLE QVariant overflowHiddenModel();
|
||||
Q_INVOKABLE QVariant pendingConferenceesModel();
|
||||
|
||||
Q_INVOKABLE void registerFilter(QObject* object, QQuickItem* item);
|
||||
Q_INVOKABLE void unregisterFilter(QObject* object, QQuickItem* item);
|
||||
Q_INVOKABLE void setEventFilterActive(QObject* object, QQuickItem* item, bool isActive);
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1,83 +1,97 @@
|
||||
/*
|
||||
* 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 net.jami.Adapters 1.1
|
||||
import net.jami.Constants 1.1
|
||||
|
||||
// A SplitView that supports dynamic RTL and splitView state saving.
|
||||
SplitView {
|
||||
id: root
|
||||
|
||||
property bool isRTL: UtilsAdapter.isRTL
|
||||
property bool isSinglePane: false
|
||||
property bool isSwapped: false
|
||||
|
||||
onIsRTLChanged: {
|
||||
if (isRTL && isSinglePane && !isSwapped)
|
||||
return
|
||||
if ((isRTL && !isSwapped) || (!isRTL && isSwapped))
|
||||
swapItems()
|
||||
}
|
||||
onIsSinglePaneChanged: {
|
||||
if (isSwapped || isRTL)
|
||||
swapItems()
|
||||
}
|
||||
|
||||
property string splitViewStateKey: objectName
|
||||
property bool autoManageState: !(parent instanceof BaseView)
|
||||
|
||||
function saveSplitViewState() {
|
||||
UtilsAdapter.setAppValue("sv_" + splitViewStateKey, root.saveState());
|
||||
}
|
||||
|
||||
function restoreSplitViewState() {
|
||||
root.restoreState(UtilsAdapter.getAppValue("sv_" + splitViewStateKey));
|
||||
}
|
||||
|
||||
onResizingChanged: if (!resizing)
|
||||
saveSplitViewState()
|
||||
onVisibleChanged: {
|
||||
if (!autoManageState)
|
||||
return;
|
||||
visible ? restoreSplitViewState() : saveSplitViewState();
|
||||
}
|
||||
|
||||
function swapItems() {
|
||||
isSwapped = !isSwapped
|
||||
var qqci = children[0];
|
||||
if (qqci.children.length > 1) {
|
||||
// swap the children
|
||||
var tempPane = qqci.children[0];
|
||||
qqci.children[0] = qqci.children[1];
|
||||
qqci.children.push(tempPane);
|
||||
}
|
||||
}
|
||||
|
||||
handle: Rectangle {
|
||||
visible: !isSinglePane
|
||||
implicitWidth: JamiTheme.splitViewHandlePreferredWidth
|
||||
implicitHeight: root.height
|
||||
color: JamiTheme.primaryBackgroundColor
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
implicitWidth: 1
|
||||
implicitHeight: root.height
|
||||
color: JamiTheme.tabbarBorderColor
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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 net.jami.Adapters 1.1
|
||||
import net.jami.Constants 1.1
|
||||
|
||||
// A SplitView that supports dynamic RTL and splitView state saving.
|
||||
SplitView {
|
||||
id: control
|
||||
|
||||
property bool isRTL: UtilsAdapter.isRTL
|
||||
property bool isSinglePane: false
|
||||
property bool isSwapped: false
|
||||
property real handleSize: 1
|
||||
|
||||
onIsRTLChanged: {
|
||||
if (isRTL && isSinglePane && !isSwapped)
|
||||
return
|
||||
if ((isRTL && !isSwapped) || (!isRTL && isSwapped))
|
||||
swapItems()
|
||||
}
|
||||
onIsSinglePaneChanged: {
|
||||
if (isSwapped || isRTL)
|
||||
swapItems()
|
||||
}
|
||||
|
||||
property string splitViewStateKey: objectName
|
||||
property bool autoManageState: !(parent instanceof BaseView)
|
||||
|
||||
function saveSplitViewState() {
|
||||
UtilsAdapter.setAppValue("sv_" + splitViewStateKey, control.saveState());
|
||||
}
|
||||
|
||||
function restoreSplitViewState() {
|
||||
control.restoreState(UtilsAdapter.getAppValue("sv_" + splitViewStateKey));
|
||||
}
|
||||
|
||||
onResizingChanged: if (!resizing)
|
||||
saveSplitViewState()
|
||||
onVisibleChanged: {
|
||||
if (!autoManageState)
|
||||
return;
|
||||
visible ? restoreSplitViewState() : saveSplitViewState();
|
||||
}
|
||||
|
||||
function swapItems() {
|
||||
isSwapped = !isSwapped
|
||||
var qqci = children[0];
|
||||
if (qqci.children.length > 1) {
|
||||
// swap the children
|
||||
var tempPane = qqci.children[0];
|
||||
qqci.children[0] = qqci.children[1];
|
||||
qqci.children.push(tempPane);
|
||||
}
|
||||
}
|
||||
|
||||
handle: Rectangle {
|
||||
id: handleRoot
|
||||
|
||||
readonly property int defaultSize: control.handleSize
|
||||
|
||||
implicitWidth: control.orientation === Qt.Horizontal ? handleRoot.defaultSize : control.width
|
||||
implicitHeight: control.orientation === Qt.Horizontal ? control.height : handleRoot.defaultSize
|
||||
|
||||
color: JamiTheme.tabbarBorderColor
|
||||
|
||||
containmentMask: Item {
|
||||
// In the default configuration, the total handle size is the sum of the default size of the
|
||||
// handle and the extra handle size (4). If the layout is not right-to-left (RTL), the handle
|
||||
// is positioned at 0 on the X-axis, otherwise it's positioned to the left by the extra handle
|
||||
// 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: !UtilsAdapter.isRTL ? 0 : -extraHandleSize
|
||||
readonly property real handleSize: handleRoot.defaultSize + extraHandleSize
|
||||
|
||||
x: control.orientation === Qt.Horizontal ? handleXPosition : 0
|
||||
width: control.orientation === Qt.Horizontal ? handleSize : handleRoot.width
|
||||
height: control.orientation === Qt.Horizontal ? handleRoot.height : handleSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,8 @@ VideoView {
|
||||
crop: true
|
||||
visible: isRendering && visibilityCondition
|
||||
|
||||
Component.onDestruction: VideoDevices.stopDevice(rendererId);
|
||||
|
||||
function startWithId(id, force = false) {
|
||||
if (id !== undefined && id.length === 0) {
|
||||
stop();
|
||||
|
||||
@ -164,7 +164,7 @@ BaseModalDialog {
|
||||
appWindow,
|
||||
"commoncomponents/JamiFileDialog.qml",
|
||||
{
|
||||
title: JamiStrings.selectAvatarImage,
|
||||
title: JamiStrings.selectProfilePicture,
|
||||
fileMode: JamiFileDialog.OpenFile,
|
||||
folder: StandardPaths.writableLocation(
|
||||
StandardPaths.PicturesLocation),
|
||||
|
||||
@ -230,6 +230,12 @@ Control {
|
||||
RowLayout {
|
||||
id: msgRowlayout
|
||||
|
||||
HoverHandler {
|
||||
id: parenthandler
|
||||
}
|
||||
|
||||
property bool msgHovered: CurrentAccount.type !== Profile.Type.SIP && root.type !== Interaction.Type.CALL && Body !== "" && (bubbleArea.bubbleHovered || hovered || more.hovered || share.hovered || parenthandler.hovered)
|
||||
|
||||
Layout.preferredHeight: {
|
||||
var h = innerContent.height + root.extraHeight;
|
||||
if (emojiReactions.emojis !== "")
|
||||
@ -278,14 +284,10 @@ 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
|
||||
|
||||
HoverHandler {
|
||||
id: bgHandler
|
||||
}
|
||||
|
||||
PushButton {
|
||||
id: more
|
||||
objectName: "more"
|
||||
@ -299,24 +301,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: msgRowlayout.msgHovered
|
||||
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(() => msgRowlayout.msgHovered);
|
||||
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 +334,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 +350,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: msgRowlayout.msgHovered
|
||||
|
||||
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: msgRowlayout.msgHovered
|
||||
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(() => msgRowlayout.msgHovered);
|
||||
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 +440,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 {
|
||||
@ -424,9 +482,9 @@ Control {
|
||||
id: editedRow
|
||||
anchors.left: root.bigMsg ? bubble.left : timestampItem.left
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: root.bigMsg || bubble.isDeleted ? 6 : 10
|
||||
anchors.bottomMargin: root.bigMsg ? 6 : 10
|
||||
anchors.leftMargin: root.bigMsg ? 10 : -timestampItem.width - 16
|
||||
visible: bubble.isEdited
|
||||
visible: bubble.isEdited && !bubble.isDeleted
|
||||
z: 1
|
||||
ResponsiveImage {
|
||||
id: editedImage
|
||||
@ -466,6 +524,11 @@ Control {
|
||||
MessagesAdapter.openUrl(root.hoveredLink);
|
||||
}
|
||||
}
|
||||
|
||||
onDoubleClicked: {
|
||||
MessagesAdapter.editId = "";
|
||||
MessagesAdapter.replyToId = Id;
|
||||
}
|
||||
property bool bubbleHovered: containsMouse || textHovered
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
@ -583,6 +646,7 @@ Control {
|
||||
id: status
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
width: JamiTheme.avatarReadReceiptSize
|
||||
property bool isAlone: CurrentConversation.members.count === 1
|
||||
|
||||
Rectangle {
|
||||
id: sending
|
||||
@ -593,7 +657,7 @@ Control {
|
||||
border.color: JamiTheme.sending
|
||||
border.width: 1
|
||||
color: JamiTheme.transparentColor
|
||||
visible: isOutgoing && Status === Interaction.Status.SENDING
|
||||
visible: isOutgoing && Status === Interaction.Status.SENDING && !status.isAlone
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
@ -624,6 +688,22 @@ Control {
|
||||
anchors.bottom: parent.bottom
|
||||
readers: root.readers
|
||||
}
|
||||
|
||||
Component {
|
||||
id: selfReadIconComp
|
||||
Avatar {
|
||||
width: JamiTheme.avatarReadReceiptSize
|
||||
height: JamiTheme.avatarReadReceiptSize
|
||||
mode: Avatar.Mode.Account
|
||||
imageId: CurrentAccount.id
|
||||
showPresenceIndicator: false
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
active: status.isAlone && CurrentConversation.lastSelfMessageId === Id
|
||||
sourceComponent: selfReadIconComp
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -89,8 +89,10 @@ BaseContextMenu {
|
||||
emojiPicker.emojiIsPicked.connect(function (content) {
|
||||
if (emojiReplied.includes(content)) {
|
||||
MessagesAdapter.removeEmojiReaction(CurrentConversation.id, content, msgId);
|
||||
parent.setBindings();
|
||||
} else {
|
||||
MessagesAdapter.addEmojiReaction(CurrentConversation.id, content, msgId);
|
||||
parent.setBindings();
|
||||
}
|
||||
});
|
||||
if (emojiPicker !== null) {
|
||||
@ -107,8 +109,11 @@ BaseContextMenu {
|
||||
property bool isScrolling: listView.verticalScrollBar.active
|
||||
|
||||
onOpened: root.closeWithoutAnimation = false
|
||||
onClosed: if (emojiPicker)
|
||||
emojiPicker.closeEmojiPicker()
|
||||
onClosed: {
|
||||
if (emojiPicker) {
|
||||
emojiPicker.closeEmojiPicker();
|
||||
}
|
||||
}
|
||||
|
||||
function getQuickEmojiListModel() {
|
||||
const defaultModel = ["👍", "👎", "😂"];
|
||||
@ -153,7 +158,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 +180,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 +203,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;
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
|
||||
}
|
||||
case Role::Draft: {
|
||||
if (!item.uid.isEmpty())
|
||||
return lrcInstance_->getContentDraft(item.uid, item.accountId);
|
||||
return lrcInstance_->getContentDraft(item.uid, item.accountId)["text"];
|
||||
return {};
|
||||
}
|
||||
case Role::ActiveCallsCount: {
|
||||
@ -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);
|
||||
@ -133,7 +137,7 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
|
||||
auto bestName = interaction.authorUri == accInfo.profileInfo.uri
|
||||
? accInfo.accountModel->bestNameForAccount(accInfo.id)
|
||||
: accInfo.contactModel->bestNameForContact(
|
||||
interaction.authorUri);
|
||||
interaction.authorUri);
|
||||
lastInteractionBody
|
||||
= interaction::getContactInteractionString(bestName,
|
||||
interaction::to_action(
|
||||
|
||||
@ -152,7 +152,7 @@ CurrentConversation::updateData()
|
||||
updateProfile(convId);
|
||||
updateActiveCalls(accountId, convId);
|
||||
} catch (...) {
|
||||
qWarning() << "Can't update current conversation data for" << convId;
|
||||
qWarning() << "An error occurred while updating current conversation data for" << convId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -29,13 +29,13 @@ void
|
||||
DBusErrorHandler::errorCallback()
|
||||
{
|
||||
qDebug() << "Dring has possibly crashed, "
|
||||
"or has been killed... will wait 2.5 seconds and try to reconnect";
|
||||
"or has been killed… will wait 2.5 seconds before attempting to reconnect.";
|
||||
|
||||
Q_EMIT showDaemonReconnectPopup(true);
|
||||
|
||||
QTimer::singleShot(2500, this, [this]() {
|
||||
if ((!lrc::api::Lrc::isConnected()) || (!lrc::api::Lrc::dbusIsValid())) {
|
||||
qDebug() << "Could not reconnect to the daemon";
|
||||
qDebug() << "An error occurred while attempting to reconnect to the daemon.";
|
||||
Q_EMIT daemonReconnectFailed();
|
||||
} else {
|
||||
static_cast<DBusErrorHandler&>(GlobalInstances::dBusErrorHandler())
|
||||
|
||||
@ -141,14 +141,14 @@ private Q_SLOTS:
|
||||
connection_ = server_->nextPendingConnection();
|
||||
connect(connection_, &QLocalSocket::readyRead, this, [this] {
|
||||
QLocalSocket* clientSocket = (QLocalSocket*) sender();
|
||||
QByteArray recievedData;
|
||||
recievedData = clientSocket->readAll();
|
||||
if (recievedData == terminateSeq_) {
|
||||
QByteArray receivedData;
|
||||
receivedData = clientSocket->readAll();
|
||||
if (receivedData == terminateSeq_) {
|
||||
qWarning() << "Received terminate signal.";
|
||||
mainAppInstance_->quit();
|
||||
} else {
|
||||
qDebug() << "Received start URI:" << recievedData;
|
||||
auto startUri = QString::fromLatin1(recievedData);
|
||||
qDebug() << "Received start URI:" << receivedData;
|
||||
auto startUri = QString::fromLatin1(receivedData);
|
||||
mainAppInstance_->handleUriAction(startUri);
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
@ -348,30 +352,36 @@ LRCInstance::stopAudioMeter()
|
||||
});
|
||||
}
|
||||
|
||||
QString
|
||||
QVariantMap
|
||||
LRCInstance::getContentDraft(const QString& convUid, const QString& accountId)
|
||||
{
|
||||
auto draftKey = accountId + "_" + convUid;
|
||||
return contentDrafts_[draftKey];
|
||||
QVariantMap draftMap;
|
||||
draftMap["text"] = contentDrafts_[draftKey];
|
||||
draftMap["files"] = fileDrafts_[draftKey];
|
||||
|
||||
return draftMap;
|
||||
}
|
||||
|
||||
void
|
||||
LRCInstance::setContentDraft(const QString& convUid,
|
||||
const QString& accountId,
|
||||
const QString& content)
|
||||
const QString& textDraft,
|
||||
const QList<QString>& filePathDraft)
|
||||
{
|
||||
if (accountId.isEmpty() || convUid.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto draftKey = accountId + "_" + convUid;
|
||||
|
||||
// prevent a senseless dataChanged signal from the
|
||||
// model if nothing has changed
|
||||
if (contentDrafts_[draftKey] == content)
|
||||
if (contentDrafts_[draftKey] == textDraft && fileDrafts_[draftKey] == filePathDraft) {
|
||||
return;
|
||||
}
|
||||
|
||||
contentDrafts_[draftKey] = content;
|
||||
contentDrafts_[draftKey] = textDraft;
|
||||
fileDrafts_[draftKey] = filePathDraft;
|
||||
// this signal is only needed to update the current smartlist
|
||||
Q_EMIT draftSaved(convUid);
|
||||
}
|
||||
|
||||
@ -102,10 +102,12 @@ public:
|
||||
Q_INVOKABLE void deselectConversation();
|
||||
Q_INVOKABLE void makeConversationPermanent(const QString& convId = {},
|
||||
const QString& accountId = {});
|
||||
Q_INVOKABLE QString getContentDraft(const QString& convUid, const QString& accountId);
|
||||
Q_INVOKABLE QVariantMap getContentDraft(const QString& convUid, const QString& accountId);
|
||||
Q_INVOKABLE void setContentDraft(const QString& convUid,
|
||||
const QString& accountId,
|
||||
const QString& content);
|
||||
const QString& textDraft,
|
||||
const QList<QString>& filePathDraft);
|
||||
|
||||
Q_INVOKABLE int indexOfActiveCall(const QString& confId,
|
||||
const QString& uri,
|
||||
const QString& deviceId);
|
||||
@ -157,6 +159,7 @@ private:
|
||||
QString selectedConvUid_;
|
||||
MapStringString contentDrafts_;
|
||||
MapStringString lastConferences_;
|
||||
MapStringListString fileDrafts_;
|
||||
|
||||
conversation::Info invalid {"", nullptr};
|
||||
|
||||
|
||||
@ -425,7 +425,8 @@ MainApplication::initQmlLayer()
|
||||
&screenInfo_,
|
||||
this);
|
||||
|
||||
QUrl url;
|
||||
QUrl url = u"qrc:/MainApplicationWindow.qml"_qs;
|
||||
#ifdef QT_DEBUG
|
||||
if (parser_.isSet("test")) {
|
||||
// List the QML files in the project source tree.
|
||||
const auto targetTestComponent = findResource(parser_.value("test"));
|
||||
@ -439,9 +440,8 @@ MainApplication::initQmlLayer()
|
||||
engine_->rootContext()->setContextProperty("testWidth", testWidth);
|
||||
engine_->rootContext()->setContextProperty("testHeight", testHeight);
|
||||
url = u"qrc:/ComponentTestWindow.qml"_qs;
|
||||
} else {
|
||||
url = u"qrc:/MainApplicationWindow.qml"_qs;
|
||||
}
|
||||
#endif
|
||||
QObject::connect(
|
||||
engine_.get(),
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
|
||||
@ -48,10 +48,10 @@ ListSelectionView {
|
||||
leftPaneItem: viewCoordinator.getView("SidePanel", true)
|
||||
|
||||
rightPaneItem: StackLayout {
|
||||
id: conversationStackLayout
|
||||
objectName: "ConversationLayout"
|
||||
|
||||
currentIndex: !CurrentConversation.hasCall ? 0 : 1
|
||||
onCurrentIndexChanged: chatView.parent = currentIndex === 1 ? callStackView.chatViewContainer : chatViewContainer
|
||||
currentIndex: CurrentConversation.hasCall ? 1 : 0
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
@ -64,24 +64,35 @@ ListSelectionView {
|
||||
ChatView {
|
||||
id: chatView
|
||||
anchors.fill: parent
|
||||
inCallView: parent == callStackView.chatViewContainer
|
||||
|
||||
// Use callStackView.chatViewContainer only when hasCall is true
|
||||
// and callStackView.chatViewContainer not null.
|
||||
// Because after a swarm call ends, callStackView.chatViewContainer might not be null
|
||||
// due to a lack of call state change signals for the swarm call.
|
||||
readonly property bool hasCall: CurrentConversation.hasCall
|
||||
readonly property var inCallChatContainer: hasCall ? callStackView.chatViewContainer : null
|
||||
|
||||
// Parent the chat view to the call stack view when in call.
|
||||
parent: inCallChatContainer ? inCallChatContainer : chatViewContainer
|
||||
inCallView: parent === callStackView.chatViewContainer
|
||||
|
||||
readonly property string currentConvId: CurrentConversation.id
|
||||
onCurrentConvIdChanged: {
|
||||
if (!CurrentConversation.hasCall) {
|
||||
Qt.callLater(focusChatView);
|
||||
} else {
|
||||
dismiss();
|
||||
callStackView.contentView.forceActiveFocus();
|
||||
}
|
||||
Qt.callLater(function() {
|
||||
if (CurrentConversation.hasCall) {
|
||||
callStackView.contentView.forceActiveFocus();
|
||||
} else {
|
||||
focusChatView();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onDismiss: {
|
||||
if (!inCallView) {
|
||||
viewNode.dismiss();
|
||||
} else {
|
||||
if (inCallView) {
|
||||
callStackView.chatViewContainer.visible = false;
|
||||
callStackView.contentView.forceActiveFocus();
|
||||
} else {
|
||||
viewNode.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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,30 @@ 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: {
|
||||
// HACK: Only display the version string if it has been constructed properly.
|
||||
// This is a workaround for an issue that occurs due to the way Linux
|
||||
// packaging is done, where the git repository is not available in the
|
||||
// build source at configure time, which is when the version files are
|
||||
// generated, so we prevent a "." from being displayed if the version
|
||||
// string is not available.
|
||||
var contentStr = JamiStrings.buildID + ": " + UtilsAdapter.getBuildIDStr();
|
||||
const versionStr = UtilsAdapter.getVersionStr()
|
||||
if (versionStr.length > 1) {
|
||||
contentStr += "\n" + JamiStrings.version + ": " + (isBeta ? "(Beta) " : "") + versionStr
|
||||
}
|
||||
return contentStr
|
||||
}
|
||||
|
||||
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();
|
||||
@ -207,10 +189,4 @@ Label {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: "Ctrl+,"
|
||||
context: Qt.ApplicationShortcut
|
||||
onActivated: settingBtnClicked()
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ import net.jami.Models 1.1
|
||||
import net.jami.Adapters 1.1
|
||||
import net.jami.Constants 1.1
|
||||
import net.jami.Enums 1.1
|
||||
import net.jami.Helpers 1.1
|
||||
import "../../commoncomponents"
|
||||
|
||||
Popup {
|
||||
@ -35,7 +36,7 @@ Popup {
|
||||
|
||||
// limit the number of accounts shown at once
|
||||
implicitHeight: {
|
||||
return visible ? Math.min(JamiTheme.accountListItemHeight * Math.min(6, listView.model.count + 1) + 96, appWindow.height - parent.height) : 0;
|
||||
return visible ? Math.min(JamiTheme.accountListItemHeight * Math.min(6, listView.model.count + 1) + 91, appWindow.height - parent.height) : 0;
|
||||
}
|
||||
padding: 0
|
||||
modal: true
|
||||
@ -60,23 +61,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
|
||||
@ -241,8 +225,12 @@ Popup {
|
||||
delegate: AccountItemDelegate {
|
||||
height: JamiTheme.accountListItemHeight
|
||||
width: root.width
|
||||
|
||||
onClicked: {
|
||||
root.close();
|
||||
// This is a workaround for the synchronicity issue
|
||||
// in AvatarRegistry::connectAccount()
|
||||
AvatarRegistry.clearCache();
|
||||
LRCInstance.currentAccountId = ID;
|
||||
}
|
||||
}
|
||||
@ -257,11 +245,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);
|
||||
|
||||
@ -119,7 +119,8 @@ Item {
|
||||
"title": JamiStrings.backupAccountHere,
|
||||
"fileMode": JamiFileDialog.SaveFile,
|
||||
"folder": StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/Desktop",
|
||||
"nameFilters": [JamiStrings.jamiArchiveFiles, JamiStrings.allFiles]
|
||||
"nameFilters": [JamiStrings.jamiAccountFiles, JamiStrings.allFiles],
|
||||
"defaultSuffix": ".jac"
|
||||
});
|
||||
dlg.fileAccepted.connect(function (file) {
|
||||
// Is there password? If so, go to password dialog, else, go to following directly
|
||||
|
||||
@ -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)
|
||||
},
|
||||
|
||||
@ -25,7 +25,11 @@ import "../../commoncomponents"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property alias chatViewContainer: ongoingCallPage.chatViewContainer
|
||||
property var chatViewContainer: {
|
||||
if (callStackMainView.item instanceof OngoingCallPage)
|
||||
return callStackMainView.item.chatViewContainer;
|
||||
return undefined;
|
||||
}
|
||||
property alias contentView: callStackMainView
|
||||
|
||||
property var sipKeys: ["1", "2", "3", "A", "4", "5", "6", "B", "7", "8", "9", "C", "*", "0", "#", "D"]
|
||||
@ -61,44 +65,49 @@ Item {
|
||||
// TODO: this should all be done by listening to
|
||||
// parent visibility change or parent `Component.onDestruction`
|
||||
function needToCloseInCallConversationAndPotentialWindow() {
|
||||
ongoingCallPage.closeInCallConversation();
|
||||
ongoingCallPage.closeContextMenuAndRelatedWindows();
|
||||
if (callStackMainView.item instanceof OngoingCallPage) {
|
||||
callStackMainView.item.closeInCallConversation();
|
||||
callStackMainView.item.closeContextMenuAndRelatedWindows();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleFullScreen() {
|
||||
if (!layoutManager.isCallFullscreen) {
|
||||
layoutManager.pushFullScreenItem(callStackMainView.currentItem, callStackMainView, null, null);
|
||||
layoutManager.pushFullScreenItem(callStackMainView.item, callStackMainView, null, null);
|
||||
} else {
|
||||
layoutManager.removeFullScreenItem(callStackMainView.currentItem);
|
||||
layoutManager.removeFullScreenItem(callStackMainView.item);
|
||||
}
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
Loader {
|
||||
id: callStackMainView
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
property Item currentItem: itemAt(currentIndex)
|
||||
|
||||
currentIndex: {
|
||||
sourceComponent: {
|
||||
switch (CurrentCall.status) {
|
||||
case Call.Status.IN_PROGRESS:
|
||||
case Call.Status.CONNECTED:
|
||||
case Call.Status.PAUSED:
|
||||
return 1;
|
||||
return ongoingCallPageComponent;
|
||||
case Call.Status.SEARCHING:
|
||||
case Call.Status.CONNECTING:
|
||||
case Call.Status.INCOMING_RINGING:
|
||||
case Call.Status.OUTGOING_RINGING:
|
||||
return initialCallPageComponent;
|
||||
default:
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
InitialCallPage {
|
||||
Component {
|
||||
id: initialCallPageComponent
|
||||
InitialCallPage {}
|
||||
}
|
||||
OngoingCallPage {
|
||||
id: ongoingCallPage
|
||||
|
||||
Component {
|
||||
id: ongoingCallPageComponent
|
||||
OngoingCallPage {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,14 @@ import "../js/pluginhandlerpickercreation.js" as PluginHandlerPickerCreation
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
// HACK: Added to capture the mouse when the layouts start stacking.
|
||||
// The header and footer we're unable to be interacted with otherwise.
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
propagateComposedEvents: false
|
||||
enabled: viewCoordinator.isInSinglePaneMode
|
||||
}
|
||||
|
||||
// An enum to make the details panels more readable.
|
||||
enum ExtrasPanel {
|
||||
SwarmDetailsPanel,
|
||||
@ -133,8 +141,13 @@ Rectangle {
|
||||
target: CurrentConversation
|
||||
|
||||
function onIdChanged() {
|
||||
if (!chatViewHeader.interactionButtonsVisibility)
|
||||
if (!chatViewHeader.detailsButtonVisibility) {
|
||||
extrasPanel.closePanel();
|
||||
} else if (width < JamiTheme.mainViewMinWidth + extrasPanel.width) {
|
||||
extrasPanel.closePanel();
|
||||
} else if (!chatViewHeader.interactionButtonsVisibility) {
|
||||
extrasPanel.closePanel();
|
||||
}
|
||||
}
|
||||
|
||||
function onNeedsHost() {
|
||||
@ -222,7 +235,7 @@ Rectangle {
|
||||
onExtrasPanelWidthChanged: {
|
||||
resolvePanes();
|
||||
// This range should ensure that the panel won't restore to maximized.
|
||||
if (extrasPanelWidth !== 0 && extrasPanelWidth !== width) {
|
||||
if (extrasPanelWidth !== 0 && extrasPanelWidth !== this.width) {
|
||||
console.debug("Saving previous extras panel width: %1".arg(extrasPanelWidth));
|
||||
previousExtrasPanelWidth = extrasPanelWidth;
|
||||
}
|
||||
|
||||
@ -43,17 +43,31 @@ Rectangle {
|
||||
color: JamiTheme.primaryBackgroundColor
|
||||
|
||||
function updateMessageDraft() {
|
||||
LRCInstance.setContentDraft(previousConvId, previousAccountId, messageBar.text);
|
||||
// Store the current files that have not been sent, if any. Do the same for the message draft.
|
||||
var filePathDraft = [];
|
||||
while(messageBar.fileContainer.filesToSendCount > 0) {
|
||||
var currentIndex = messageBar.fileContainer.filesToSendListModel.index(0, 0);
|
||||
var filePath = messageBar.fileContainer.filesToSendListModel.data(currentIndex, FilesToSend.FilePath);
|
||||
filePathDraft.push(filePath);
|
||||
messageBar.fileContainer.filesToSendListModel.removeFromPending(0);
|
||||
}
|
||||
LRCInstance.setContentDraft(previousConvId, previousAccountId, messageBar.text, filePathDraft);
|
||||
previousConvId = CurrentConversation.id;
|
||||
previousAccountId = CurrentAccount.id;
|
||||
|
||||
// turn off the button animations when switching convs
|
||||
messageBar.animate = false;
|
||||
messageBar.textAreaObj.clearText();
|
||||
|
||||
// restore the draft state of contents for a specific conversation
|
||||
var restoredContent = LRCInstance.getContentDraft(CurrentConversation.id, CurrentAccount.id);
|
||||
if (restoredContent) {
|
||||
messageBar.textAreaObj.insertText(restoredContent);
|
||||
messageBar.textAreaObj.insertText(restoredContent["text"]);
|
||||
for (var i = 0; i < restoredContent["files"].length; ++i) {
|
||||
messageBar.fileContainer.filesToSendListModel.addToPending(restoredContent["files"][i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Connections {
|
||||
@ -134,7 +148,7 @@ Rectangle {
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: footerColumnLayout.width
|
||||
Layout.leftMargin: 0
|
||||
Layout.leftMargin: marginSize
|
||||
Layout.rightMargin: marginSize
|
||||
Layout.bottomMargin: marginSize
|
||||
Layout.preferredHeight: height
|
||||
|
||||
@ -23,7 +23,6 @@ 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"
|
||||
|
||||
Rectangle {
|
||||
@ -46,6 +45,8 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
property bool detailsButtonVisibility: detailsButton.visible
|
||||
|
||||
readonly property bool interactionButtonsVisibility: {
|
||||
if (CurrentConversation.inCall)
|
||||
return false;
|
||||
@ -59,9 +60,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
property bool addMemberVisibility: {
|
||||
return swarmDetailsVisibility
|
||||
&& !CurrentConversation.isCoreDialog
|
||||
&& !CurrentConversation.isRequest;
|
||||
return swarmDetailsVisibility && !CurrentConversation.isCoreDialog && !CurrentConversation.isRequest;
|
||||
}
|
||||
|
||||
property bool swarmDetailsVisibility: {
|
||||
@ -79,8 +78,10 @@ Rectangle {
|
||||
anchors.rightMargin: 10 + layoutManager.qwkSystemButtonSpacing.right
|
||||
spacing: 16
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
JamiPushButton {
|
||||
id: backToWelcomeViewButton
|
||||
QWKSetParentHitTestVisible {
|
||||
}
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
Layout.leftMargin: 8
|
||||
@ -88,7 +89,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()
|
||||
}
|
||||
@ -107,8 +108,10 @@ Rectangle {
|
||||
|
||||
color: JamiTheme.transparentColor
|
||||
|
||||
ColumnLayout { QWKSetParentHitTestVisible {}
|
||||
ColumnLayout {
|
||||
id: userNameOrIdColumnLayout
|
||||
QWKSetParentHitTestVisible {
|
||||
}
|
||||
objectName: "userNameOrIdColumnLayout"
|
||||
|
||||
height: parent.height
|
||||
@ -146,72 +149,66 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
id: startAAudioCallButton
|
||||
JamiPushButton {
|
||||
id: startAudioCallButton
|
||||
QWKSetParentHitTestVisible {
|
||||
}
|
||||
|
||||
visible: interactionButtonsVisibility &&
|
||||
(!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm))
|
||||
visible: interactionButtonsVisibility && (!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm))
|
||||
source: JamiResources.place_audiocall_24dp_svg
|
||||
toolTipText: JamiStrings.placeAudioCall
|
||||
toolTipText: JamiStrings.startAudioCall
|
||||
|
||||
onClicked: CallAdapter.placeAudioOnlyCall()
|
||||
}
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
id: startAVideoCallButton
|
||||
JamiPushButton {
|
||||
id: startVideoCallButton
|
||||
QWKSetParentHitTestVisible {
|
||||
}
|
||||
|
||||
visible: interactionButtonsVisibility &&
|
||||
CurrentAccount.videoEnabled_Video &&
|
||||
(!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm))
|
||||
visible: interactionButtonsVisibility && CurrentAccount.videoEnabled_Video && (!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm))
|
||||
source: JamiResources.videocam_24dp_svg
|
||||
toolTipText: JamiStrings.placeVideoCall
|
||||
toolTipText: JamiStrings.startVideoCall
|
||||
|
||||
onClicked: CallAdapter.placeCall()
|
||||
}
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
id: addParticipantsButton
|
||||
JamiPushButton {
|
||||
id: inviteMembersButton
|
||||
QWKSetParentHitTestVisible {
|
||||
}
|
||||
|
||||
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
|
||||
JamiPushButton {
|
||||
id: selectExtensionsButton
|
||||
QWKSetParentHitTestVisible {
|
||||
}
|
||||
|
||||
visible: PluginAdapter.chatHandlersListCount && interactionButtonsVisibility
|
||||
source: JamiResources.plugins_24dp_svg
|
||||
toolTipText: JamiStrings.showPlugins
|
||||
toolTipText: JamiStrings.showExtensions
|
||||
|
||||
onClicked: pluginSelector()
|
||||
}
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
id: sendContactRequestButton
|
||||
objectName: "sendContactRequestButton"
|
||||
|
||||
visible: CurrentConversation.isTemporary || CurrentConversation.isBanned
|
||||
source: JamiResources.add_people_24dp_svg
|
||||
toolTipText: JamiStrings.addToConversations
|
||||
|
||||
onClicked: CurrentConversation.isBanned ?
|
||||
MessagesAdapter.unbanConversation(CurrentConversation.id) :
|
||||
MessagesAdapter.sendConversationRequest()
|
||||
}
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
JamiPushButton {
|
||||
id: searchMessagesButton
|
||||
QWKSetParentHitTestVisible {
|
||||
}
|
||||
objectName: "searchMessagesButton"
|
||||
|
||||
checkable: true
|
||||
checked: extrasPanel.isOpen(ChatView.MessagesResearchPanel)
|
||||
visible: root.swarmDetailsVisibility
|
||||
source: JamiResources.ic_baseline_search_24dp_svg
|
||||
source: JamiResources.ic_baseline_search_24dp_svg
|
||||
toolTipText: JamiStrings.search
|
||||
|
||||
onClicked: extrasPanel.switchToPanel(ChatView.MessagesResearchPanel)
|
||||
@ -224,8 +221,10 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
JamiPushButton { QWKSetParentHitTestVisible {}
|
||||
JamiPushButton {
|
||||
id: detailsButton
|
||||
QWKSetParentHitTestVisible {
|
||||
}
|
||||
objectName: "detailsButton"
|
||||
|
||||
checkable: true
|
||||
|
||||
@ -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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user