mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-10-30 07:53:33 +08:00
Compare commits
211 Commits
nightly/20
...
beta/20250
| Author | SHA1 | Date | |
|---|---|---|---|
| b15d692a0e | |||
| e76bcbd555 | |||
| b5a979e6b1 | |||
| 898444dd3c | |||
| 99f246016d | |||
| e24f3d91e8 | |||
| 3a7850b398 | |||
| 1e1750024b | |||
| 2ba53a2e40 | |||
| ceec1f95b9 | |||
| 1ac3db4f33 | |||
| 93d3d18c7b | |||
| d4b7891f48 | |||
| d7c294edd0 | |||
| 945cfe176d | |||
| fa3a153896 | |||
| e9106b2bcc | |||
| a967518d45 | |||
| 7ebed53e97 | |||
| ca05963c40 | |||
| df98c6c3fd | |||
| 05501e33e9 | |||
| 91780ae400 | |||
| 4900ca9f1b | |||
| 0f965aae28 | |||
| f8c29fc4a1 | |||
| 2e1889caf1 | |||
| 8070d1bfc2 | |||
| 4ee1a309a1 | |||
| 0333016c44 | |||
| 32b7525ee3 | |||
| 32b941ab96 | |||
| e4932abd39 | |||
| 718d1d266d | |||
| 8d55f352b4 | |||
| 2a72da564e | |||
| 88d0539085 | |||
| 4b1c299a1d | |||
| 479da3ca54 | |||
| 02140a11c4 | |||
| b5dbe23c17 | |||
| ff5f94b34a | |||
| def2e19abe | |||
| 69430c4af3 | |||
| 911fdbc9e5 | |||
| 80b3336f1b | |||
| f8bafd4154 | |||
| b8b06ccfa1 | |||
| 6cb5a8206a | |||
| ae1a2462e2 | |||
| 31581db7f5 | |||
| c323dcfe13 | |||
| 8a31aca346 | |||
| 7eeabbe1c6 | |||
| 8c0ecaf3c5 | |||
| c91bff35b6 | |||
| cb05b4afd0 | |||
| 4419f7bfbc | |||
| deaa15a36e | |||
| 6b70ffcf3e | |||
| a407fa2c47 | |||
| 3143d60760 | |||
| 73eacd5125 | |||
| fc70ddc6dc | |||
| e2e5a0c8cc | |||
| dd9ed8d57d | |||
| 7eea1484c5 | |||
| 6fac40340b | |||
| 04a1544d56 | |||
| 91fd8a0295 | |||
| bad5698e71 | |||
| 7f0a94dd48 | |||
| 81112ff1f8 | |||
| b63eb384b6 | |||
| ebcc60c570 | |||
| c12a753979 | |||
| 386b578e47 | |||
| 76417edfa4 | |||
| 960fdc0f05 | |||
| 2567d81359 | |||
| e700d8160a | |||
| 37065cb7d6 | |||
| 03efee4c14 | |||
| 04e43b07f4 | |||
| a00a191371 | |||
| 65d3befad8 | |||
| 84ac5dba02 | |||
| a149a575a7 | |||
| 407561732f | |||
| 82c2a9d9c6 | |||
| 1414e1804f | |||
| 7146f20b18 | |||
| 5ee4990534 | |||
| 0d1bdfdfdd | |||
| f3dd3b4643 | |||
| d3c76eac8d | |||
| 33da15daba | |||
| 82c876c0fa | |||
| 83765dcebf | |||
| b76570b892 | |||
| ffb9bb8748 | |||
| 416137d6dd | |||
| ffcfaffc90 | |||
| a950a3f9e7 | |||
| 3c279b292d | |||
| c19af7f97f | |||
| 0087f1b8a8 | |||
| 19f7f43912 | |||
| c818eeedce | |||
| 0f08dbcf59 | |||
| 7d3331d235 | |||
| aa375a7f89 | |||
| 9b51f26e80 | |||
| 6b0adb7005 | |||
| 217efe603b | |||
| 00febee4c7 | |||
| c88797163c | |||
| f7a771f7e1 | |||
| 03756aedd0 | |||
| 8af5a25607 | |||
| fe4c63b775 | |||
| 4ee1f1a5d3 | |||
| 37f29c9882 | |||
| 1bfacdbb76 | |||
| c5e455a9de | |||
| f489f21271 | |||
| 560f44f6f1 | |||
| d0639b4e88 | |||
| 79d3c7be03 | |||
| 5b6cc620cd | |||
| f4c997c62f | |||
| 2974cb52bd | |||
| 98e71a7c89 | |||
| 0b49077de9 | |||
| 5540001e7a | |||
| 71527afd76 | |||
| 15d62f0200 | |||
| 0024721192 | |||
| a540cbf529 | |||
| 6b142cd374 | |||
| 4e235d60e8 | |||
| 05954191a2 | |||
| 56b8aa16e7 | |||
| 7acf48d919 | |||
| 70c64a5947 | |||
| ca74c961ef | |||
| 32a44c9820 | |||
| d1a8ec3af0 | |||
| 12628713f1 | |||
| 7659080b34 | |||
| 4152700848 | |||
| cba84f2cb7 | |||
| 7289a92b2b | |||
| c6a474aa96 | |||
| 2226d30123 | |||
| 529b7cf529 | |||
| 49d83fd937 | |||
| 484808a2eb | |||
| dccc6c7e18 | |||
| 53a3d32114 | |||
| 6fdcfc6317 | |||
| 5352ded3e3 | |||
| 9a0ed9995e | |||
| 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 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,6 +7,7 @@ doc/Doxyfile
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
|
||||
10
.gitmodules
vendored
10
.gitmodules
vendored
@ -21,9 +21,17 @@
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/md4c"]
|
||||
path = 3rdparty/md4c
|
||||
url = https://github.com/mity/md4c.git
|
||||
url = https://github.com/fsimonfc/md4c.git
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/tidy-html5"]
|
||||
path = 3rdparty/tidy-html5
|
||||
url = https://github.com/htacg/tidy-html5.git
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/zxing-cpp"]
|
||||
path = 3rdparty/zxing-cpp
|
||||
url = https://github.com/nu-book/zxing-cpp.git
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/hunspell"]
|
||||
path = 3rdparty/hunspell
|
||||
url = https://gitlab.savoirfairelinux.com/jami/hunspell.git
|
||||
ignore = dirty
|
||||
|
||||
1
3rdparty/hunspell
vendored
Submodule
1
3rdparty/hunspell
vendored
Submodule
Submodule 3rdparty/hunspell added at 749cd84a0b
2
3rdparty/md4c
vendored
2
3rdparty/md4c
vendored
Submodule 3rdparty/md4c updated: ad8d41127b...635f296735
1
3rdparty/zxing-cpp
vendored
Submodule
1
3rdparty/zxing-cpp
vendored
Submodule
Submodule 3rdparty/zxing-cpp added at a920817b6f
191
CMakeLists.txt
191
CMakeLists.txt
@ -1,11 +1,4 @@
|
||||
# Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Albert Babí <albert.babi@savoirfairelinux.com>
|
||||
# Author: Amin Bandali <amin.bandali@savoirfairelinux.com>
|
||||
# Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
# Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
# Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
|
||||
# Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
# Copyright (C) 2020-2025 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
|
||||
@ -50,9 +43,13 @@ if(ENABLE_ASAN AND NOT MSVC)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
endif()
|
||||
|
||||
# Enable this option when building for production.
|
||||
option(ENABLE_CRASHREPORTS "Enable crash reports" OFF)
|
||||
|
||||
# These values are exposed to QML and are better off being defined as values.
|
||||
define_macro_with_value(WITH_WEBENGINE)
|
||||
define_macro_with_value(APPSTORE)
|
||||
define_macro_with_value(ENABLE_CRASHREPORTS)
|
||||
|
||||
# jami-core
|
||||
if(NOT WITH_DAEMON_SUBMODULE)
|
||||
@ -72,12 +69,6 @@ set(CLIENT_INCLUDE_DIRS, "")
|
||||
set(CLIENT_LINK_DIRS, "")
|
||||
set(CLIENT_LIBS, "")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if(NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -ggdb")
|
||||
endif()
|
||||
|
||||
include(${PROJECT_SOURCE_DIR}/extras/build/cmake/contrib_tools.cmake)
|
||||
set(EXTRA_PATCHES_DIR ${PROJECT_SOURCE_DIR}/extras/patches)
|
||||
|
||||
@ -85,31 +76,79 @@ list(APPEND QWINDOWKIT_OPTIONS
|
||||
QWINDOWKIT_BUILD_WIDGETS OFF
|
||||
QWINDOWKIT_INSTALL OFF
|
||||
QWINDOWKIT_BUILD_STATIC ON
|
||||
QWINDOWKIT_BUILD_QUICK ON
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
# Beta config
|
||||
if(BETA)
|
||||
message(STATUS "Beta config enabled")
|
||||
add_definitions(-DBETA)
|
||||
endif()
|
||||
set(JAMI_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/x64/${CMAKE_BUILD_TYPE})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND QWINDOWKIT_OPTIONS QWINDOWKIT_ENABLE_WINDOWS_SYSTEM_BORDERS OFF)
|
||||
endif()
|
||||
|
||||
# qmsetup uses the wrong package dir on some distributions
|
||||
# (including Fedora and openSUSE Leap at least)
|
||||
check_distro_needs_qmsetup_patch(DISTRO_NEEDS_QMSETUP_PATCH)
|
||||
if(DISTRO_NEEDS_QMSETUP_PATCH)
|
||||
list(APPEND QWINDOWKIT_PATCHES ${EXTRA_PATCHES_DIR}/0001-fix-fedora-fc-build.patch)
|
||||
set(qmsetup_cmake_path ${CMAKE_BINARY_DIR}/_install/lib64/cmake/qmsetup)
|
||||
# If qwindowkit can't find qmsetup via cmake's find_package function, it will install it and
|
||||
# then call find_package again. Unfortunately, even the second call to find_package sometimes
|
||||
# fails due to qmsetup having been installed in the wrong directory. The following patch
|
||||
# ensures that qmsetup is always installed in the directory where find_package looks for it.
|
||||
if(NOT WIN32)
|
||||
list(APPEND QWINDOWKIT_PATCHES ${EXTRA_PATCHES_DIR}/0001-fix-qm_install_package-function.patch)
|
||||
endif()
|
||||
|
||||
# qwindowkit (frameless window)
|
||||
add_fetch_content(
|
||||
TARGET qwindowkit
|
||||
URL https://github.com/stdware/qwindowkit.git
|
||||
BRANCH 79b1f3110754f9c21af2d7dacbd07b1a9dbaf6ef
|
||||
BRANCH 758b00cb6c2d924be3a1ea137ec366dc33a5132d
|
||||
PATCHES ${QWINDOWKIT_PATCHES}
|
||||
OPTIONS ${QWINDOWKIT_OPTIONS}
|
||||
)
|
||||
list(APPEND CLIENT_INCLUDE_DIRS ${QWindowKit_BINARY_DIR}/include)
|
||||
list(APPEND CLIENT_LIBS QWindowKit::Quick)
|
||||
|
||||
# If ENABLE_CRASHREPORTS is enabled, we will use crashpad_cmake for now.
|
||||
if(ENABLE_CRASHREPORTS)
|
||||
set(ENABLE_CRASHPAD ON)
|
||||
set(CRASH_REPORT_URL "http://localhost:8080/submit" CACHE STRING "URL for crash handler uploads")
|
||||
endif()
|
||||
add_definitions(-DCRASH_REPORT_URL="${CRASH_REPORT_URL}")
|
||||
|
||||
# Crash-report client: crashpad
|
||||
if(ENABLE_CRASHPAD)
|
||||
message(STATUS "Crashpad enabled for client")
|
||||
if(WIN32)
|
||||
set(CMAKE_OBJECT_PATH_MAX 256)
|
||||
add_definitions(-DNOMINMAX)
|
||||
endif()
|
||||
add_fetch_content(
|
||||
TARGET crashpad_cmake
|
||||
URL https://github.com/TheAssemblyArmada/crashpad-cmake.git
|
||||
BRANCH 80573adcc845071401c73c99eaec7fd9847d45fb
|
||||
)
|
||||
add_definitions(-DENABLE_CRASHPAD)
|
||||
if (WIN32)
|
||||
# This makes sure the console window doesn't show up when running the
|
||||
# crashpad_handler executable.
|
||||
set_target_properties(crashpad_handler PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS")
|
||||
# Set the output directory for the crashpad_handler executable. On Windows,
|
||||
# we use either the Release or Beta directory depending on the BETA option
|
||||
# which is set above.
|
||||
set_target_properties(crashpad_handler PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${JAMI_OUTPUT_DIRECTORY_RELEASE}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if(NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -ggdb")
|
||||
endif()
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
@ -214,7 +253,7 @@ 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
|
||||
# Touch the file to ensure it exists at configure time as
|
||||
# we add it to the target_sources below.
|
||||
file(TOUCH ${VERSION_FILE})
|
||||
add_custom_target(
|
||||
@ -225,6 +264,7 @@ add_custom_target(
|
||||
-DAPP_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
|
||||
-DCORE_SOURCE_DIR=${DAEMON_DIR}
|
||||
-DCPP_INT_FILE=${VERSION_INFO_DIR}/version_info.cpp.in
|
||||
-DBUILD_VERSION=${BUILD_VERSION}
|
||||
-P ${CMAKE_SCRIPTS_DIR}/generate_version_info.cmake
|
||||
)
|
||||
list(APPEND CLIENT_INCLUDE_DIRS ${VERSION_INFO_DIR})
|
||||
@ -233,7 +273,7 @@ list(APPEND CLIENT_INCLUDE_DIRS ${VERSION_INFO_DIR})
|
||||
# QML and related code files
|
||||
# Check files in the app's src directory and force a reconfigure if it
|
||||
# changes.
|
||||
# Only include webengine resources if specified.
|
||||
# Only include WebEngine resources if specified.
|
||||
if(WITH_WEBENGINE)
|
||||
set(GEN_QRC_ARGS "--with-webengine")
|
||||
endif()
|
||||
@ -306,6 +346,8 @@ set(COMMON_SOURCES
|
||||
${APP_SRC_DIR}/conversationlistmodel.cpp
|
||||
${APP_SRC_DIR}/searchresultslistmodel.cpp
|
||||
${APP_SRC_DIR}/calloverlaymodel.cpp
|
||||
${APP_SRC_DIR}/spellcheckdictionarylistmodel.cpp
|
||||
${APP_SRC_DIR}/spellcheckadapter.cpp
|
||||
${APP_SRC_DIR}/filestosendlistmodel.cpp
|
||||
${APP_SRC_DIR}/wizardviewstepmodel.cpp
|
||||
${APP_SRC_DIR}/avatarregistry.cpp
|
||||
@ -320,10 +362,13 @@ set(COMMON_SOURCES
|
||||
${APP_SRC_DIR}/currentcall.cpp
|
||||
${APP_SRC_DIR}/messageparser.cpp
|
||||
${APP_SRC_DIR}/previewengine.cpp
|
||||
${APP_SRC_DIR}/imagedownloader.cpp
|
||||
${APP_SRC_DIR}/filedownloader.cpp
|
||||
${APP_SRC_DIR}/pluginversionmanager.cpp
|
||||
${APP_SRC_DIR}/connectioninfolistmodel.cpp
|
||||
${APP_SRC_DIR}/pluginversionmanager.cpp)
|
||||
${APP_SRC_DIR}/pluginversionmanager.cpp
|
||||
${APP_SRC_DIR}/linkdevicemodel.cpp
|
||||
${APP_SRC_DIR}/qrcodescannermodel.cpp
|
||||
${APP_SRC_DIR}/spellchecker.cpp)
|
||||
|
||||
set(COMMON_HEADERS
|
||||
${APP_SRC_DIR}/global.h
|
||||
@ -333,7 +378,6 @@ set(COMMON_HEADERS
|
||||
${APP_SRC_DIR}/appversionmanager.h
|
||||
${APP_SRC_DIR}/utils.h
|
||||
${APP_SRC_DIR}/bannedlistmodel.h
|
||||
${APP_SRC_DIR}/version.h
|
||||
${APP_SRC_DIR}/accountlistmodel.h
|
||||
${APP_SRC_DIR}/instancemanager.h
|
||||
${APP_SRC_DIR}/connectivitymonitor.h
|
||||
@ -375,6 +419,8 @@ set(COMMON_HEADERS
|
||||
${APP_SRC_DIR}/conversationlistmodel.h
|
||||
${APP_SRC_DIR}/searchresultslistmodel.h
|
||||
${APP_SRC_DIR}/calloverlaymodel.h
|
||||
${APP_SRC_DIR}/spellcheckdictionarylistmodel.h
|
||||
${APP_SRC_DIR}/spellcheckadapter.h
|
||||
${APP_SRC_DIR}/filestosendlistmodel.h
|
||||
${APP_SRC_DIR}/wizardviewstepmodel.h
|
||||
${APP_SRC_DIR}/avatarregistry.h
|
||||
@ -389,10 +435,15 @@ set(COMMON_HEADERS
|
||||
${APP_SRC_DIR}/currentcall.h
|
||||
${APP_SRC_DIR}/messageparser.h
|
||||
${APP_SRC_DIR}/htmlparser.h
|
||||
${APP_SRC_DIR}/imagedownloader.h
|
||||
${APP_SRC_DIR}/filedownloader.h
|
||||
${APP_SRC_DIR}/pluginversionmanager.h
|
||||
${APP_SRC_DIR}/connectioninfolistmodel.h
|
||||
${APP_SRC_DIR}/pttlistener.h)
|
||||
${APP_SRC_DIR}/pttlistener.h
|
||||
${APP_SRC_DIR}/crashreportclient.h
|
||||
${APP_SRC_DIR}/crashreporter.h
|
||||
${APP_SRC_DIR}/linkdevicemodel.h
|
||||
${APP_SRC_DIR}/qrcodescannermodel.h
|
||||
${APP_SRC_DIR}/spellchecker.h)
|
||||
|
||||
# For libavutil/avframe.
|
||||
set(LIBJAMI_CONTRIB_DIR "${DAEMON_DIR}/contrib")
|
||||
@ -411,6 +462,34 @@ endif()
|
||||
# Define PREFER_VULKAN to prefer Vulkan over the default API
|
||||
# on GNU/Linux and Windows. Metal is always preferred on macOS.
|
||||
|
||||
if(ENABLE_CRASHREPORTS)
|
||||
set(CRASHREPORT_CLIENT_DIR ${APP_SRC_DIR}/crashreportclients)
|
||||
if(ENABLE_CRASHPAD)
|
||||
list(APPEND CLIENT_LIBS crashpad_client)
|
||||
list(APPEND COMMON_SOURCES ${CRASHREPORT_CLIENT_DIR}/crashpad.cpp)
|
||||
list(APPEND COMMON_HEADERS ${CRASHREPORT_CLIENT_DIR}/crashpad.h)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
# hunspell
|
||||
pkg_search_module(hunspell IMPORTED_TARGET hunspell)
|
||||
if(hunspell_FOUND)
|
||||
message(STATUS "hunspell found")
|
||||
set(HUNSPELL_LIBRARIES PkgConfig::hunspell)
|
||||
else()
|
||||
message(STATUS "hunspell not found - building hunspell")
|
||||
|
||||
set(HUNSPELL_DIR ${PROJECT_SOURCE_DIR}/3rdparty/hunspell)
|
||||
|
||||
# Build using the submodule and its CMakeLists.txt
|
||||
add_subdirectory(${HUNSPELL_DIR} hunspell_build EXCLUDE_FROM_ALL)
|
||||
|
||||
set(HUNSPELL_INCLUDE_DIR ${HUNSPELL_DIR}/src)
|
||||
set(HUNSPELL_LIBRARIES hunspell::hunspell)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(WINDOWS_SYS_LIBS
|
||||
windowsapp.lib
|
||||
@ -456,16 +535,6 @@ if(MSVC)
|
||||
set(JAMID_SRC_PATH ${DAEMON_DIR}/contrib/msvc/include)
|
||||
set(GNUTLS_LIB ${DAEMON_DIR}/contrib/msvc/lib/x64/libgnutls.lib)
|
||||
|
||||
# Beta config
|
||||
if(BETA)
|
||||
message(STATUS "Beta config enabled")
|
||||
add_definitions(-DBETA)
|
||||
set(JAMI_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/x64/Beta)
|
||||
else()
|
||||
set(JAMI_OUTPUT_DIRECTORY_RELEASE
|
||||
${PROJECT_SOURCE_DIR}/x64/Release)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${JAMID_SRC_PATH}
|
||||
${LIBCLIENT_SRC_DIR}
|
||||
@ -483,8 +552,6 @@ elseif (NOT APPLE)
|
||||
${APP_SRC_DIR}/screencastportal.h)
|
||||
list(APPEND QT_MODULES DBus)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_check_modules(GLIB REQUIRED glib-2.0)
|
||||
if(GLIB_FOUND)
|
||||
add_definitions(${GLIB_CFLAGS_OTHER})
|
||||
@ -567,6 +634,13 @@ else() # APPLE
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Adding HUNSPELL_INCLUDE_DIR" ${HUNSPELL_INCLUDE_DIR})
|
||||
list(APPEND CLIENT_INCLUDE_DIRS ${HUNSPELL_INCLUDE_DIR} ${CMAKE_BINARY_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/hunspell/src)
|
||||
|
||||
message(STATUS "Adding HUNSPELL_LIBRARIES" ${HUNSPELL_INCLUDE_DIR})
|
||||
list(APPEND CLIENT_LIBS ${HUNSPELL_LIBRARIES})
|
||||
|
||||
# Qt find package
|
||||
if(QT6_VER AND QT6_PATH)
|
||||
message(STATUS "Using custom Qt version")
|
||||
@ -635,6 +709,15 @@ list(APPEND CLIENT_LINK_DIRS ${tidy_BINARY_DIR}/Release)
|
||||
list(APPEND CLIENT_INCLUDE_DIRS ${tidy_SOURCE_DIR}/include)
|
||||
list(APPEND CLIENT_LIBS tidy-static)
|
||||
|
||||
# ZXing-cpp configuration
|
||||
set(BUILD_EXAMPLES OFF CACHE BOOL "")
|
||||
set(BUILD_BLACKBOX_TESTS OFF CACHE BOOL "")
|
||||
add_subdirectory(3rdparty/zxing-cpp EXCLUDE_FROM_ALL)
|
||||
|
||||
# Add ZXing-cpp to includes and libraries
|
||||
list(APPEND CLIENT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/zxing-cpp/core/src)
|
||||
list(APPEND CLIENT_LIBS ZXing)
|
||||
|
||||
# common executable sources
|
||||
qt_add_executable(
|
||||
${PROJECT_NAME}
|
||||
@ -644,9 +727,12 @@ qt_add_executable(
|
||||
${COMMON_SOURCES}
|
||||
${QML_RESOURCES}
|
||||
${QML_RESOURCES_QML}
|
||||
${SFPM_OBJECTS})
|
||||
${SFPM_OBJECTS}
|
||||
src/app/spellcheckadapter.h src/app/spellcheckadapter.cpp)
|
||||
|
||||
# Make sure we can find the generated version file
|
||||
#add_dependencies(${PROJECT_NAME} hunspell)
|
||||
|
||||
# Ensure the generated version file can be found.
|
||||
add_dependencies(${PROJECT_NAME} generate_version_info)
|
||||
|
||||
foreach(MODULE ${QT_MODULES})
|
||||
@ -715,13 +801,13 @@ elseif (NOT APPLE)
|
||||
# Install .desktop in XDG desktop direcory so that it is recognized
|
||||
# by the system.
|
||||
install(
|
||||
FILES ${DATA_DIR}/jami.desktop
|
||||
FILES ${DATA_DIR}/net.jami.Jami.desktop
|
||||
DESTINATION ${JAMI_DATA_PREFIX}/applications)
|
||||
|
||||
# Install .desktop in the jami data directory, so that it can be
|
||||
# copied to the autostart directory by the client.
|
||||
install(
|
||||
FILES ${DATA_DIR}/jami.desktop
|
||||
FILES ${DATA_DIR}/net.jami.Jami.desktop
|
||||
DESTINATION "${JAMI_DATA_PREFIX}/${PROJECT_NAME}"
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) # 644
|
||||
|
||||
@ -740,6 +826,11 @@ elseif (NOT APPLE)
|
||||
PRIVATE
|
||||
JAMI_INSTALL_PREFIX="${JAMI_DATA_PREFIX}")
|
||||
|
||||
target_compile_definitions(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
HUNSPELL_INSTALL_DIR="${HUNSPELL_DICT_DIR}")
|
||||
|
||||
# Logos
|
||||
install(
|
||||
FILES resources/images/jami.svg
|
||||
@ -756,9 +847,19 @@ elseif (NOT APPLE)
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps
|
||||
RENAME jami.xpm)
|
||||
|
||||
# AppStream metadata
|
||||
#
|
||||
# MetaInfo file:
|
||||
install(
|
||||
FILES ${DATA_DIR}/jami.appdata.xml
|
||||
FILES ${DATA_DIR}/net.jami.Jami.metainfo.xml
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
|
||||
# Catalog file:
|
||||
if(NOT DEFINED APPSTREAM_CATALOG_DIR)
|
||||
set(APPSTREAM_CATALOG_DIR /share/swcatalog/xml)
|
||||
endif()
|
||||
install(
|
||||
FILES ${DATA_DIR}/jami.xml
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}${APPSTREAM_CATALOG_DIR})
|
||||
|
||||
# man page
|
||||
install(
|
||||
|
||||
30
INSTALL.md
30
INSTALL.md
@ -113,7 +113,7 @@ sudo ./build.py --dependencies
|
||||
Then, you can build daemon and the client using:
|
||||
|
||||
```bash
|
||||
./build.py --install
|
||||
./build.py --install [--qt=<path/to/qt> (this needs to be the same as in the previous ./build.py --init)]
|
||||
```
|
||||
|
||||
If you use a Qt version that is not system-wide installed, you need to
|
||||
@ -189,7 +189,7 @@ Only 64-bit MSVC build can be compiled.
|
||||
|
||||
- Download [Qt (Open Source)](https://www.qt.io/download-open-source?hsCtaTracking=9f6a2170-a938-42df-a8e2-a9f0b1d6cdce%7C6cb0de4f-9bb5-4778-ab02-bfb62735f3e5)
|
||||
|
||||
- Using the online installer, install the following Qt 6.6.1 components:
|
||||
- Using the online installer, install the following Qt 6.6.2 components:
|
||||
|
||||
- Git 2.10.2
|
||||
- MSVC 2019 64-bit
|
||||
@ -237,9 +237,14 @@ Only 64-bit MSVC build can be compiled.
|
||||
|
||||
- Using a new **Non-Elevated Command Prompt**
|
||||
|
||||
```bash
|
||||
python build.py --init --qt <path-to-qt-bin-folder> (e.g. C:/Qt/6.6.2/msvc2019_64)
|
||||
```
|
||||
|
||||
```bash
|
||||
python build.py --install --qt <path-to-qt-bin-folder> (e.g. C:/Qt/6.6.2/msvc2019_64)
|
||||
```
|
||||
> **CMake** Note: The build script does not specify what CMake generator should be used. This means CMake will search the system for the appropriate generator, which might not always select the right one if, for instance, Ninja is installed. To resolve that, the CMAKE_GENERATOR environment variable can be used, set to "Visual Studio 16 2019" or "Visual Studio 19 2022" depending on the installed Visual Studio version.
|
||||
|
||||
> **SDK** Note:
|
||||
> Jami can be build with more recent Windows SDK than the one specified in the table above. However, if your have another version than SDK 10.0.18362.0 installed, you need to identify it according to the example below. And you still need to have the required version in addition to the one you chose.
|
||||
@ -343,9 +348,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,6 @@
|
||||
<?define Name="Jami" ?>
|
||||
<?define ExeName="Jami" ?>
|
||||
<?define AppName="Jami" ?>
|
||||
|
||||
<?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"?>
|
||||
<?define ReleaseDir="..\x64\Release"?>
|
||||
</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>
|
||||
@ -13,20 +16,10 @@
|
||||
<InstallerPlatform>x64</InstallerPlatform>
|
||||
<DefineSolutionProperties>false</DefineSolutionProperties>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>HarvestPath=..\x64\Release</DefineConstants>
|
||||
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||
<CompilerAdditionalOptions>
|
||||
</CompilerAdditionalOptions>
|
||||
<WixVariables>
|
||||
</WixVariables>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Beta|x64' ">
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||
<DefineConstants>HarvestPath=..\x64\Beta</DefineConstants>
|
||||
<PropertyGroup>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
|
||||
<DefineConstants>AppHarvestPath=..\x64\Release;CrtHarvestPath=$(VC_CRT_Dir)</DefineConstants>
|
||||
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||
<CompilerAdditionalOptions>
|
||||
</CompilerAdditionalOptions>
|
||||
@ -35,8 +28,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 +51,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\Release"
|
||||
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>
|
||||
@ -38,7 +38,7 @@ cf [INSTALL.md](/INSTALL.md)
|
||||
|
||||
# License
|
||||
|
||||
Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
Copyright (C) 2020-2025 Savoir-faire Linux Inc.
|
||||
|
||||
Jami 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.
|
||||
|
||||
|
||||
43
build.py
43
build.py
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# build.py --- Convenience script for building and running Jami
|
||||
|
||||
# Copyright (C) 2016-2024 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2016-2025 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
|
||||
@ -112,7 +112,7 @@ ZYPPER_CLIENT_DEPENDENCIES = [
|
||||
'qt6-svg-devel', 'qt6-multimedia-devel', 'qt6-multimedia-imports',
|
||||
'qt6-declarative-devel', 'qt6-qmlcompiler-private-devel',
|
||||
'qt6-quickcontrols2-devel', 'qt6-shadertools-devel',
|
||||
'qrencode-devel', 'NetworkManager-devel'
|
||||
'qrencode-devel', 'NetworkManager-devel', 'hunspell-devel', 'libhunspell-devel'
|
||||
]
|
||||
|
||||
ZYPPER_QT_WEBENGINE = [
|
||||
@ -139,7 +139,7 @@ DNF_CLIENT_DEPENDENCIES = [
|
||||
'libnotify-devel',
|
||||
'qt6-qtbase-devel',
|
||||
'qt6-qtsvg-devel', 'qt6-qtmultimedia-devel', 'qt6-qtdeclarative-devel',
|
||||
'qrencode-devel', 'NetworkManager-libnm-devel'
|
||||
'qrencode-devel', 'NetworkManager-libnm-devel', 'hunspell-devel', 'libhunspell-devel'
|
||||
]
|
||||
|
||||
DNF_QT_WEBENGINE = ['qt6-qtwebengine-devel']
|
||||
@ -171,7 +171,7 @@ APT_CLIENT_DEPENDENCIES = [
|
||||
'qml6-module-qtquick-dialogs', 'qml6-module-qtquick-layouts',
|
||||
'qml6-module-qtquick-shapes', 'qml6-module-qtquick-window',
|
||||
'qml6-module-qtquick-templates', 'qml6-module-qt-labs-platform',
|
||||
'libqrencode-dev', 'libnm-dev'
|
||||
'libqrencode-dev', 'libnm-dev', 'hunspell', 'libhunspell-dev'
|
||||
]
|
||||
|
||||
APT_QT_WEBENGINE = [
|
||||
@ -194,7 +194,7 @@ PACMAN_CLIENT_DEPENDENCIES = [
|
||||
'qt6-declarative', 'qt6-5compat', 'qt6-multimedia',
|
||||
'qt6-networkauth', 'qt6-shadertools',
|
||||
'qt6-svg', 'qt6-tools',
|
||||
'qrencode', 'libnm'
|
||||
'qrencode', 'libnm', 'hunspell'
|
||||
]
|
||||
|
||||
PACMAN_QT_WEBENGINE = ['qt6-webengine']
|
||||
@ -299,7 +299,7 @@ def run_dependencies(args):
|
||||
print("The win32 version does not install dependencies with this script.\nPlease continue with the --install instruction.")
|
||||
sys.exit(1)
|
||||
elif args.distribution == 'guix':
|
||||
print(f"Building the profile defined in '{GUIX_MANIFEST}'...")
|
||||
print(f"Building the profile defined in '{GUIX_MANIFEST}'…")
|
||||
execute_script([f'guix shell --manifest={GUIX_MANIFEST} -- true'])
|
||||
|
||||
else:
|
||||
@ -316,7 +316,7 @@ def run_init(args):
|
||||
client_hooks_dir = '.git/hooks'
|
||||
daemon_hooks_dir = '.git/modules/daemon/hooks'
|
||||
|
||||
print("Installing commit-msg hooks...")
|
||||
print("Installing commit-msg hooks…")
|
||||
# Copy the commit-msg hook to all modules in the same way.
|
||||
for hooks_dir in [client_hooks_dir, daemon_hooks_dir]:
|
||||
if not os.path.exists(hooks_dir):
|
||||
@ -324,7 +324,7 @@ def run_init(args):
|
||||
copy_file("./extras/scripts/commit-msg",
|
||||
os.path.join(hooks_dir, "commit-msg"))
|
||||
|
||||
print("Installing pre-commit hooks...")
|
||||
print("Installing pre-commit hooks…")
|
||||
format_script = "./extras/scripts/format.py"
|
||||
# Prepend with the python executable if on Windows (not WSL).
|
||||
if sys.platform == 'win32':
|
||||
@ -366,13 +366,27 @@ def cwd(path):
|
||||
def run_install(args):
|
||||
# Platforms with special compilation scripts
|
||||
if args.distribution == WIN32_DISTRIBUTION_NAME:
|
||||
# Build daemon if not using pywinmake
|
||||
if not args.pywinmake:
|
||||
with cwd('daemon/compat/msvc'):
|
||||
execute_script([f'python winmake.py -iv -s {args.sdk} -b daemon'])
|
||||
|
||||
# Prepare the build-windows.py script call
|
||||
build_windows = 'extras/scripts/build-windows.py'
|
||||
execute_script([f'python {build_windows} --init'])
|
||||
execute_script([f'python {build_windows} --qt={args.qt}'])
|
||||
# Initialize build environment
|
||||
execute_script([f'python {build_windows} --init --qt={args.qt}'])
|
||||
|
||||
# Construct build command with options
|
||||
build_cmd = [
|
||||
'python',
|
||||
build_windows,
|
||||
f'--qt={args.qt}'
|
||||
]
|
||||
|
||||
if args.enable_crash_reports:
|
||||
build_cmd.append('--enable-crash-reports')
|
||||
|
||||
execute_script([' '.join(build_cmd)])
|
||||
return True
|
||||
|
||||
# Unix-like platforms
|
||||
@ -401,6 +415,8 @@ def run_install(args):
|
||||
install_args += ('-a', args.arch)
|
||||
if args.extra_cmake_flags:
|
||||
install_args += ('-D', args.extra_cmake_flags)
|
||||
if args.enable_crash_reports:
|
||||
install_args.append('-C')
|
||||
|
||||
if args.distribution == OSX_DISTRIBUTION_NAME:
|
||||
# The `universal_newlines` parameter has been renamed to `text` in
|
||||
@ -604,7 +620,7 @@ def run_run(args):
|
||||
client_process.wait()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\nCaught KeyboardInterrupt...")
|
||||
print("\nCaught KeyboardInterrupt…")
|
||||
|
||||
finally:
|
||||
if args.debug:
|
||||
@ -614,7 +630,7 @@ def run_run(args):
|
||||
try:
|
||||
# Only kill the processes if they are running, as they
|
||||
# could have been closed by the user.
|
||||
print("Killing processes...")
|
||||
print("Killing processes…")
|
||||
if args.no_libwrap:
|
||||
jamid_log.close()
|
||||
if jamid_process.poll() is None:
|
||||
@ -750,6 +766,9 @@ def parse_args():
|
||||
# Allow supplying extra congifure flags to the client cmake.
|
||||
ap.add_argument('--extra-cmake-flags', type=str,
|
||||
help='Extra flags to pass to the client cmake')
|
||||
ap.add_argument('--enable-crash-reports',
|
||||
action='store_true', default=False,
|
||||
help='Enable crash reporting')
|
||||
|
||||
dist = choose_distribution()
|
||||
|
||||
|
||||
2
daemon
2
daemon
Submodule daemon updated: 7c41450f29...41384122a8
@ -1,7 +1,7 @@
|
||||
# Taken from:
|
||||
# https://cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F
|
||||
#
|
||||
# Copyright (C) 2021-2024 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2021-2025 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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2024 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2024-2025 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
|
||||
@ -17,32 +17,6 @@
|
||||
include(FetchContent)
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# Helper function to check if we're on a distribution that requires us
|
||||
# to apply a patch in order for qmsetup to use the right package directory
|
||||
function(check_distro_needs_qmsetup_patch DISTRO_NEEDS_QMSETUP_PATCH)
|
||||
set(${DISTRO_NEEDS_QMSETUP_PATCH} FALSE PARENT_SCOPE)
|
||||
# Check for the existence of /etc/os-release
|
||||
if(EXISTS "/etc/os-release")
|
||||
# Read the content of the file
|
||||
file(READ "/etc/os-release" OS_RELEASE_CONTENT)
|
||||
# Check if the distribution is Fedora or Red Hat-based
|
||||
string(REGEX MATCH "ID=fedora|ID_LIKE=\"rhel fedora\"|ID_LIKE=\"rhel centos fedora\"" RED_HAT_BASED "${OS_RELEASE_CONTENT}")
|
||||
# Check if the distribution is openSUSE Leap
|
||||
string(REGEX MATCH "ID=\"opensuse-leap\"" OPENSUSE_LEAP "${OS_RELEASE_CONTENT}")
|
||||
if(RED_HAT_BASED)
|
||||
set(${DISTRO_NEEDS_QMSETUP_PATCH} TRUE PARENT_SCOPE)
|
||||
message(STATUS "Running on a Red Hat-based distribution (Fedora, RHEL, CentOS, etc.)")
|
||||
elseif(OPENSUSE_LEAP)
|
||||
set(${DISTRO_NEEDS_QMSETUP_PATCH} TRUE PARENT_SCOPE)
|
||||
message(STATUS "Running on openSUSE Leap")
|
||||
else()
|
||||
message(STATUS "Distribution is not openSUSE Leap or Red Hat-based")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Cannot determine the distribution type: /etc/os-release not found")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Helper function to add external content with patches and options.
|
||||
# Parameters:
|
||||
# TARGET: Name of the target to create
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2024 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2024-2025 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
|
||||
|
||||
@ -24,6 +24,7 @@ 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)
|
||||
set(BUILD_VERSION_STRING ${BUILD_VERSION})
|
||||
|
||||
# Get output file names with the .in extension removed
|
||||
get_filename_component(VERSION_CPP_FILENAME ${CPP_INT_FILE} NAME_WE)
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
# Copyright (C) 2015-2024 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
|
||||
# Author: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>
|
||||
# Author: Amin Bandali <amin.bandali@savoirfairelinux.com>
|
||||
# Copyright (C) 2015-2025 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
|
||||
|
||||
@ -4,11 +4,24 @@ ENV DEBIAN_FRONTEND noninteractive
|
||||
ENV QT_QUICK_BACKEND software
|
||||
ENV QT_QPA_PLATFORM offscreen
|
||||
|
||||
RUN apt-get clean
|
||||
RUN apt-get update && \
|
||||
apt-get install -y devscripts equivs
|
||||
apt-get install -y --no-install-recommends ca-certificates && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Use only the custom Savoir-faire Linux Ubuntu mirror
|
||||
RUN rm -f /etc/apt/sources.list /etc/apt/sources.list.d/* && \
|
||||
echo "deb http://gpl.savoirfairelinux.net/pub/mirrors/ubuntu jammy main restricted universe multiverse" > /etc/apt/sources.list && \
|
||||
echo "deb http://gpl.savoirfairelinux.net/pub/mirrors/ubuntu jammy-updates main restricted universe multiverse" >> /etc/apt/sources.list && \
|
||||
echo "deb http://gpl.savoirfairelinux.net/pub/mirrors/ubuntu jammy-security main restricted universe multiverse" >> /etc/apt/sources.list
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
devscripts \
|
||||
equivs \
|
||||
gnupg \
|
||||
dirmngr \
|
||||
curl
|
||||
|
||||
RUN apt install gnupg dirmngr ca-certificates curl --no-install-recommends
|
||||
RUN curl -s https://dl.jami.net/public-key.gpg | tee /usr/share/keyrings/jami-archive-keyring.gpg > /dev/null
|
||||
RUN sh -c "echo 'deb [signed-by=/usr/share/keyrings/jami-archive-keyring.gpg] https://dl.jami.net/internal/ubuntu_22.04/ jami main' > /etc/apt/sources.list.d/jami.list"
|
||||
RUN apt-get update && apt-get install libqt-jami -y
|
||||
@ -69,7 +82,8 @@ RUN apt-get install -y pandoc \
|
||||
libcppunit-dev \
|
||||
googletest \
|
||||
libgtest-dev \
|
||||
wget
|
||||
wget && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install a recent version of CMake
|
||||
ADD extras/packaging/gnu-linux/scripts/install-cmake.sh /opt/install-cmake.sh
|
||||
|
||||
2
extras/ci/client-qt-gnulinux/Jenkinsfile
vendored
2
extras/ci/client-qt-gnulinux/Jenkinsfile
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022-2024 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2022-2025 Savoir-faire Linux Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
|
||||
9
extras/crash-reports/example-submission-servers/.gitignore
vendored
Normal file
9
extras/crash-reports/example-submission-servers/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# python virtual environment
|
||||
venv/
|
||||
# python compiled files
|
||||
*.pyc
|
||||
# python cache
|
||||
__pycache__
|
||||
|
||||
# example output
|
||||
crash_reports/
|
||||
51
extras/crash-reports/example-submission-servers/README.md
Normal file
51
extras/crash-reports/example-submission-servers/README.md
Normal file
@ -0,0 +1,51 @@
|
||||
# Crash report submission server examples
|
||||
|
||||
## Overview
|
||||
|
||||
This directory contains an example of a crash report submission server. This server is responsible for receiving crash reports from clients and storing them. The example is written in Python and uses the Flask web framework with Waitress as the WSGI server. It exposes one endpoint for submitting crash reports on the `/submit` path using the POST method on port `8080`.
|
||||
|
||||
It also contains an example of a crash report access server. This server is responsible for displaying the crash reports. It uses port `8081` and provides a simple HTML page that lists crash reports by page.
|
||||
|
||||
## Running the examples
|
||||
|
||||
To run the examples, you need to have Python 3 installed. You can just use the virtual environment provided in this directory. To activate the virtual environment, run the following commands:
|
||||
|
||||
```
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
python3 -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
|
||||
> ⚠️ On Windows, you need to use `venv\Scripts\activate` instead of `source venv/bin/activate`.
|
||||
|
||||
After activating the virtual environment, you can should be able to execute the example submission server. To run the example submission server that uses the Crashpad format, run the following command:
|
||||
|
||||
```
|
||||
python3 crashpad_submit_server.py
|
||||
```
|
||||
|
||||
To run a server that displays the crash reports, run the following command:
|
||||
|
||||
```
|
||||
python3 report_access_server.py
|
||||
```
|
||||
|
||||
> ⚠️ It is recommended to run the report access server in a way that is not publicly accessible.
|
||||
|
||||
Either server can be run on the same machine or on different machines, and each can be run using the `--debug` flag to enable debugging.
|
||||
|
||||
## Metadata
|
||||
|
||||
The crash report submission servers expect the crash reports to contain a JSON object. The JSON object should contain the following basic metadata:
|
||||
```
|
||||
{
|
||||
"build_id": "202410021437",
|
||||
"client_sha": "77149ebd62",
|
||||
"guid": "50c4218a-bcb9-48a9-8093-a06e6435cd61",
|
||||
"jamicore_sha": "cbf8f0af6",
|
||||
"platform": "Ubuntu 22.04.4 LTS_x86_64"
|
||||
}
|
||||
```
|
||||
|
||||
The `build_id` field is the build identifier of the client application. The `client_sha` field is the SHA-1 hash of the client application. The `guid` field is a unique identifier for the crash report. The `jamicore_sha` field is the SHA-1 hash of the Jami core library. The `platform` field is the platform on which the client application is running.
|
||||
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
from flask import Flask, request, jsonify
|
||||
import json
|
||||
import argparse
|
||||
|
||||
app = Flask(__name__)
|
||||
BASE_PATH = 'crash_reports'
|
||||
|
||||
@app.route('/submit', methods=['POST'])
|
||||
def submit():
|
||||
try:
|
||||
print("Received a crash report GUID: %s" % request.form.get('guid', 'No GUID provided'))
|
||||
file_storage = request.files.get('upload_file_minidump')
|
||||
dump_id = ""
|
||||
if file_storage:
|
||||
dump_id = file_storage.filename
|
||||
|
||||
# Create a directory to store the crash reports if it doesn't exist
|
||||
if not os.path.exists(BASE_PATH):
|
||||
os.makedirs(BASE_PATH)
|
||||
|
||||
filepath = os.path.join(BASE_PATH, dump_id)
|
||||
|
||||
# Attempt to write the file, fail gracefully if it already exists
|
||||
if os.path.exists(filepath):
|
||||
print(f"File {filepath} already exists.")
|
||||
return 'File already exists', 409
|
||||
with open(filepath, 'wb') as f:
|
||||
f.write(file_storage.read())
|
||||
print(f"File saved successfully at {filepath}")
|
||||
|
||||
# Now save the metadata in {request.form} as separate filename <UID>.info.
|
||||
metadata_filepath = os.path.join(BASE_PATH, f"{dump_id}.info")
|
||||
with open(metadata_filepath, 'w') as f:
|
||||
f.write(str(json.dumps(dict(request.form), indent=4)))
|
||||
else:
|
||||
print("No file found for the key 'upload_file_minidump'")
|
||||
return 'No file found', 400
|
||||
|
||||
return 'Crash report received', 200
|
||||
except OSError as e:
|
||||
print(f"Error creating directory or writing file: {e}")
|
||||
return 'Internal Server Error', 500
|
||||
except Exception as e:
|
||||
print(f"An unexpected error occurred: {e}")
|
||||
return 'Internal Server Error', 500
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Crash report submission server')
|
||||
parser.add_argument('--debug', action='store_true', help='Run in debug mode')
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.debug:
|
||||
app.run(port=8080, debug=True)
|
||||
else:
|
||||
from waitress import serve
|
||||
print("Starting production server on port 8080...")
|
||||
serve(app, host='0.0.0.0', port=8080)
|
||||
@ -0,0 +1,252 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
from flask import Flask, request, jsonify, render_template_string, send_file
|
||||
import json
|
||||
from datetime import datetime
|
||||
import argparse
|
||||
|
||||
app = Flask(__name__)
|
||||
BASE_PATH = 'crash_reports'
|
||||
|
||||
@app.route('/', methods=['GET'])
|
||||
def list_reports():
|
||||
try:
|
||||
if not os.path.exists(BASE_PATH):
|
||||
return jsonify({"error": "No reports directory found"}), 404
|
||||
|
||||
# Get page number from query parameters, default to 1
|
||||
page = int(request.args.get('page', 1))
|
||||
per_page = 10
|
||||
|
||||
reports = os.listdir(BASE_PATH)
|
||||
if not reports:
|
||||
return render_template_string("""
|
||||
<h1>Crash Reports</h1>
|
||||
<p>No crash reports found.</p>
|
||||
""")
|
||||
|
||||
# Build report pairs with metadata
|
||||
report_pairs = []
|
||||
for report in reports:
|
||||
if not report.endswith('.info'):
|
||||
info_file = f"{report}.info"
|
||||
if info_file in reports:
|
||||
try:
|
||||
dump_path = os.path.join(BASE_PATH, report)
|
||||
timestamp = os.path.getctime(dump_path)
|
||||
upload_time = datetime.fromtimestamp(timestamp)
|
||||
|
||||
with open(os.path.join(BASE_PATH, info_file), 'r') as f:
|
||||
metadata = json.load(f)
|
||||
report_pairs.append({
|
||||
'dump_file': report,
|
||||
'info_file': info_file,
|
||||
'metadata': metadata,
|
||||
'sort_key': f"{metadata.get('client_sha', '')}-{metadata.get('jamicore_sha', '')}",
|
||||
'download_name': f"{metadata.get('client_sha', 'unknown')}-{metadata.get('jamicore_sha', 'unknown')}-{metadata.get('platform', 'unknown').replace(' ', '_')}",
|
||||
'upload_time': upload_time
|
||||
})
|
||||
except json.JSONDecodeError:
|
||||
print(f"Error parsing metadata file: {info_file}")
|
||||
continue
|
||||
|
||||
# Sort reports by upload time (most recent first), then by SHA
|
||||
report_pairs.sort(key=lambda x: (-x['upload_time'].timestamp(), x['sort_key']))
|
||||
|
||||
# Calculate pagination values
|
||||
total_reports = len(report_pairs)
|
||||
total_pages = (total_reports + per_page - 1) // per_page
|
||||
page = min(max(1, page), total_pages or 1) # Handle case when total_pages is 0
|
||||
start_idx = (page - 1) * per_page
|
||||
end_idx = start_idx + per_page
|
||||
|
||||
# Get current page's reports
|
||||
current_page_reports = report_pairs[start_idx:end_idx]
|
||||
|
||||
return render_template_string("""
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Crash Reports</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 2em; }
|
||||
.header {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
.header h1 {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.report-list { list-style: none; padding: 0; }
|
||||
.report-item { margin: 1em 0; padding: 1em; border: 1px solid #ddd; border-radius: 4px; }
|
||||
.download-link {
|
||||
display: inline-block;
|
||||
padding: 8px 16px;
|
||||
background-color: #0066cc;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
.download-link:hover { background-color: #0052a3; }
|
||||
.metadata-table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 8px 0;
|
||||
}
|
||||
.metadata-table td {
|
||||
padding: 4px 8px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.metadata-table td:first-child {
|
||||
font-weight: bold;
|
||||
width: 150px;
|
||||
}
|
||||
.upload-time {
|
||||
color: #666;
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.pagination {
|
||||
margin: 1em 0;
|
||||
text-align: center;
|
||||
}
|
||||
.pagination a, .pagination span {
|
||||
display: inline-block;
|
||||
padding: 8px 16px;
|
||||
margin: 0 4px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
color: #0066cc;
|
||||
}
|
||||
.pagination .current {
|
||||
background-color: #0066cc;
|
||||
color: white;
|
||||
border-color: #0066cc;
|
||||
}
|
||||
.pagination a:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.pagination-info {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>Crash Reports</h1>
|
||||
<div class="pagination-info">
|
||||
Showing {{ start_idx + 1 }}-{{ [end_idx, total_reports] | min }} of {{ total_reports }} reports
|
||||
</div>
|
||||
<div class="pagination">
|
||||
{% if page > 1 %}
|
||||
<a href="{{ url_for('list_reports', page=1) }}">« First</a>
|
||||
<a href="{{ url_for('list_reports', page=page-1) }}">‹ Previous</a>
|
||||
{% endif %}
|
||||
|
||||
{% for p in range([1, page-2] | max, [total_pages + 1, page + 3] | min) %}
|
||||
{% if p == page %}
|
||||
<span class="current">{{ p }}</span>
|
||||
{% else %}
|
||||
<a href="{{ url_for('list_reports', page=p) }}">{{ p }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if page < total_pages %}
|
||||
<a href="{{ url_for('list_reports', page=page+1) }}">Next ›</a>
|
||||
<a href="{{ url_for('list_reports', page=total_pages) }}">Last »</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="report-list">
|
||||
{% for report in reports %}
|
||||
<div class="report-item">
|
||||
<h3>Report: {{ report['sort_key'] }}</h3>
|
||||
<div class="upload-time">
|
||||
Uploaded: {{ report['upload_time'].strftime('%Y-%m-%d %H:%M:%S') }}
|
||||
</div>
|
||||
<table class="metadata-table">
|
||||
<tr>
|
||||
<td>Platform:</td>
|
||||
<td>{{ report['metadata']['platform'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Client SHA:</td>
|
||||
<td>{{ report['metadata']['client_sha'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jami Core SHA:</td>
|
||||
<td>{{ report['metadata']['jamicore_sha'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Build ID:</td>
|
||||
<td>{{ report['metadata']['build_id'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GUID:</td>
|
||||
<td>{{ report['metadata']['guid'] }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a class="download-link" href="{{ url_for('download_report_bundle', dump_file=report['dump_file'], info_file=report['info_file'], download_name=report['download_name']) }}">
|
||||
Download Report Bundle
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
""", reports=current_page_reports, page=page, total_pages=total_pages,
|
||||
start_idx=start_idx, end_idx=end_idx, total_reports=total_reports)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error listing reports: {e}")
|
||||
return 'Internal Server Error', 500
|
||||
|
||||
@app.route('/download-bundle/<path:dump_file>/<path:info_file>/<path:download_name>')
|
||||
def download_report_bundle(dump_file, info_file, download_name):
|
||||
try:
|
||||
import zipfile
|
||||
from io import BytesIO
|
||||
|
||||
# Create a memory file for the zip
|
||||
memory_file = BytesIO()
|
||||
|
||||
# Create the zip file
|
||||
with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_DEFLATED) as zf:
|
||||
# Add the dump file
|
||||
dump_path = os.path.join(BASE_PATH, dump_file)
|
||||
zf.write(dump_path, f"{download_name}.dmp")
|
||||
|
||||
# Add the info file
|
||||
info_path = os.path.join(BASE_PATH, info_file)
|
||||
zf.write(info_path, f"{download_name}.info")
|
||||
|
||||
# Seek to the beginning of the memory file
|
||||
memory_file.seek(0)
|
||||
|
||||
return send_file(
|
||||
memory_file,
|
||||
mimetype='application/zip',
|
||||
as_attachment=True,
|
||||
download_name=f"{download_name}.zip"
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Error creating zip bundle: {e}")
|
||||
return 'Internal Server Error', 500
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Crash reports viewing server')
|
||||
parser.add_argument('--debug', action='store_true', help='Run in debug mode')
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.debug:
|
||||
app.run(port=8081, debug=True)
|
||||
else:
|
||||
from waitress import serve
|
||||
print("Starting production server on port 8081...")
|
||||
serve(app, host='0.0.0.0', port=8081)
|
||||
@ -0,0 +1,6 @@
|
||||
Flask==3.0.3
|
||||
requests==2.24.0
|
||||
markupsafe==2.1.1
|
||||
itsdangerous==2.1.2
|
||||
werkzeug==3.0.0
|
||||
waitress==3.0.2
|
||||
@ -1,131 +0,0 @@
|
||||
<?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>
|
||||
<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.
|
||||
</p>
|
||||
<p>
|
||||
Jami supports the following key features:
|
||||
</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
|
||||
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>
|
||||
<p xml:lang="hu">
|
||||
A Jami a következő főbb funkciókat támogatja:
|
||||
</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>
|
||||
|
||||
</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>
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<launchable type="desktop-id">jami.desktop</launchable>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<requires><id>net.jami.daemon</id></requires>
|
||||
|
||||
</component>
|
||||
153
extras/data/jami.xml
Normal file
153
extras/data/jami.xml
Normal file
@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<components version="0.14" origin="jami">
|
||||
<component type="desktop-application">
|
||||
<id>net.jami.Jami</id>
|
||||
<pkgname>jami</pkgname>
|
||||
<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>
|
||||
<project_license>GPL-3.0+</project_license>
|
||||
<description>
|
||||
<p>Jami, 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 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>
|
||||
<p>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 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), 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>Manage multiple SIP accounts, Jami accounts and JAMS accounts with the Jami client installed on one or multiple devices.</p>
|
||||
<p>Jami is free, unlimited, private, advertising free, compatible, fast, autonomous, and anonymous.</p>
|
||||
<p>Learn more about:</p>
|
||||
<ul>
|
||||
<li>Jami: https://jami.net/</li>
|
||||
<li>Jami extensions: https://jami.net/extensions/</li>
|
||||
<li>“Jami Account Management Server” (JAMS): https://jami.biz/</li>
|
||||
<li>Jami documentation: https://docs.jami.net/</li>
|
||||
</ul>
|
||||
<p>Follow us for more:</p>
|
||||
<ul>
|
||||
<li>Mastodon: https://mstdn.io/@Jami</li>
|
||||
<li>X: https://x.com/jami_social</li>
|
||||
<li>YouTube: https://www.youtube.com/@jami9311</li>
|
||||
</ul>
|
||||
<p>We’d love to hear from you! Join the Jami community:</p>
|
||||
<ul>
|
||||
<li>Contribute: https://jami.net/contribute/</li>
|
||||
<li>Forum: https://forum.jami.net/</li>
|
||||
</ul>
|
||||
<p>Build with Jami on your IoT project: re-use the universal communications technology of Jami with its portable library on your system of choice.</p>
|
||||
<p>Jami for Android TV is tested on NVIDIA SHIELD TV with Logitech cameras.</p>
|
||||
<p>Jami is published under the GPL license, version 3 or higher.</p>
|
||||
<p>Copyright © Savoir-faire Linux Inc.</p>
|
||||
</description>
|
||||
<description xml:lang="hu">
|
||||
<p>A Jami, 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 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 JAMS (Jami Account Management Server – Jami fiókkezelő kiszolgáló), 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>További tájékoztatás:</p>
|
||||
<ul>
|
||||
<li>Jami: https://jami.net/hu/</li>
|
||||
<li>Jami-bővítmények: https://jami.net/hu/extensions/</li>
|
||||
<li>JAMS (Jami Account Management Server – Jami fiókkezelő kiszolgáló): https://jami.biz/</li>
|
||||
<li>Jami-dokumentáció: https://docs.jami.net/hu/</li>
|
||||
</ul>
|
||||
<p>Kövess minket a továbbiakért:</p>
|
||||
<ul>
|
||||
<li>Mastodon: https://mstdn.io/@Jami</li>
|
||||
<li>X: https://x.com/jami_social</li>
|
||||
<li>YouTube: https://www.youtube.com/@jami9311</li>
|
||||
</ul>
|
||||
<p>Szívesen hallanánk felőled! Csatlakozzon a Jami közösséghez:</p>
|
||||
<ul>
|
||||
<li>Közreműködés: https://jami.net/hu/contribute/</li>
|
||||
<li>Fórum: https://forum.jami.net/</li>
|
||||
</ul>
|
||||
<p>Építsen a Jamival IoT-projektjére: használja újra a Jami univerzális kommunikációs technológiáját a hordozható könyvtárával a választott rendszerén.</p>
|
||||
<p>A Jami for Android TV-t Logitech kamerákkal ellátott NVIDIA SHIELD TV-n tesztelték.</p>
|
||||
<p>A Jami a GPL licenc 3-as vagy újabb verziója alatt jelent meg.</p>
|
||||
<p>Szerzői jog © Savoir-faire Linux Inc.</p>
|
||||
</description>
|
||||
<requires>
|
||||
<id>net.jami.daemon</id>
|
||||
</requires>
|
||||
<launchable type="desktop-id">net.jami.Jami.desktop</launchable>
|
||||
<icon type="stock">jami</icon>
|
||||
<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>
|
||||
<categories>
|
||||
<category>Chat</category>
|
||||
<category>FileTransfer</category>
|
||||
<category>InstantMessaging</category>
|
||||
<category>Network</category>
|
||||
<category>P2P</category>
|
||||
<category>Telephony</category>
|
||||
<category>VideoConference</category>
|
||||
</categories>
|
||||
<provides>
|
||||
<binary>jami</binary>
|
||||
<mediatype>x-scheme-handler/jami</mediatype>
|
||||
</provides>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<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>
|
||||
<image type="source" width="1310" height="650">https://dl.jami.net/media-resources/screenshots/jami_linux_audiovideo.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Screen sharing</caption>
|
||||
<caption xml:lang="hu">Képernyőmegosztás</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 codec="vp9" container="webm" 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 number of participants</caption>
|
||||
<caption xml:lang="hu">Konferenciahívások korlátlan számú résztvevővel</caption>
|
||||
<video codec="vp9" container="webm" 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 without servers</caption>
|
||||
<caption xml:lang="hu">Titkosított és biztonságos csevegési üzenetküldés, kiszolgálók nélkül</caption>
|
||||
<video codec="vp9" container="webm" width="600" height="400">https://dl.jami.net/media-resources/gifs_features/conversiongif_webm/chat_web.webm</video>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Transfer files of any size</caption>
|
||||
<caption xml:lang="hu">Bármilyen méretű fájl küldése</caption>
|
||||
<video codec="vp9" container="webm" width="600" height="400">https://dl.jami.net/media-resources/gifs_features/conversiongif_webm/files-share_web.webm</video>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<keywords>
|
||||
<keyword>Qt</keyword>
|
||||
<keyword>chat</keyword>
|
||||
<keyword>talk</keyword>
|
||||
<keyword>im</keyword>
|
||||
<keyword>message</keyword>
|
||||
<keyword>voip</keyword>
|
||||
</keywords>
|
||||
<content_rating type="oars-1.1">
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
<content_attribute id="social-audio">intense</content_attribute>
|
||||
</content_rating>
|
||||
</component>
|
||||
</components>
|
||||
146
extras/data/net.jami.Jami.metainfo.xml
Normal file
146
extras/data/net.jami.Jami.metainfo.xml
Normal file
@ -0,0 +1,146 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (C) 2015-2025 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>
|
||||
<p>Jami, a GNU package, is software for universal and distributed peer-to-peer communication that respects the freedom and privacy of its users.</p>
|
||||
<p xml:lang="hu">A Jami, 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>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>
|
||||
<p xml:lang="hu">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>Jami is a free/libre, end-to-end encrypted, and private communication platform.</p>
|
||||
<p xml:lang="hu">A Jami egy ingyenes, teljes körűen titkosított és privát kommunikációs 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 xml:lang="hu">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>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 xml:lang="hu">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>This gives the greatest privacy as the distributed nature of Jami means your calls are only between participants.</p>
|
||||
<p xml:lang="hu">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>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 xml:lang="hu">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>Jami can also function as a SIP client.</p>
|
||||
<p xml:lang="hu">A Jami SIP-ügyfélként is működhet.</p>
|
||||
<p>Jami has multiple extensions available: Audio Filter; Auto Answer; Green Screen; Watermark; and, Whisper Transcript.</p>
|
||||
<p xml:lang="hu">A Jami-nek több bővítménye is elérhető: hangszűrő; automatikus válasz; zöld képernyő; vízjel; és, suttogó átirat.</p>
|
||||
<p>Jami can be easily deployed in organizations with the “Jami Account Management Server” (JAMS), 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 xml:lang="hu">A Jami könnyen telepíthető a szervezetekben a JAMS (Jami Account Management Server – Jami fiókkezelő kiszolgáló), 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>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">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>Manage multiple SIP accounts, Jami accounts and JAMS accounts with the Jami client installed on one or multiple devices.</p>
|
||||
<p xml:lang="hu">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>Jami is free, unlimited, private, advertising free, compatible, fast, autonomous, and anonymous.</p>
|
||||
<p xml:lang="hu">A Jami ingyenes, korlátlan, privát, reklámmentes, kompatibilis, gyors, autonóm és névtelen.</p>
|
||||
<p>Learn more about:</p>
|
||||
<p xml:lang="hu">További tájékoztatás:</p>
|
||||
<ul>
|
||||
<li>Jami: https://jami.net/</li>
|
||||
<li xml:lang="hu">Jami: https://jami.net/hu/</li>
|
||||
<li>Jami extensions: https://jami.net/extensions/</li>
|
||||
<li xml:lang="hu">Jami-bővítmények: https://jami.net/hu/extensions/</li>
|
||||
<li>“Jami Account Management Server” (JAMS): https://jami.biz/</li>
|
||||
<li xml:lang="hu">JAMS (Jami Account Management Server – Jami fiókkezelő kiszolgáló): https://jami.biz/</li>
|
||||
<li>Jami documentation: https://docs.jami.net/</li>
|
||||
<li xml:lang="hu">Jami-dokumentáció: https://docs.jami.net/hu/</li>
|
||||
</ul>
|
||||
<p>Follow us for more:</p>
|
||||
<p xml:lang="hu">Kövess minket a továbbiakért:</p>
|
||||
<ul>
|
||||
<li>Mastodon: https://mstdn.io/@Jami</li>
|
||||
<li xml:lang="hu">Mastodon: https://mstdn.io/@Jami</li>
|
||||
<li>X: https://x.com/jami_social</li>
|
||||
<li xml:lang="hu">X: https://x.com/jami_social</li>
|
||||
<li>YouTube: https://www.youtube.com/@jami9311</li>
|
||||
<li xml:lang="hu">YouTube: https://www.youtube.com/@jami9311</li>
|
||||
</ul>
|
||||
<p>We’d love to hear from you! Join the Jami community:</p>
|
||||
<p xml:lang="hu">Szívesen hallanánk felőled! Csatlakozzon a Jami közösséghez:</p>
|
||||
<ul>
|
||||
<li>Contribute: https://jami.net/contribute/</li>
|
||||
<li xml:lang="hu">Közreműködés: https://jami.net/hu/contribute/</li>
|
||||
<li>Forum: https://forum.jami.net/</li>
|
||||
<li xml:lang="hu">Fórum: https://forum.jami.net/</li>
|
||||
</ul>
|
||||
<p>Build with Jami on your IoT project: re-use the universal communications technology of Jami with its portable library on your system of choice.</p>
|
||||
<p xml:lang="hu">Építsen a Jamival IoT-projektjére: használja újra a Jami univerzális kommunikációs technológiáját a hordozható könyvtárával a választott rendszerén.</p>
|
||||
<p>Jami for Android TV is tested on NVIDIA SHIELD TV with Logitech cameras.</p>
|
||||
<p xml:lang="hu">A Jami for Android TV-t Logitech kamerákkal ellátott NVIDIA SHIELD TV-n tesztelték.</p>
|
||||
<p>Jami is published under the GPL license, version 3 or higher.</p>
|
||||
<p xml:lang="hu">A Jami a GPL licenc 3-as vagy újabb verziója alatt jelent meg.</p>
|
||||
<p>Copyright © Savoir-faire Linux Inc.</p>
|
||||
<p xml:lang="hu">Szerzői jog © Savoir-faire Linux Inc.</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://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">
|
||||
<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">net.jami.Jami.desktop</launchable>
|
||||
|
||||
<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>FileTransfer</category>
|
||||
<category>InstantMessaging</category>
|
||||
<category>Network</category>
|
||||
<category>P2P</category>
|
||||
<category>Telephony</category>
|
||||
<category>VideoConference</category>
|
||||
</categories>
|
||||
|
||||
<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>
|
||||
|
||||
<requires><id>net.jami.daemon</id></requires>
|
||||
</component>
|
||||
12
extras/packaging/gnu-linux/Jenkinsfile
vendored
12
extras/packaging/gnu-linux/Jenkinsfile
vendored
@ -1,6 +1,4 @@
|
||||
// Copyright (C) 2021-2024 Savoir-faire Linux Inc.
|
||||
//
|
||||
// Author: Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com>
|
||||
// Copyright (C) 2021-2025 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
|
||||
@ -35,7 +33,9 @@
|
||||
def SUBMODULES = ['daemon',
|
||||
'3rdparty/SortFilterProxyModel',
|
||||
'3rdparty/md4c',
|
||||
'3rdparty/tidy-html5']
|
||||
'3rdparty/tidy-html5',
|
||||
'3rdparty/zxing-cpp',
|
||||
'3rdparty/hunspell']
|
||||
def TARGETS = [:]
|
||||
def REMOTE_HOST = env.SSH_HOST_DL_RING_CX
|
||||
def REMOTE_BASE_DIR = '/srv/repository/ring'
|
||||
@ -85,6 +85,10 @@ pipeline {
|
||||
|
||||
environment {
|
||||
TARBALLS = '/var/cache/jami' // set the cache directory
|
||||
BUILD_VERSION = sh(
|
||||
returnStdout: true,
|
||||
script: 'date +"%Y%m%d%H%M"'
|
||||
).trim()
|
||||
}
|
||||
|
||||
stages {
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
# -*- mode: makefile; -*-
|
||||
# Copyright (C) 2016-2024 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com>
|
||||
# Copyright (C) 2016-2025 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
|
||||
@ -129,7 +127,9 @@ $(RELEASE_TARBALL_FILENAME): tarballs.manifest
|
||||
. \
|
||||
./3rdparty/SortFilterProxyModel \
|
||||
./3rdparty/md4c \
|
||||
./3rdparty/tidy-html5; do \
|
||||
./3rdparty/tidy-html5 \
|
||||
./3rdparty/zxing-cpp \
|
||||
./3rdparty/hunspell; do \
|
||||
(cd "$$m" && git archive --prefix "$$m/" HEAD \
|
||||
| tar xf - -C $(TMPDIR)/$(RELEASE_DIRNAME)); \
|
||||
done
|
||||
@ -166,17 +166,16 @@ DISTRIBUTIONS := \
|
||||
debian_unstable \
|
||||
ubuntu_20.04 \
|
||||
ubuntu_22.04 \
|
||||
ubuntu_23.10 \
|
||||
ubuntu_24.04 \
|
||||
ubuntu_24.10 \
|
||||
fedora_37 \
|
||||
fedora_38 \
|
||||
ubuntu_25.04 \
|
||||
fedora_39 \
|
||||
fedora_40 \
|
||||
fedora_41 \
|
||||
fedora_42 \
|
||||
alma_9 \
|
||||
opensuse-leap_15.4 \
|
||||
opensuse-leap_15.5 \
|
||||
opensuse-leap_15.6 \
|
||||
snap
|
||||
|
||||
IS_SHELL_INTERACTIVE := $(shell [ -t 0 ] && echo yes)
|
||||
@ -195,6 +194,7 @@ $(1)-docker-image-name := jami-packaging-$(1)
|
||||
$(1)-docker-image-file := .docker-image-$$($(1)-docker-image-name)
|
||||
$(1)-docker-run-command := docker run \
|
||||
--rm --privileged --security-opt apparmor=docker-default \
|
||||
-e BUILD_VERSION=${BUILD_VERSION} \
|
||||
-e RELEASE_VERSION="$(RELEASE_VERSION)" \
|
||||
-e RELEASE_DIRNAME="$(RELEASE_DIRNAME)" \
|
||||
-e RELEASE_TARBALL_FILENAME="$(RELEASE_TARBALL_FILENAME)" \
|
||||
@ -253,10 +253,11 @@ GUIX_PACK_FORMATS = deb rpm
|
||||
define guix-pack-command
|
||||
guix pack -C xz -f $(1) -m $(CURDIR)/extras/packaging/gnu-linux/guix/guix-pack-manifest.scm -v3 \
|
||||
-S /usr/bin/jami=bin/jami \
|
||||
-S /usr/share/applications/jami.desktop=share/applications/jami.desktop \
|
||||
-S /usr/share/applications/net.jami.Jami.desktop=share/applications/net.jami.Jami.desktop \
|
||||
-S /usr/share/icons/hicolor/scalable/apps/jami.svg=share/icons/hicolor/scalable/apps/jami.svg \
|
||||
-S /usr/share/icons/hicolor/48x48/apps/jami.png=share/icons/hicolor/48x48/apps/jami.png \
|
||||
-S /usr/share/metainfo/jami.appdata.xml=share/metainfo/jami.appdata.xml \
|
||||
-S /usr/share/metainfo/net.jami.Jami.metainfo.xml=share/metainfo/net.jami.Jami.metainfo.xml \
|
||||
-S /usr/share/swcatalog/xml/jami.xml=share/swcatalog/xml/jami.xml \
|
||||
$(and $(findstring deb,$(1)), \
|
||||
--postinst-file=$(CURDIR)/extras/packaging/gnu-linux/guix/guix-pack-deb.postinst)
|
||||
endef
|
||||
|
||||
@ -70,9 +70,8 @@ RUN dnf install -y \
|
||||
libdrm \
|
||||
gperf \
|
||||
bison \
|
||||
clang \
|
||||
clang-devel \
|
||||
llvm-devel \
|
||||
clang16-devel \
|
||||
llvm16-devel \
|
||||
nodejs \
|
||||
flex \
|
||||
gstreamer1 gstreamer1-devel \
|
||||
@ -96,7 +95,6 @@ RUN dnf install -y \
|
||||
perl-English \
|
||||
libxshmfence-devel \
|
||||
ninja-build \
|
||||
clang \
|
||||
cmake \
|
||||
fmt-devel \
|
||||
python3-html5lib \
|
||||
|
||||
@ -12,7 +12,7 @@ RUN apt-get update --allow-releaseinfo-change && \
|
||||
nasm
|
||||
|
||||
# As of January 2024, the default compiler on Debian testing is GCC 13.2.0, which
|
||||
# can't build one of Qt 6.6.1's dependencies, see:
|
||||
# is unable to build one of Qt 6.6.1's dependencies, see:
|
||||
# https://github.com/qt/qtquick3d-assimp/commit/253f8bfa621a9fa6cd2c36291cdaa8c60c99322c
|
||||
# The linked commit above fixes the problem and is included in more recent versions of Qt.
|
||||
# For now, we use GCC 12 as a temporary workaround:
|
||||
|
||||
@ -11,14 +11,6 @@ RUN apt-get update && \
|
||||
libdbus-1-dev \
|
||||
wget
|
||||
|
||||
# As of January 2024, the default compiler on Debian unstable is GCC 13.2.0, which
|
||||
# can't build one of Qt 6.6.1's dependencies, see:
|
||||
# https://github.com/qt/qtquick3d-assimp/commit/253f8bfa621a9fa6cd2c36291cdaa8c60c99322c
|
||||
# The linked commit above fixes the problem and is included in more recent versions of Qt.
|
||||
# For now, we use GCC 12 as a temporary workaround:
|
||||
ADD extras/packaging/gnu-linux/scripts/install-gcc-debian.sh /opt/install-gcc-debian.sh
|
||||
RUN /opt/install-gcc-debian.sh 12
|
||||
|
||||
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
|
||||
|
||||
@ -1,106 +0,0 @@
|
||||
FROM fedora:37
|
||||
|
||||
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 \
|
||||
python2.7 \
|
||||
python3-html5lib \
|
||||
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 \
|
||||
pipewire-devel \
|
||||
cups-devel #Chromium for Qt
|
||||
|
||||
ADD extras/packaging/gnu-linux/scripts/build-package-rpm.sh /opt/build-package-rpm.sh
|
||||
|
||||
CMD ["/opt/build-package-rpm.sh"]
|
||||
@ -1,4 +1,4 @@
|
||||
FROM fedora:38
|
||||
FROM fedora:42
|
||||
|
||||
RUN dnf clean all
|
||||
RUN dnf update -y
|
||||
@ -6,12 +6,10 @@ 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 group install -y x-software-development
|
||||
|
||||
RUN dnf install -y \
|
||||
git \
|
||||
rpm-build \
|
||||
tar \
|
||||
make \
|
||||
autoconf \
|
||||
automake \
|
||||
@ -22,15 +20,11 @@ RUN dnf install -y \
|
||||
libcurl-devel \
|
||||
libtool \
|
||||
mesa-libgbm-devel \
|
||||
mesa-dri-drivers \
|
||||
dbus-devel \
|
||||
expat-devel \
|
||||
pcre-devel \
|
||||
yaml-cpp-devel \
|
||||
libXext-devel \
|
||||
libXfixes-devel \
|
||||
yasm \
|
||||
python2.7 \
|
||||
speex-devel \
|
||||
gsm-devel \
|
||||
chrpath \
|
||||
@ -38,16 +32,15 @@ RUN dnf install -y \
|
||||
astyle \
|
||||
uuid-c++-devel \
|
||||
gettext-devel \
|
||||
gcc-c++ \
|
||||
gcc14 \
|
||||
gcc14-c++ \
|
||||
which \
|
||||
alsa-lib-devel \
|
||||
systemd-devel \
|
||||
libuuid-devel \
|
||||
uuid-devel \
|
||||
gnutls-devel \
|
||||
nettle-devel \
|
||||
opus-devel \
|
||||
patch \
|
||||
jsoncpp-devel \
|
||||
libnatpmp-devel \
|
||||
webkitgtk4-devel \
|
||||
@ -65,28 +58,20 @@ RUN dnf install -y \
|
||||
qrencode-devel \
|
||||
libargon2-devel \
|
||||
libsndfile-devel \
|
||||
libdrm \
|
||||
gperf \
|
||||
bison \
|
||||
clang \
|
||||
clang-devel \
|
||||
llvm-devel \
|
||||
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 \
|
||||
@ -94,13 +79,19 @@ RUN dnf install -y \
|
||||
perl-English \
|
||||
libxshmfence-devel \
|
||||
ninja-build \
|
||||
clang \
|
||||
cmake \
|
||||
fmt-devel \
|
||||
python3-html5lib \
|
||||
python3.10 \
|
||||
cups-devel \
|
||||
pipewire-devel
|
||||
|
||||
# Use GCC 14 instead of GCC 15 (the default on Fedora 42)
|
||||
# because Qt 6.6.3 fails to build when using the latter.
|
||||
RUN rm /usr/bin/gcc /usr/bin/g++ /usr/bin/c++ && \
|
||||
ln -s /usr/bin/gcc-14 /usr/bin/gcc && \
|
||||
ln -s /usr/bin/g++-14 /usr/bin/g++ && \
|
||||
ln -s /usr/bin/g++-14 /usr/bin/c++
|
||||
|
||||
ADD extras/packaging/gnu-linux/scripts/build-package-rpm.sh /opt/build-package-rpm.sh
|
||||
|
||||
CMD ["/opt/build-package-rpm.sh"]
|
||||
@ -1,10 +1,9 @@
|
||||
FROM opensuse/leap:15.4
|
||||
FROM opensuse/leap:15.6
|
||||
|
||||
RUN zypper refresh
|
||||
RUN zypper --gpg-auto-import-keys refresh
|
||||
|
||||
RUN zypper --non-interactive install -y \
|
||||
dnf \
|
||||
dnf-command\(builddep\) \
|
||||
rpmdevtools \
|
||||
Mesa-dri-devel Mesa-dri \
|
||||
git \
|
||||
@ -29,11 +28,11 @@ RUN zypper --non-interactive install -y \
|
||||
speex-devel \
|
||||
libgsm-devel \
|
||||
chrpath \
|
||||
check \
|
||||
check-devel \
|
||||
astyle \
|
||||
gettext-devel \
|
||||
gettext-tools \
|
||||
which \
|
||||
alsa-lib-devel \
|
||||
alsa-devel \
|
||||
systemd-devel \
|
||||
libuuid-devel \
|
||||
uuid-devel \
|
||||
@ -44,9 +43,10 @@ RUN zypper --non-interactive install -y \
|
||||
libcryptopp-devel \
|
||||
libva-devel \
|
||||
libvdpau-devel \
|
||||
msgpack-devel \
|
||||
msgpack-c-devel \
|
||||
msgpack-cxx-devel \
|
||||
clutter-devel \
|
||||
openssl-devel \
|
||||
libopenssl-devel \
|
||||
clutter-gtk-devel \
|
||||
libnma-devel \
|
||||
libcryptopp-devel \
|
||||
@ -55,20 +55,20 @@ RUN zypper --non-interactive install -y \
|
||||
libgsm-devel \
|
||||
gtk3-devel \
|
||||
libappindicator-devel \
|
||||
sqlite-devel \
|
||||
ffmpeg-4-libavutil-devel \
|
||||
sqlite3-devel \
|
||||
gtk3-devel\
|
||||
qrencode-devel \
|
||||
python310 \
|
||||
python3-python-dateutil \
|
||||
python3-html5lib \
|
||||
libsndfile-devel \
|
||||
libdrm \
|
||||
libdrm-devel \
|
||||
gperf \
|
||||
bison \
|
||||
flex \
|
||||
ffmpeg ffmpeg-devel \
|
||||
nodejs18 \
|
||||
ffmpeg \
|
||||
ffmpeg-devel \
|
||||
nodejs20 \
|
||||
mozilla-nss-devel \
|
||||
python-xml \
|
||||
python3-six \
|
||||
@ -85,7 +85,7 @@ RUN zypper --non-interactive install -y \
|
||||
xorg-x11-devel \
|
||||
xz \
|
||||
xkeyboard-config \
|
||||
libnotify \
|
||||
libnotify-devel \
|
||||
argon2-devel \
|
||||
libxshmfence-devel \
|
||||
xproto-devel \
|
||||
@ -102,7 +102,7 @@ RUN zypper --non-interactive install -y \
|
||||
wget \
|
||||
pipewire-devel
|
||||
|
||||
# openSUSE Leap 15.4 comes with Python 3.6 by default,
|
||||
# openSUSE Leap 15.6 comes with Python 3.6 by default,
|
||||
# but we need at least 3.7 to compile Qt 6.6.1
|
||||
RUN rm /usr/bin/python3 && ln -s /usr/bin/python3.10 /usr/bin/python3
|
||||
|
||||
@ -113,10 +113,4 @@ ADD extras/packaging/gnu-linux/scripts/build-package-rpm.sh /opt/build-package-r
|
||||
|
||||
ENV CC=gcc
|
||||
ENV CXX=g++
|
||||
|
||||
# Setting this variable so that FFmpeg gets built without pipewiregrab
|
||||
# (see daemon/contrib/bootstrap and daemon/contrib/src/ffmpeg/rules.mak)
|
||||
# We rely on PipeWire for screen sharing on Wayland, but the version available on openSUSE Leap 15.4 is too old.
|
||||
ENV DISABLE_PIPEWIRE=true
|
||||
|
||||
CMD ["/opt/build-package-rpm.sh"]
|
||||
@ -1,10 +1,12 @@
|
||||
ARG RISK=edge
|
||||
# This file is based on the examples at the following links:
|
||||
# https://snapcraft.io/docs/build-on-docker
|
||||
# https://github.com/canonical/snapcraft/issues/5079#issuecomment-2414199613
|
||||
|
||||
ARG UBUNTU=focal
|
||||
|
||||
FROM ubuntu:$UBUNTU as builder
|
||||
ARG RISK
|
||||
FROM ubuntu:$UBUNTU AS builder
|
||||
ARG UBUNTU
|
||||
RUN echo "Building snapcraft:$RISK in ubuntu:$UBUNTU"
|
||||
RUN echo "Building snapcraft in ubuntu:$UBUNTU"
|
||||
|
||||
# Grab dependencies
|
||||
RUN apt-get update
|
||||
@ -14,57 +16,41 @@ RUN apt-get install --yes \
|
||||
jq \
|
||||
squashfs-tools
|
||||
|
||||
# Grab the core snap (for backwards compatibility) from the stable channel and
|
||||
# unpack it in the proper place.
|
||||
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' 'https://api.snapcraft.io/api/v1/snaps/details/core' | jq '.download_url' -r) --output core.snap
|
||||
RUN mkdir -p /snap/core
|
||||
RUN unsquashfs -d /snap/core/current core.snap
|
||||
|
||||
# Grab the core22 snap (which snapcraft uses as a base) from the stable channel
|
||||
# and unpack it in the proper place.
|
||||
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' 'https://api.snapcraft.io/api/v1/snaps/details/core22?channel='$RISK | jq '.download_url' -r) --output core22.snap
|
||||
# Download and unpack the core22 snap
|
||||
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' 'https://api.snapcraft.io/api/v1/snaps/details/core22' | jq '.download_url' -r) --output core22.snap
|
||||
RUN mkdir -p /snap/core22
|
||||
RUN unsquashfs -d /snap/core22/current core22.snap
|
||||
|
||||
# Grab the core20 snap (which snapcraft uses as a base) from the stable channel
|
||||
# and unpack it in the proper place.
|
||||
# Download and unpack the core20 snap
|
||||
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' 'https://api.snapcraft.io/api/v1/snaps/details/core20' | jq '.download_url' -r) --output core20.snap
|
||||
RUN mkdir -p /snap/core20
|
||||
RUN unsquashfs -d /snap/core20/current core20.snap
|
||||
|
||||
# Grab the core20 snap (which snapcraft uses as a base) from the stable channel
|
||||
# and unpack it in the proper place.
|
||||
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' 'https://api.snapcraft.io/api/v1/snaps/details/lxd' | jq '.download_url' -r) --output lxd.snap
|
||||
RUN mkdir -p /snap/lxd
|
||||
RUN unsquashfs -d /snap/lxd/current lxd.snap
|
||||
# Download and unpack the core24 snap
|
||||
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' 'https://api.snapcraft.io/api/v1/snaps/details/core24' | jq '.download_url' -r) --output core24.snap
|
||||
RUN mkdir -p /snap/core24
|
||||
RUN unsquashfs -d /snap/core24/current core24.snap
|
||||
|
||||
# Grab the snapcraft snap from the $RISK channel and unpack it in the proper
|
||||
# place.
|
||||
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' 'https://api.snapcraft.io/api/v1/snaps/details/snapcraft?channel='$RISK | jq '.download_url' -r) --output snapcraft.snap
|
||||
# Download and unpack snapcraft
|
||||
RUN curl -L $(curl -H 'X-Ubuntu-Series: 16' 'https://api.snapcraft.io/api/v1/snaps/details/snapcraft' | jq '.download_url' -r) --output snapcraft.snap
|
||||
RUN mkdir -p /snap/snapcraft
|
||||
RUN unsquashfs -d /snap/snapcraft/current snapcraft.snap
|
||||
|
||||
# Fix Python3 installation: Make sure we use the interpreter from
|
||||
# the snapcraft snap:
|
||||
RUN unlink /snap/snapcraft/current/usr/bin/python3
|
||||
RUN ln -s /snap/snapcraft/current/usr/bin/python3.* /snap/snapcraft/current/usr/bin/python3
|
||||
RUN echo /snap/snapcraft/current/lib/python3.*/site-packages >> /snap/snapcraft/current/usr/lib/python3/dist-packages/site-packages.pth
|
||||
|
||||
# Create a snapcraft runner (TODO: move version detection to the core of
|
||||
# snapcraft).
|
||||
# Create a snapcraft runner
|
||||
RUN mkdir -p /snap/bin
|
||||
RUN echo "#!/bin/sh" > /snap/bin/snapcraft
|
||||
RUN snap_version="$(awk '/^version:/{print $2}' /snap/snapcraft/current/meta/snap.yaml | tr -d \')" && echo "export SNAP_VERSION=\"$snap_version\"" >> /snap/bin/snapcraft
|
||||
RUN echo 'exec "$SNAP/usr/bin/python3" "$SNAP/bin/snapcraft" "$@"' >> /snap/bin/snapcraft
|
||||
RUN echo 'exec "/snap/snapcraft/current/bin/python3" -m snapcraft "$@"' >> /snap/bin/snapcraft
|
||||
RUN chmod +x /snap/bin/snapcraft
|
||||
|
||||
|
||||
# Multi-stage build, only need the snaps from the builder. Copy them one at a
|
||||
# time so they can be cached.
|
||||
FROM ubuntu:$UBUNTU
|
||||
COPY --from=builder /snap/core /snap/core
|
||||
COPY --from=builder /snap/core22 /snap/core22
|
||||
|
||||
COPY --from=builder /snap/core20 /snap/core20
|
||||
COPY --from=builder /snap/lxd /snap/lxd
|
||||
COPY --from=builder /snap/core22 /snap/core22
|
||||
COPY --from=builder /snap/core24 /snap/core24
|
||||
COPY --from=builder /snap/snapcraft /snap/snapcraft
|
||||
COPY --from=builder /snap/bin/snapcraft /snap/bin/snapcraft
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM ubuntu:23.10
|
||||
FROM ubuntu:25.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
@ -10,14 +10,6 @@ RUN apt-get update && \
|
||||
python-is-python3 \
|
||||
wget
|
||||
|
||||
# The default compiler on Ubuntu 23.10, GCC 13.2.0, can't build one of Qt 6.6.1's
|
||||
# dependencies, see:
|
||||
# https://github.com/qt/qtquick3d-assimp/commit/253f8bfa621a9fa6cd2c36291cdaa8c60c99322c
|
||||
# The linked commit above fixes the problem and is included in more recent versions of Qt.
|
||||
# For now, we use GCC 12 as a temporary workaround:
|
||||
ADD extras/packaging/gnu-linux/scripts/install-gcc-debian.sh /opt/install-gcc-debian.sh
|
||||
RUN /opt/install-gcc-debian.sh 12
|
||||
|
||||
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
|
||||
@ -26,5 +18,12 @@ RUN /opt/prebuild-package-debian.sh qt-deps
|
||||
COPY extras/packaging/gnu-linux/rules/debian/control /tmp/builddeps/debian/control
|
||||
RUN /opt/prebuild-package-debian.sh jami-deps
|
||||
|
||||
# Remove the libre2-dev package in order to force Qt to build using the bundled
|
||||
# version of the RE2 library. This is necessary because the system version of the
|
||||
# library on Ubuntu 25.04 (libre2-11) is not compatible with the one used in
|
||||
# Qt 6.6.1 due to an API change:
|
||||
# https://codereview.qt-project.org/c/qt/qtwebengine/+/516094
|
||||
RUN apt-get remove -y libre2-dev libre2-11
|
||||
|
||||
ADD extras/packaging/gnu-linux/scripts/build-package-debian.sh /opt/build-package-debian.sh
|
||||
CMD ["/opt/build-package-debian.sh"]
|
||||
@ -1,7 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2021-2024 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com>
|
||||
# Copyright (C) 2021-2025 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
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
;;; Copyright (C) 2021-2024 Savoir-faire Linux Inc.
|
||||
;;;
|
||||
;;; Author: Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com>
|
||||
;;; Copyright (C) 2021-2025 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
|
||||
|
||||
@ -261,7 +261,7 @@ Build-Depends: debhelper (>= 9),
|
||||
gperf,
|
||||
khronos-api,
|
||||
# libasound2-dev [linux-any],
|
||||
libavcodec-dev (>= 7:3.4.8~),
|
||||
libavcodec-dev (>= 7:3.4.8~) | libavcodec-extra-dev (>= 7:3.4.8~),
|
||||
libavformat-dev (>= 7:3.4.8~),
|
||||
libavutil-dev (>= 7:3.4.8~),
|
||||
libcap-dev [linux-any],
|
||||
|
||||
@ -30,7 +30,7 @@ Build-Depends: debhelper (>= 9),
|
||||
libspeex-dev,
|
||||
libspeexdsp-dev,
|
||||
uuid-dev,
|
||||
libavcodec-dev,
|
||||
libavcodec-dev | libavcodec-extra-dev,
|
||||
libavutil-dev,
|
||||
libavformat-dev,
|
||||
libswscale-dev,
|
||||
|
||||
@ -3,7 +3,7 @@ Upstream-Name: jami
|
||||
Upstream-Contact: Amin Bandali <bandali@gnu.org>
|
||||
Source: https://dl.jami.net/release/tarballs/
|
||||
Files: *
|
||||
Copyright: 2004-2024 Savoir-faire Linux Inc.
|
||||
Copyright: 2004-2025 Savoir-faire Linux Inc.
|
||||
License: GPL-3+
|
||||
Comment: Upstream embeds everything that is needed to build Jami inside the release tarball.
|
||||
Everything that is already in Debian has been removed.
|
||||
|
||||
@ -99,12 +99,12 @@ if [ -f /etc/os-release ]; then
|
||||
ENDTAG="ubuntu_20.04"
|
||||
elif [ "${UBUNTU_CODENAME}" = "jammy" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_22.04" ]; then
|
||||
ENDTAG="ubuntu_22.04"
|
||||
elif [ "${UBUNTU_CODENAME}" = "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 [ "${UBUNTU_CODENAME}" = "plucky" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_25.04" ]; then
|
||||
ENDTAG="ubuntu_25.04"
|
||||
elif [ "${ID}" = "debian" ] && \
|
||||
[ "$(command -v lsb_release)" ] && \
|
||||
[ "$(lsb_release -rs)" = "testing" ]; then
|
||||
|
||||
@ -74,7 +74,7 @@ override_dh_auto_build:
|
||||
--disable-gsm \
|
||||
--disable-speexdsp \
|
||||
--disable-natpmp \
|
||||
--enable-gnutls $(BUNDLED_PKGS) && \
|
||||
$(BUNDLED_PKGS) && \
|
||||
make list && \
|
||||
make -j$(NO_CPUS) V=1
|
||||
cd daemon && \
|
||||
@ -91,6 +91,7 @@ override_dh_auto_build:
|
||||
mkdir build && \
|
||||
cd build && \
|
||||
cmake \
|
||||
-DBUILD_VERSION=$(BUILD_VERSION) \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DLIBJAMI_BUILD_DIR=$(CURDIR)/daemon/src \
|
||||
-DENABLE_LIBWRAP=true \
|
||||
|
||||
@ -2,6 +2,16 @@
|
||||
%define version RELEASE_VERSION
|
||||
%define release 0
|
||||
|
||||
# The AppStream 1.0 spec says that the catalog file must be put in /usr/share/swcatalog/xml
|
||||
# (see https://www.freedesktop.org/software/appstream/docs/chap-CatalogData.html).
|
||||
#
|
||||
# However, openSUSE Leap still uses the legacy path /usr/share/app-info/xmls as of version 15.5.
|
||||
%if 0%{?sle_version} && 0%{?sle_version} <= 150500
|
||||
%define appstream_catalog_dir /share/app-info/xmls
|
||||
%else
|
||||
%define appstream_catalog_dir /share/swcatalog/xml
|
||||
%endif
|
||||
|
||||
# Exclude vendored Qt6 from dependency generator
|
||||
%define __requires_exclude ^libQt6.*$
|
||||
|
||||
@ -69,6 +79,7 @@ cd %{_builddir}/jami-%{version} && \
|
||||
-DLIBJAMI_BUILD_DIR=%{_builddir}/jami-%{version}/daemon/src \
|
||||
-DCMAKE_INSTALL_PREFIX=%{_prefix} \
|
||||
-DCMAKE_INSTALL_LIBDIR=%{_libdir} \
|
||||
-DAPPSTREAM_CATALOG_DIR=%{appstream_catalog_dir} \
|
||||
-DWITH_DAEMON_SUBMODULE=true \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
..
|
||||
@ -80,11 +91,12 @@ DESTDIR=%{buildroot} make -C %{_builddir}/jami-%{version}/build install V=2
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_bindir}/jami
|
||||
%{_datadir}/applications/jami.desktop
|
||||
%{_datadir}/jami/jami.desktop
|
||||
%{_datadir}/applications/net.jami.Jami.desktop
|
||||
%{_datadir}/jami/net.jami.Jami.desktop
|
||||
%{_datadir}/icons/hicolor/scalable/apps/jami.svg
|
||||
%{_datadir}/icons/hicolor/48x48/apps/jami.png
|
||||
%{_datadir}/pixmaps/jami.xpm
|
||||
%{_datadir}/metainfo/jami.appdata.xml
|
||||
%{_datadir}/metainfo/net.jami.Jami.metainfo.xml
|
||||
%{_prefix}%{appstream_catalog_dir}/jami.xml
|
||||
%{_datadir}/jami/translations/*
|
||||
%doc %{_mandir}/man1/jami*
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
# Copyright (C) 2019-2024 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
# Author: Amin Bandali <amin.bandali@savoirfairelinux.com>
|
||||
# Copyright (C) 2019-2025 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
|
||||
@ -51,37 +48,53 @@ icon: common/icons/jami.svg
|
||||
license: GPL-3.0+
|
||||
summary: 'Privacy-oriented voice, video, chat, and conference platform and SIP phone'
|
||||
description: |
|
||||
Jami is free software for universal communication that respects the
|
||||
freedom and privacy of its users.
|
||||
Jami, a GNU package, is software for universal and distributed peer-to-peer communication that respects the freedom and privacy of its users.
|
||||
|
||||
Jami is an end-to-end encrypted secure and distributed voice, video,
|
||||
and chat communication platform. Jami requires no central server
|
||||
for these communications and leaves the power of privacy and freedom
|
||||
in the hands of users.
|
||||
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.
|
||||
|
||||
Jami provides the following key features to its users:
|
||||
Jami is a free/libre, end-to-end encrypted, and private communication platform.
|
||||
|
||||
* Synchronized and enriched one-to-one conversations
|
||||
* Group conversations (Beta)
|
||||
* Audio/video calls and conferences
|
||||
* Screen sharing in video calls and conferences
|
||||
* Unlimited peer-to-peer file sharing
|
||||
* Recording and sending audio/video messages
|
||||
* Jami plugins SDK for additional functionality (green screen,
|
||||
watermark, audio filters, and more)
|
||||
* Use Jami as your SIP phone with a variety of media codecs
|
||||
and VoIP providers
|
||||
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.
|
||||
|
||||
Client applications for GNU/Linux, Windows, macOS, iOS, Android,
|
||||
and Android TV are available, making Jami an interoperable and
|
||||
cross-platform communication framework.
|
||||
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.
|
||||
|
||||
Seamlessly deploy Jami in your organization using
|
||||
Jami Account Management Server (JAMS). With JAMS, you can enable
|
||||
your users to connect using their LDAP/ActiveDirectory credentials
|
||||
or create local accounts, enabling you to manage your own
|
||||
Jami community while taking advantage of Jami's distributed network
|
||||
architecture. For more information, please visit https://jami.biz.
|
||||
This gives the greatest privacy as the distributed nature of Jami means your calls are only between participants.
|
||||
|
||||
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.
|
||||
|
||||
Jami can also function as a SIP client.
|
||||
|
||||
Jami has multiple extensions available: Audio Filter; Auto Answer; Green Screen; Watermark; and, Whisper Transcript.
|
||||
|
||||
Jami can be easily deployed in organizations with the “Jami Account Management Server” (JAMS), 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.
|
||||
|
||||
Jami is available for GNU/Linux, Windows, macOS, iOS, Android, and Android TV, making Jami an interoperable and cross-platform communication framework.
|
||||
|
||||
Manage multiple SIP accounts, Jami accounts and JAMS accounts with the Jami client installed on one or multiple devices.
|
||||
|
||||
Jami is free, unlimited, private, advertising free, compatible, fast, autonomous, and anonymous.
|
||||
|
||||
Learn more about:
|
||||
Jami: https://jami.net/
|
||||
Jami extensions: https://jami.net/extensions/
|
||||
“Jami Account Management Server” (JAMS): https://jami.biz/
|
||||
Jami documentation: https://docs.jami.net/
|
||||
|
||||
Follow us for more:
|
||||
Mastodon: https://mstdn.io/@Jami
|
||||
X: https://x.com/jami_social
|
||||
YouTube: https://www.youtube.com/@jami9311
|
||||
|
||||
We’d love to hear from you! Join the Jami community:
|
||||
Contribute: https://jami.net/contribute/
|
||||
Forum: https://forum.jami.net/
|
||||
|
||||
Build with Jami on your IoT project: re-use the universal communications technology of Jami with its portable library on your system of choice.
|
||||
|
||||
Jami for Android TV is tested on NVIDIA SHIELD TV with Logitech cameras.
|
||||
|
||||
Jami is published under the GPL license, version 3 or higher.
|
||||
Copyright © Savoir-faire Linux Inc.
|
||||
|
||||
confinement: strict
|
||||
grade: stable
|
||||
@ -135,9 +148,9 @@ apps:
|
||||
- bin/desktop-launch
|
||||
- snap/command-chain/alsa-launch
|
||||
- bin/jami-wrapper
|
||||
autostart: jami.desktop
|
||||
autostart: net.jami.Jami.desktop
|
||||
common-id: net.jami.Jami
|
||||
desktop: usr/share/applications/jami.desktop
|
||||
desktop: usr/share/applications/net.jami.Jami.desktop
|
||||
environment:
|
||||
PIPEWIRE_CONFIG_NAME: "$SNAP/usr/share/pipewire/pipewire.conf"
|
||||
PIPEWIRE_MODULE_DIR: "$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pipewire-0.3"
|
||||
@ -242,7 +255,7 @@ parts:
|
||||
after: [alsa-mixin]
|
||||
source: .
|
||||
plugin: nil
|
||||
parse-info: [usr/share/metainfo/jami.appdata.xml]
|
||||
parse-info: [usr/share/metainfo/net.jami.Jami.metainfo.xml]
|
||||
stage:
|
||||
- -usr/lib/x86_64-linux-gnu/liblber-2.4.so*
|
||||
- -usr/lib/x86_64-linux-gnu/libldap_r-2.4.so*
|
||||
@ -257,7 +270,7 @@ parts:
|
||||
ls
|
||||
snapcraftctl pull
|
||||
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
|
||||
sed -i -E 's|^Icon=.*|Icon=${SNAP}/usr/share/icons/hicolor/scalable/apps/jami.svg|' extras/data/net.jami.Jami.desktop
|
||||
override-build: |
|
||||
$SNAPCRAFT_PART_BUILD/extras/packaging/gnu-linux/scripts/install-pipewire-from-source.sh
|
||||
|
||||
@ -325,6 +338,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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2016-2024 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2016-2025 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com>
|
||||
# Author: Amin Bandali <amin.bandali@savoirfairelinux.com>
|
||||
@ -47,7 +47,11 @@ 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
|
||||
# NOTE: We use this on Ubuntu 25.04 and Debian 13 ("trixie") too
|
||||
# because otherwise we get a ModuleNotFoundError when building
|
||||
# Qt 6.6.1 (specifically the chromium submodule in QtWebEngine)
|
||||
# due to the version of python used (3.13) being too recent.
|
||||
if cat /etc/os-release | grep -Eq "24.04|25.04|trixie"; 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"
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2016-2024 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com>
|
||||
# Author: Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com>
|
||||
# Copyright (C) 2016-2025 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
|
||||
@ -104,18 +101,14 @@ if [ ! -f "${RPM_PATH}" ]; then
|
||||
# Cache the built Qt RPM package.
|
||||
if [[ "${DISTRIBUTION:0:4}" == "rhel" ]]; then
|
||||
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.el8.x86_64.rpm "${RPM_PATH}"
|
||||
elif [[ "${DISTRIBUTION}" == "fedora_36" ]]; then
|
||||
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc36.x86_64.rpm "${RPM_PATH}"
|
||||
elif [[ "${DISTRIBUTION}" == "fedora_37" ]]; then
|
||||
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc37.x86_64.rpm "${RPM_PATH}"
|
||||
elif [[ "${DISTRIBUTION}" == "fedora_38" ]]; 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}" == "fedora_42" ]]; then
|
||||
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc42.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
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Amin Bandali <amin.bandali@savoirfairelinux.com>
|
||||
# Copyright (C) 2020-2025 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
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2016-2024 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com>
|
||||
# Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
|
||||
# Copyright (C) 2016-2025 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
|
||||
@ -83,9 +80,6 @@ EOF
|
||||
find ./extras/packaging/gnu-linux/packages -type f -name '*.ddeb' -print0 | xargs -0 -I{} mv {} {}.deb
|
||||
|
||||
for package in ./extras/packaging/gnu-linux/packages/${DISTRIBUTION}*/*.deb; do
|
||||
echo "## signing: ${package} ##"
|
||||
dpkg-sig -k ${KEYID} --sign builder ${package}
|
||||
|
||||
echo "## including ${package} ##"
|
||||
package_name=$(dpkg -I ${package} | grep -m 1 Package: | awk '{print $2}')
|
||||
package_arch=$(dpkg -I ${package} | grep -m 1 Architecture: | awk '{print $2}')
|
||||
|
||||
@ -8,9 +8,6 @@ set -e
|
||||
OLD_WD=$(pwd)
|
||||
cd /tmp
|
||||
|
||||
# Install PipeWire's build dependencies
|
||||
apt-get install --yes gcc git libasound2-dev libdbus-1-dev libglib2.0-dev ninja-build pkg-config
|
||||
|
||||
# Get a version of Meson that's recent enough to build PipeWire 1.0.5 (the one available via apt is too old)
|
||||
wget -q https://github.com/mesonbuild/meson/releases/download/0.61.1/meson-0.61.1.tar.gz
|
||||
echo "feb2cefb325b437dbf36146df7c6b87688ddff0b0205caa31dc64055c6da410c meson-0.61.1.tar.gz" | sha256sum --check
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2021-2024 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Amin Bandali <amin.bandali@savoirfairelinux.com>
|
||||
# Copyright (C) 2021-2025 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
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2024 Savoir-faire Linux Inc.
|
||||
#
|
||||
# Author: Amin Bandali <amin.bandali@savoirfairelinux.com>
|
||||
# Copyright (C) 2024-2025 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
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
From 161d28abb6784115ad71fcb6977e112e9d5756d4 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
Date: Tue, 23 Jan 2024 15:38:34 -0500
|
||||
Subject: [PATCH] fix-fedora-fc-build
|
||||
|
||||
---
|
||||
CMakeLists.txt | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 0fb89c8..3a6ad6d 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -65,7 +65,7 @@ if(NOT TARGET qmsetup::library)
|
||||
)
|
||||
|
||||
# Find package again
|
||||
- find_package(qmsetup REQUIRED PATHS ${_package_path})
|
||||
+ find_package(qmsetup REQUIRED PATHS ${_package_path} ${qmsetup_cmake_path})
|
||||
|
||||
# Update import path
|
||||
set(qmsetup_DIR ${_package_path} CACHE PATH "" FORCE)
|
||||
--
|
||||
2.34.1
|
||||
|
||||
32
extras/patches/0001-fix-qm_install_package-function.patch
Normal file
32
extras/patches/0001-fix-qm_install_package-function.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 56830725e641705e0113a068ee58df7029202439 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, 2 Apr 2025 20:54:02 -0400
|
||||
Subject: [PATCH] fix qm_install_package function
|
||||
|
||||
---
|
||||
cmake/modules/private/InstallPackage.cmake | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/qmsetup/cmake/modules/private/InstallPackage.cmake b/qmsetup/cmake/modules/private/InstallPackage.cmake
|
||||
index 70174bc..f067de5 100644
|
||||
--- a/qmsetup/cmake/modules/private/InstallPackage.cmake
|
||||
+++ b/qmsetup/cmake/modules/private/InstallPackage.cmake
|
||||
@@ -101,6 +101,7 @@ function(qm_install_package _name)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -S ${_src_dir} -B ${_build_dir}
|
||||
${_extra_args} ${_build_type}
|
||||
+ "-DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}"
|
||||
"-DCMAKE_INSTALL_PREFIX=${_install_dir}" ${FUNC_CONFIGURE_ARGS}
|
||||
OUTPUT_FILE ${_log_file}
|
||||
ERROR_FILE ${_log_file}
|
||||
@@ -150,4 +151,4 @@ function(qm_install_package _name)
|
||||
if(FUNC_RESULT_PATH)
|
||||
set(${FUNC_RESULT_PATH} ${_install_cmake_dir} PARENT_SCOPE)
|
||||
endif()
|
||||
-endfunction()
|
||||
\ No newline at end of file
|
||||
+endfunction()
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -9,14 +9,15 @@ and package the project for Windows.
|
||||
usage: build.py [-q] [-h] [-a ARCH] [-c CONFIG] [-t] [-i] [-v] {pack} ...
|
||||
|
||||
optional arguments:
|
||||
-q, --qt PATH Sets the Qt installation path
|
||||
-a ARCH, --arch ARCH Sets the build architecture
|
||||
-q, --qt PATH Sets the Qt installation path
|
||||
-a ARCH, --arch ARCH Sets the build architecture
|
||||
-c CONFIG, --config CONFIG
|
||||
Sets the build configuration type
|
||||
-t, --tests Build and run tests
|
||||
-i, --init Initialize submodules
|
||||
-v, --version Show the version number and exit
|
||||
-s, --skip-build Only do packaging or run tests, skip building
|
||||
Sets the build configuration type
|
||||
-t, --tests Build and run tests
|
||||
-i, --init Initialize submodules
|
||||
-v, --version Show the version number and exit
|
||||
-s, --skip-build Only do packaging or run tests, skip building
|
||||
--enable-crash-reports Enable crash reports
|
||||
|
||||
positional arguments:
|
||||
{pack}
|
||||
@ -210,6 +211,8 @@ def init_submodules():
|
||||
"3rdparty/SortFilterProxyModel",
|
||||
"3rdparty/md4c",
|
||||
"3rdparty/tidy-html5",
|
||||
"3rdparty/zxing-cpp",
|
||||
"3rdparty/hunspell",
|
||||
]
|
||||
if execute_cmd(["git", "submodule", "update", "--init" ] + submodules,
|
||||
False):
|
||||
@ -260,7 +263,7 @@ def cmake_build(config_str, env_vars, cmake_build_dir):
|
||||
return True
|
||||
|
||||
|
||||
def build(config_str, qt_dir, tests):
|
||||
def build(config_str, qt_dir, tests, build_version, enable_crash_reports, crash_report_url=None):
|
||||
"""Use cmake to build the project."""
|
||||
print("Building with Qt at " + qt_dir)
|
||||
|
||||
@ -284,6 +287,16 @@ def build(config_str, qt_dir, tests):
|
||||
"-DBETA=" + str((0, 1)[config_str == "Beta"]),
|
||||
]
|
||||
|
||||
if enable_crash_reports:
|
||||
cmake_options.append("-DENABLE_CRASHREPORTS=ON")
|
||||
if crash_report_url:
|
||||
cmake_options.append(f"-DCRASH_REPORT_URL={crash_report_url}")
|
||||
else:
|
||||
cmake_options.append("-DENABLE_CRASHREPORTS=OFF")
|
||||
|
||||
if build_version:
|
||||
cmake_options.append("-DBUILD_VERSION=" + build_version)
|
||||
|
||||
# Make sure the build directory exists.
|
||||
if not os.path.exists(build_dir):
|
||||
os.makedirs(build_dir)
|
||||
@ -297,11 +310,11 @@ def build(config_str, qt_dir, tests):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def deploy_runtimes(config_str, qt_dir):
|
||||
def deploy_runtimes(qt_dir):
|
||||
"""Deploy the dependencies to the runtime directory."""
|
||||
print("Deploying runtime dependencies")
|
||||
|
||||
runtime_dir = os.path.join(repo_root_dir, "x64", config_str)
|
||||
runtime_dir = os.path.join(repo_root_dir, "x64", "Release")
|
||||
stamp_file = os.path.join(runtime_dir, ".deploy.stamp")
|
||||
if os.path.exists(stamp_file):
|
||||
return
|
||||
@ -314,8 +327,8 @@ def deploy_runtimes(config_str, qt_dir):
|
||||
shutil.copy(os.path.join(rel_path, src), runtime_dir)
|
||||
|
||||
print("Copying libjami dependencies")
|
||||
install_file("contrib/build/openssl/libcrypto-1_1-x64.dll", daemon_dir)
|
||||
install_file("contrib/build/openssl/libssl-1_1-x64.dll", daemon_dir)
|
||||
install_file("contrib/build/openssl/libcrypto-3-x64.dll", daemon_dir)
|
||||
install_file("contrib/build/openssl/libssl-3-x64.dll", daemon_dir)
|
||||
# Ringtone files (ul,ogg,wav,opus files in the daemon ringtone dir).
|
||||
|
||||
print("Copying ringtones")
|
||||
@ -341,8 +354,8 @@ def deploy_runtimes(config_str, qt_dir):
|
||||
install_file("resources/images/jami.ico", repo_root_dir)
|
||||
|
||||
# windeployqt
|
||||
print("Running windeployqt (this may take a while)...")
|
||||
win_deploy_qt = os.path.join(qt_dir, "bin", "windeployqt.exe")
|
||||
print(f"Running windeployqt ({win_deploy_qt}) (this may take a while)...")
|
||||
qml_src_dir = os.path.join(repo_root_dir, "src", "app")
|
||||
installation_dir = get_vs_prop("installationPath")
|
||||
if not installation_dir:
|
||||
@ -460,6 +473,8 @@ def parse_args():
|
||||
help='Sets the Qt root path')
|
||||
parser.add_argument(
|
||||
"-a", "--arch", default="x64", help="Sets the build architecture")
|
||||
parser.add_argument(
|
||||
"--build-version", help="Sets the build version string used for defining app build version")
|
||||
parser.add_argument(
|
||||
"-t", "--tests", action="store_true", help="Build and run tests")
|
||||
parser.add_argument(
|
||||
@ -471,17 +486,24 @@ def parse_args():
|
||||
parser.add_argument(
|
||||
"-i", "--init", action="store_true", help="Initialize submodules")
|
||||
parser.add_argument(
|
||||
'-sd',
|
||||
'--skip-deploy',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Force skip deployment of runtime files needed for packaging')
|
||||
parser.add_argument(
|
||||
"-sb",
|
||||
"--skip-build",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Only do packaging or run tests, skip build step")
|
||||
parser.add_argument(
|
||||
'--enable-crash-reports',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Enable crash reporting')
|
||||
parser.add_argument(
|
||||
'--crash-report-url',
|
||||
help='Override the crash report submission URL',
|
||||
default=None)
|
||||
|
||||
pack_arg_parser = subparsers.add_parser("pack")
|
||||
pack_group = pack_arg_parser.add_mutually_exclusive_group(required=True)
|
||||
@ -534,9 +556,12 @@ def main():
|
||||
|
||||
def do_build(do_tests):
|
||||
if not parsed_args.skip_build:
|
||||
build(config_str, parsed_args.qt, do_tests)
|
||||
build(config_str, parsed_args.qt, do_tests,
|
||||
parsed_args.build_version,
|
||||
parsed_args.enable_crash_reports,
|
||||
parsed_args.crash_report_url)
|
||||
if not parsed_args.skip_deploy:
|
||||
deploy_runtimes(config_str, parsed_args.qt)
|
||||
deploy_runtimes(parsed_args.qt)
|
||||
|
||||
if parsed_args.subcommand == "pack":
|
||||
do_build(False)
|
||||
|
||||
@ -52,7 +52,7 @@ for ARCH in "${ARCHS[@]}"; do
|
||||
# force to build every contrib
|
||||
for dir in "$DAEMON"/contrib/src/*/; do
|
||||
PKG=$(basename -- "$dir")
|
||||
if [ "$PKG" != "sdbus-cpp" ] && [ "$PKG" != "natpmp" ] &&
|
||||
if [ "$PKG" != "sdbus-cpp" ] && [ "$PKG" != "freetype" ] &&
|
||||
[ "$PKG" != "portaudio" ] && [ "$PKG" != "pthreads" ] &&
|
||||
[ "$PKG" != "lttng-ust" ] && [ "$PKG" != "openssl" ] &&
|
||||
[ "$PKG" != "media-sdk" ] && [ "$PKG" != "jack" ] &&
|
||||
|
||||
@ -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."
|
||||
|
||||
@ -139,14 +139,14 @@ def main():
|
||||
|
||||
if args.type in ["cpp", "both"]:
|
||||
if command_exists("clang-format-" + CFVERSION):
|
||||
CLANGFORMAT = "clang-format-" + CFVERSION
|
||||
CLANGFORMAT = "clang-format-" + CFVERSION
|
||||
elif command_exists("clang-format"):
|
||||
CLANGFORMAT = "clang-format"
|
||||
CLANGFORMAT = "clang-format"
|
||||
|
||||
if CLANGFORMAT is not None:
|
||||
print("Using source formatter: " + CLANGFORMAT)
|
||||
else:
|
||||
print("clang-format not found. can't format source files")
|
||||
print("clang-format not found, unable to format source files")
|
||||
|
||||
if args.qt is not None and args.type in ["qml", "both"]:
|
||||
global QMLFORMAT # pylint: disable=global-statement
|
||||
@ -154,7 +154,7 @@ def main():
|
||||
if QMLFORMAT is not None:
|
||||
print("Using qmlformatter: " + QMLFORMAT)
|
||||
else:
|
||||
print("qmlformat not found, can't format QML files")
|
||||
print("qmlformat not found, unable to format QML files")
|
||||
|
||||
if args.install:
|
||||
if CLANGFORMAT is not None or QMLFORMAT is not None:
|
||||
@ -171,10 +171,10 @@ def main():
|
||||
exit_if_no_files()
|
||||
else:
|
||||
if src_files and args.type in ["cpp", "both"] and CLANGFORMAT:
|
||||
print("Formatting source files...")
|
||||
print("Formatting source files…")
|
||||
clang_format_files(src_files)
|
||||
if qml_files and args.type in ["qml", "both"] and QMLFORMAT:
|
||||
print("Formatting QML files...")
|
||||
print("Formatting QML files…")
|
||||
qml_format_files(qml_files)
|
||||
|
||||
|
||||
|
||||
@ -1,92 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2022-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, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
# USA.
|
||||
|
||||
"""
|
||||
Generate qrc file for qml and related code files recursively within the source
|
||||
directory.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
# These paths should be relative to the working directory of the
|
||||
# script as set in the project CMakeLists, which should in turn be
|
||||
# where the resources.qrc will be located (currently 'src/app').
|
||||
app_src_dir = os.path.join('..', '..', 'src', 'app')
|
||||
resfile = os.path.join('qml.qrc')
|
||||
|
||||
|
||||
def path_contains_dir(filepath, dir_str):
|
||||
""" Return True if the given filepath contains the given directory. """
|
||||
# Split the filepath into its components
|
||||
path_components = os.path.normpath(filepath).split(os.sep)
|
||||
# Return True if the given directory is in the path
|
||||
return dir_str in path_components
|
||||
|
||||
|
||||
def posix_path(path):
|
||||
"""
|
||||
Force the use of POSIX path separators for the resource prefixes
|
||||
and paths (useful only if versioning the qml.qrc file).
|
||||
"""
|
||||
return path.replace(os.sep, '/')
|
||||
|
||||
|
||||
def gen_qml_qrc(with_webengine):
|
||||
""" Generate the qml.qrc file. """
|
||||
print("Generating qml.qrc file ...")
|
||||
with open(resfile, 'w', encoding='utf-8') as qrc:
|
||||
qrc.write('<RCC>\n')
|
||||
for root, _, files in os.walk(app_src_dir):
|
||||
# Skip the nowebengine directory if we can use webengine
|
||||
if with_webengine and path_contains_dir(root, 'nowebengine'):
|
||||
continue
|
||||
# Skip the webengine directory if we can't use webengine
|
||||
if not with_webengine and path_contains_dir(root, 'webengine'):
|
||||
continue
|
||||
filtered = [k for k in files if k.endswith('.qml') or
|
||||
k.endswith('.js') or k.endswith('.html') or
|
||||
k.endswith('.css') or k.endswith('.conf') or
|
||||
k == 'qmldir']
|
||||
# if there are no files of interest in this directory, skip it
|
||||
if not filtered:
|
||||
continue
|
||||
# For now, get the relative resource prefix for this directory,
|
||||
# remove the leading slash, and add it as a comment to the line.
|
||||
# Ideally, we should use the actual resource prefix instead of /,
|
||||
# but this will require some refactoring of the QML code.
|
||||
prefix = root.split(app_src_dir)[-1][1:]
|
||||
qrc.write(
|
||||
f'\t<qresource prefix="/"> <!--{posix_path(prefix)}-->\n')
|
||||
for file in filtered:
|
||||
relpath = os.path.relpath(
|
||||
os.path.join(root, file), app_src_dir)
|
||||
qrc.write(f'\t\t<file>{posix_path(relpath)}</file>\n')
|
||||
qrc.write('\t</qresource>\n')
|
||||
qrc.write('</RCC>')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# We can't use webengine if we're building for macOS app store
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--with-webengine', action='store_true',
|
||||
default=False, help='Include webengine resources')
|
||||
args = parser.parse_args()
|
||||
gen_qml_qrc(args.with_webengine)
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2022-2025 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, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
# USA.
|
||||
|
||||
"""
|
||||
Generate qrc file for qml and related code files recursively within the source
|
||||
directory.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
# These paths should be relative to the working directory of the
|
||||
# script as set in the project CMakeLists, which should in turn be
|
||||
# where the resources.qrc will be located (currently 'src/app').
|
||||
app_src_dir = os.path.join('..', '..', 'src', 'app')
|
||||
resfile = os.path.join('qml.qrc')
|
||||
|
||||
|
||||
def path_contains_dir(filepath, dir_str):
|
||||
""" Return True if the given filepath contains the given directory. """
|
||||
# Split the filepath into its components
|
||||
path_components = os.path.normpath(filepath).split(os.sep)
|
||||
# Return True if the given directory is in the path
|
||||
return dir_str in path_components
|
||||
|
||||
|
||||
def posix_path(path):
|
||||
"""
|
||||
Force the use of POSIX path separators for the resource prefixes
|
||||
and paths (useful only if versioning the qml.qrc file).
|
||||
"""
|
||||
return path.replace(os.sep, '/')
|
||||
|
||||
|
||||
def gen_qml_qrc(with_webengine):
|
||||
""" Generate the qml.qrc file. """
|
||||
print("Generating qml.qrc file…")
|
||||
with open(resfile, 'w', encoding='utf-8') as qrc:
|
||||
qrc.write('<RCC>\n')
|
||||
for root, _, files in os.walk(app_src_dir):
|
||||
# Skip the nowebengine directory if we can use WebEngine
|
||||
if with_webengine and path_contains_dir(root, 'nowebengine'):
|
||||
continue
|
||||
# Skip the webengine directory if WebEngine is unable to be used
|
||||
if not with_webengine and path_contains_dir(root, 'webengine'):
|
||||
continue
|
||||
filtered = [k for k in files if k.endswith('.qml') or
|
||||
k.endswith('.js') or k.endswith('.html') or
|
||||
k.endswith('.css') or k.endswith('.conf') or
|
||||
k == 'qmldir']
|
||||
# if there are no files of interest in this directory, skip it
|
||||
if not filtered:
|
||||
continue
|
||||
# For now, get the relative resource prefix for this directory,
|
||||
# remove the leading slash, and add it as a comment to the line.
|
||||
# Ideally, we should use the actual resource prefix instead of /,
|
||||
# but this will require some refactoring of the QML code.
|
||||
prefix = root.split(app_src_dir)[-1][1:]
|
||||
qrc.write(
|
||||
f'\t<qresource prefix="/"> <!--{posix_path(prefix)}-->\n')
|
||||
for file in filtered:
|
||||
relpath = os.path.relpath(
|
||||
os.path.join(root, file), app_src_dir)
|
||||
qrc.write(f'\t\t<file>{posix_path(relpath)}</file>\n')
|
||||
qrc.write('\t</qresource>\n')
|
||||
qrc.write('</RCC>')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# WebEngine is unable to be used if building for macOS App Store
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--with-webengine', action='store_true',
|
||||
default=False, help='Include WebEngine resources')
|
||||
args = parser.parse_args()
|
||||
gen_qml_qrc(args.with_webengine)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2021-2024 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2021-2025 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
|
||||
@ -64,7 +64,7 @@ def gen_resources_qrc(with_webengine):
|
||||
qrc.write('<RCC>\n')
|
||||
qml.write('pragma Singleton\nimport QtQuick\nQtObject {\n')
|
||||
for root, _, files in os.walk(resdir):
|
||||
# Skip the webengine directory if we can't use webengine
|
||||
# Skip the WebEngine directory if WebEngine is unable to used
|
||||
if not with_webengine and path_contains_dir(root, 'webengine'):
|
||||
continue
|
||||
prefix = root.rsplit(os.sep, 1)[-1]
|
||||
@ -90,10 +90,10 @@ def gen_resources_qrc(with_webengine):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# We can't use webengine if we're building for macOS app store
|
||||
# WebEngine is unable to be used if building for macOS App Store
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--with-webengine', action='store_true',
|
||||
default=False, help='Include webengine resources')
|
||||
default=False, help='Include WebEngine resources')
|
||||
args = parser.parse_args()
|
||||
gen_resources_qrc(args.with_webengine)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2019-2024 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2019-2025 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
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# install.sh --- build and install Jami daemon and client
|
||||
|
||||
# Copyright (C) 2016-2024 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2016-2025 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
|
||||
@ -31,6 +31,7 @@ export OSTYPE
|
||||
# -a: arch to build
|
||||
# -A: enable AddressSanitizer
|
||||
# -D: extra CMake flags for the client
|
||||
# -C: enable crash reporting
|
||||
|
||||
set -ex
|
||||
|
||||
@ -49,8 +50,9 @@ asan=
|
||||
extra_cmake_flags=''
|
||||
arch=''
|
||||
enable_testing=false
|
||||
enable_crashreports=false
|
||||
|
||||
while getopts gsc:dQ:P:p:uWwa:AtD: OPT; do
|
||||
while getopts gsc:dQ:P:p:uWwa:AtD:C OPT; do
|
||||
case "$OPT" in
|
||||
g)
|
||||
global='true'
|
||||
@ -91,6 +93,9 @@ while getopts gsc:dQ:P:p:uWwa:AtD: OPT; do
|
||||
D)
|
||||
extra_cmake_flags="${OPTARG}"
|
||||
;;
|
||||
C)
|
||||
enable_crashreports='true'
|
||||
;;
|
||||
\?)
|
||||
exit 1
|
||||
;;
|
||||
@ -212,6 +217,12 @@ else
|
||||
client_cmake_flags+=(-DBUILD_TESTING=Off)
|
||||
fi
|
||||
|
||||
if [ "${enable_crashreports}" = "true" ]; then
|
||||
client_cmake_flags+=(-DENABLE_CRASHREPORTS=ON)
|
||||
else
|
||||
client_cmake_flags+=(-DENABLE_CRASHREPORTS=OFF)
|
||||
fi
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
#detect arch for macos
|
||||
CMAKE_OSX_ARCHITECTURES="arm64"
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
##
|
||||
## Copyright (C) 2016-2024 Savoir-faire Linux Inc.
|
||||
##
|
||||
## Author: Edric Milaret <edric.ladent-milaret@savoirfairelinux.com>
|
||||
## Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
|
||||
## Copyright (C) 2016-2025 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
|
||||
@ -26,9 +23,9 @@ import shutil
|
||||
|
||||
print("== Updating from sources")
|
||||
if os.system("lupdate jami.pro -no-obsolete"):
|
||||
print("trying with 'lupdate-qt5'")
|
||||
print("Attempting with 'lupdate-qt5'")
|
||||
if os.system("lupdate-qt5 jami.pro -no-obsolete"):
|
||||
raise RuntimeError("unable to find any suitable lupdate Qt tool on this system. Stopping")
|
||||
raise RuntimeError("Unable to find any suitable lupdate Qt tool on this system. Stopping…")
|
||||
|
||||
print("== Pushing sources")
|
||||
os.system("tx push -s")
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 514 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 622 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 779 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 653 KiB |
BIN
resources/images/welcome_bg_dark.jpg
Normal file
BIN
resources/images/welcome_bg_dark.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 522 KiB |
BIN
resources/images/welcome_bg_light.jpg
Normal file
BIN
resources/images/welcome_bg_light.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 528 KiB |
382
resources/misc/available_dictionaries.json
Normal file
382
resources/misc/available_dictionaries.json
Normal file
@ -0,0 +1,382 @@
|
||||
{
|
||||
"af_ZA": {
|
||||
"nativeName": "Afrikaans (Suid-Afrika)",
|
||||
"path": "af_ZA/af_ZA"
|
||||
},
|
||||
"an_ES": {
|
||||
"nativeName": "aragonés (España)",
|
||||
"path": "an_ES/an_ES"
|
||||
},
|
||||
"ar": {
|
||||
"nativeName": "العربية",
|
||||
"path": "ar/ar"
|
||||
},
|
||||
"as_IN": {
|
||||
"nativeName": "অসমীয়া (भारत)",
|
||||
"path": "as_IN/as_IN"
|
||||
},
|
||||
"be-official": {
|
||||
"nativeName": "беларуская",
|
||||
"path": "be_BY/be-official"
|
||||
},
|
||||
"bg_BG": {
|
||||
"nativeName": "български",
|
||||
"path": "bg_BG/bg_BG"
|
||||
},
|
||||
"bn_BD": {
|
||||
"nativeName": "বাঙ্গালি (বাংলাদেশ)",
|
||||
"path": "bn_BD/bn_BD"
|
||||
},
|
||||
"bn_IN": {
|
||||
"nativeName": "বাঙ্গালি (ভারত)",
|
||||
"path": "bn_BD/bn_IN"
|
||||
},
|
||||
"bo": {
|
||||
"nativeName": "བོད་སྐད་",
|
||||
"path": "bo/bo"
|
||||
},
|
||||
"br_FR": {
|
||||
"nativeName": "breton (France)",
|
||||
"path": "br_FR/br_FR"
|
||||
},
|
||||
"bs_BA": {
|
||||
"nativeName": "bosanski",
|
||||
"path": "bs_BA/bs_BA"
|
||||
},
|
||||
"cs_CZ": {
|
||||
"nativeName": "čeština",
|
||||
"path": "cs_CZ/cs_CZ"
|
||||
},
|
||||
"da_DK": {
|
||||
"nativeName": "dansk",
|
||||
"path": "da_DK/da_DK"
|
||||
},
|
||||
"de_AT_frami": {
|
||||
"nativeName": "Deutsch (Österreich)",
|
||||
"path": "de/de_AT_frami"
|
||||
},
|
||||
"de_CH_frami": {
|
||||
"nativeName": "Deutsch (Schweiz)",
|
||||
"path": "de/de_CH_frami"
|
||||
},
|
||||
"de_DE_frami": {
|
||||
"nativeName": "Deutsch (Deutschland)",
|
||||
"path": "de/de_DE_frami"
|
||||
},
|
||||
"el_GR": {
|
||||
"nativeName": "Ελληνικά",
|
||||
"path": "el_GR/el_GR"
|
||||
},
|
||||
"en_AU": {
|
||||
"nativeName": "English (Australia)",
|
||||
"path": "en/en_AU"
|
||||
},
|
||||
"en_CA": {
|
||||
"nativeName": "English (Canada)",
|
||||
"path": "en/en_CA"
|
||||
},
|
||||
"en_GB": {
|
||||
"nativeName": "English (British)",
|
||||
"path": "en/en_GB"
|
||||
},
|
||||
"en_US": {
|
||||
"nativeName": "English (American)",
|
||||
"path": "en/en_US"
|
||||
},
|
||||
"en_ZA": {
|
||||
"nativeName": "English (Suid-Afrika)",
|
||||
"path": "en/en_ZA"
|
||||
},
|
||||
"eo": {
|
||||
"nativeName": "esperanto",
|
||||
"path": "eo/eo"
|
||||
},
|
||||
"es_AR": {
|
||||
"nativeName": "español (Argentina)",
|
||||
"path": "es/es_AR"
|
||||
},
|
||||
"es_BO": {
|
||||
"nativeName": "español (Bolivia)",
|
||||
"path": "es/es_BO"
|
||||
},
|
||||
"es_CL": {
|
||||
"nativeName": "español (Chile)",
|
||||
"path": "es/es_CL"
|
||||
},
|
||||
"es_CO": {
|
||||
"nativeName": "español (Colombia)",
|
||||
"path": "es/es_CO"
|
||||
},
|
||||
"es_CR": {
|
||||
"nativeName": "español (Costa Rica)",
|
||||
"path": "es/es_CR"
|
||||
},
|
||||
"es_CU": {
|
||||
"nativeName": "español (Cuba)",
|
||||
"path": "es/es_CU"
|
||||
},
|
||||
"es_DO": {
|
||||
"nativeName": "español (República Dominicana)",
|
||||
"path": "es/es_DO"
|
||||
},
|
||||
"es_EC": {
|
||||
"nativeName": "español (Ecuador)",
|
||||
"path": "es/es_EC"
|
||||
},
|
||||
"es_ES": {
|
||||
"nativeName": "español (España)",
|
||||
"path": "es/es_ES"
|
||||
},
|
||||
"es_GQ": {
|
||||
"nativeName": "español (Guinea Ecuatorial)",
|
||||
"path": "es/es_GQ"
|
||||
},
|
||||
"es_GT": {
|
||||
"nativeName": "español (Guatemala)",
|
||||
"path": "es/es_GT"
|
||||
},
|
||||
"es_HN": {
|
||||
"nativeName": "español (Honduras)",
|
||||
"path": "es/es_HN"
|
||||
},
|
||||
"es_MX": {
|
||||
"nativeName": "español (México)",
|
||||
"path": "es/es_MX"
|
||||
},
|
||||
"es_NI": {
|
||||
"nativeName": "español (Nicaragua)",
|
||||
"path": "es/es_NI"
|
||||
},
|
||||
"es_PA": {
|
||||
"nativeName": "español (Panamá)",
|
||||
"path": "es/es_PA"
|
||||
},
|
||||
"es_PE": {
|
||||
"nativeName": "español (Perú)",
|
||||
"path": "es/es_PE"
|
||||
},
|
||||
"es_PH": {
|
||||
"nativeName": "español (Pilipinas)",
|
||||
"path": "es/es_PH"
|
||||
},
|
||||
"es_PR": {
|
||||
"nativeName": "español (Puerto Rico)",
|
||||
"path": "es/es_PR"
|
||||
},
|
||||
"es_PY": {
|
||||
"nativeName": "español (Paraguai)",
|
||||
"path": "es/es_PY"
|
||||
},
|
||||
"es_SV": {
|
||||
"nativeName": "español (El Salvador)",
|
||||
"path": "es/es_SV"
|
||||
},
|
||||
"es_US": {
|
||||
"nativeName": "español (United States)",
|
||||
"path": "es/es_US"
|
||||
},
|
||||
"es_UY": {
|
||||
"nativeName": "español (Uruguay)",
|
||||
"path": "es/es_UY"
|
||||
},
|
||||
"es_VE": {
|
||||
"nativeName": "español (Venezuela)",
|
||||
"path": "es/es_VE"
|
||||
},
|
||||
"et_EE": {
|
||||
"nativeName": "eesti",
|
||||
"path": "et_EE/et_EE"
|
||||
},
|
||||
"fa-IR": {
|
||||
"nativeName": "فارسی",
|
||||
"path": "fa_IR/fa-IR"
|
||||
},
|
||||
"fr": {
|
||||
"nativeName": "français",
|
||||
"path": "fr_FR/fr"
|
||||
},
|
||||
"gd_GB": {
|
||||
"nativeName": "Gàidhlig",
|
||||
"path": "gd_GB/gd_GB"
|
||||
},
|
||||
"gl_ES": {
|
||||
"nativeName": "galego",
|
||||
"path": "gl/gl_ES"
|
||||
},
|
||||
"gu_IN": {
|
||||
"nativeName": "ગુજરાતી",
|
||||
"path": "gu_IN/gu_IN"
|
||||
},
|
||||
"he_IL": {
|
||||
"nativeName": "עברית",
|
||||
"path": "he_IL/he_IL"
|
||||
},
|
||||
"hi_IN": {
|
||||
"nativeName": "हिन्दी",
|
||||
"path": "hi_IN/hi_IN"
|
||||
},
|
||||
"hr_HR": {
|
||||
"nativeName": "hrvatski",
|
||||
"path": "hr_HR/hr_HR"
|
||||
},
|
||||
"hu_HU": {
|
||||
"nativeName": "magyar",
|
||||
"path": "hu_HU/hu_HU"
|
||||
},
|
||||
"id_ID": {
|
||||
"nativeName": "Indonesian",
|
||||
"path": "id/id_ID"
|
||||
},
|
||||
"is": {
|
||||
"nativeName": "íslenska",
|
||||
"path": "is/is"
|
||||
},
|
||||
"it_IT": {
|
||||
"nativeName": "italiano",
|
||||
"path": "it_IT/it_IT"
|
||||
},
|
||||
"kmr_Latn": {
|
||||
"nativeName": "Northern Kurdish",
|
||||
"path": "kmr_Latn/kmr_Latn"
|
||||
},
|
||||
"kn_IN": {
|
||||
"nativeName": "ಕನ್ನಡ",
|
||||
"path": "kn_IN/kn_IN"
|
||||
},
|
||||
"ko_KR": {
|
||||
"nativeName": "한국어",
|
||||
"path": "ko_KR/ko_KR"
|
||||
},
|
||||
"lo_LA": {
|
||||
"nativeName": "ລາວ",
|
||||
"path": "lo_LA/lo_LA"
|
||||
},
|
||||
"lt": {
|
||||
"nativeName": "lietuvių",
|
||||
"path": "lt_LT/lt"
|
||||
},
|
||||
"lv_LV": {
|
||||
"nativeName": "latviešu",
|
||||
"path": "lv_LV/lv_LV"
|
||||
},
|
||||
"mn_MN": {
|
||||
"nativeName": "монгол",
|
||||
"path": "mn_MN/mn_MN"
|
||||
},
|
||||
"mr_IN": {
|
||||
"nativeName": "मराठी",
|
||||
"path": "mr_IN/mr_IN"
|
||||
},
|
||||
"nb_NO": {
|
||||
"nativeName": "norsk bokmål",
|
||||
"path": "no/nb_NO"
|
||||
},
|
||||
"ne_NP": {
|
||||
"nativeName": "नेपाली",
|
||||
"path": "ne_NP/ne_NP"
|
||||
},
|
||||
"nl_NL": {
|
||||
"nativeName": "Nederlands",
|
||||
"path": "nl_NL/nl_NL"
|
||||
},
|
||||
"nn_NO": {
|
||||
"nativeName": "norsk nynorsk",
|
||||
"path": "no/nn_NO"
|
||||
},
|
||||
"oc_FR": {
|
||||
"nativeName": "occitan",
|
||||
"path": "oc_FR/oc_FR"
|
||||
},
|
||||
"or_IN": {
|
||||
"nativeName": "ଓଡ଼ିଆ",
|
||||
"path": "or_IN/or_IN"
|
||||
},
|
||||
"pa_IN": {
|
||||
"nativeName": "ਪੰਜਾਬੀ",
|
||||
"path": "pa_IN/pa_IN"
|
||||
},
|
||||
"pl_PL": {
|
||||
"nativeName": "polski",
|
||||
"path": "pl_PL/pl_PL"
|
||||
},
|
||||
"pt_BR": {
|
||||
"nativeName": "português (Brasil)",
|
||||
"path": "pt_BR/pt_BR"
|
||||
},
|
||||
"pt_PT": {
|
||||
"nativeName": "português europeu (Portugal)",
|
||||
"path": "pt_PT/pt_PT"
|
||||
},
|
||||
"ro_RO": {
|
||||
"nativeName": "română",
|
||||
"path": "ro/ro_RO"
|
||||
},
|
||||
"ru_RU": {
|
||||
"nativeName": "русский",
|
||||
"path": "ru_RU/ru_RU"
|
||||
},
|
||||
"sa_IN": {
|
||||
"nativeName": "संस्कृत भाषा",
|
||||
"path": "sa_IN/sa_IN"
|
||||
},
|
||||
"si_LK": {
|
||||
"nativeName": "සිංහල",
|
||||
"path": "si_LK/si_LK"
|
||||
},
|
||||
"sk_SK": {
|
||||
"nativeName": "slovenčina",
|
||||
"path": "sk_SK/sk_SK"
|
||||
},
|
||||
"sl_SI": {
|
||||
"nativeName": "slovenščina",
|
||||
"path": "sl_SI/sl_SI"
|
||||
},
|
||||
"sq_AL": {
|
||||
"nativeName": "shqip",
|
||||
"path": "sq_AL/sq_AL"
|
||||
},
|
||||
"sr": {
|
||||
"nativeName": "српски",
|
||||
"path": "sr/sr"
|
||||
},
|
||||
"sr-Latn": {
|
||||
"nativeName": "srpski",
|
||||
"path": "sr/sr-Latn"
|
||||
},
|
||||
"sv_FI": {
|
||||
"nativeName": "svenska (Finland)",
|
||||
"path": "sv_SE/sv_FI"
|
||||
},
|
||||
"sv_SE": {
|
||||
"nativeName": "svenska (Sverige)",
|
||||
"path": "sv_SE/sv_SE"
|
||||
},
|
||||
"sw_TZ": {
|
||||
"nativeName": "Kiswahili",
|
||||
"path": "sw_TZ/sw_TZ"
|
||||
},
|
||||
"ta_IN": {
|
||||
"nativeName": "தமிழ்",
|
||||
"path": "ta_IN/ta_IN"
|
||||
},
|
||||
"te_IN": {
|
||||
"nativeName": "తెలుగు",
|
||||
"path": "te_IN/te_IN"
|
||||
},
|
||||
"th_TH": {
|
||||
"nativeName": "ไทย",
|
||||
"path": "th_TH/th_TH"
|
||||
},
|
||||
"tr_TR": {
|
||||
"nativeName": "Türkçe",
|
||||
"path": "tr_TR/tr_TR"
|
||||
},
|
||||
"uk_UA": {
|
||||
"nativeName": "українська",
|
||||
"path": "uk_UA/uk_UA"
|
||||
},
|
||||
"vi_VN": {
|
||||
"nativeName": "Tiếng Việt",
|
||||
"path": "vi/vi_VN"
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 Savoir-faire Linux Inc.
|
||||
* Author: Yang Wang <yang.wang@savoirfairelinux.com>
|
||||
* Copyright (C) 2019-2025 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2024-2025 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
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Copyright (C) 2020-2025 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
|
||||
@ -85,7 +84,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
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022-2024 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
* Copyright (C) 2022-2025 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
|
||||
@ -18,6 +17,7 @@
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtWebEngine
|
||||
|
||||
import net.jami.Adapters 1.1
|
||||
import net.jami.Enums 1.1
|
||||
@ -38,9 +38,12 @@ QtObject {
|
||||
readonly property bool isHidden: visibility === Window.Hidden ||
|
||||
visibility === Window.Minimized
|
||||
|
||||
// Used to store if a OngoingCallPage component is fullscreened.
|
||||
// Used to store if a CallStackView component is fullscreened.
|
||||
property bool isCallFullscreen: false
|
||||
|
||||
// Used to store if a WebEngineView component is fullscreened.
|
||||
property bool isWebFullscreen: false
|
||||
|
||||
// QWK: Provide spacing for widgets that may be occluded by the system buttons.
|
||||
property QtObject qwkSystemButtonSpacing: QtObject {
|
||||
id: qwkSystemButtonSpacing
|
||||
@ -151,9 +154,8 @@ QtObject {
|
||||
// Adds an item to the fullscreen item stack. Automatically puts
|
||||
// the main window in fullscreen mode if needed. Callbacks should be used
|
||||
// to perform component-specific tasks upon successful transitions.
|
||||
function pushFullScreenItem(item, prevParent, pushedCb, removedCb) {
|
||||
if (item === null || item === undefined
|
||||
|| priv.fullScreenItems.length >= 3) {
|
||||
function pushFullScreenItem(item, removedCb=undefined) {
|
||||
if (!item || priv.fullScreenItems.length >= 3) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -163,15 +165,13 @@ QtObject {
|
||||
// Add the item to our list and reparent it to appContainer.
|
||||
priv.fullScreenItems.push({
|
||||
"item": item,
|
||||
"prevParent": prevParent,
|
||||
"prevParent": item.parent,
|
||||
"prevAnchorsFill": item.anchors.fill,
|
||||
"removedCb": removedCb
|
||||
})
|
||||
|
||||
item.parent = appContainer
|
||||
item.anchors.fill = item.parent
|
||||
if (pushedCb) {
|
||||
pushedCb()
|
||||
}
|
||||
item.anchors.fill = appContainer
|
||||
|
||||
// Reevaluate isCallFullscreen.
|
||||
priv.fullScreenItemsChanged()
|
||||
@ -179,34 +179,37 @@ QtObject {
|
||||
|
||||
// Remove an item if specified, or by default, the top item. Automatically
|
||||
// resets the main window to windowed mode if no items remain in the stack.
|
||||
function popFullScreenItem(obj=null) {
|
||||
function popFullScreenItem(obj = undefined) {
|
||||
// Remove the item and reparent it to its original parent.
|
||||
if (obj === null) {
|
||||
obj = priv.fullScreenItems.pop()
|
||||
if (obj === undefined) {
|
||||
obj = priv.fullScreenItems.pop();
|
||||
} else {
|
||||
const index = priv.fullScreenItems.indexOf(obj);
|
||||
if (index > -1) {
|
||||
priv.fullScreenItems.splice(index, 1);
|
||||
}
|
||||
}
|
||||
if (obj !== undefined) {
|
||||
if (obj && typeof obj === 'object') {
|
||||
if (obj.item !== appWindow) {
|
||||
obj.item.anchors.fill = obj.prevAnchorsFill
|
||||
obj.item.parent = obj.prevParent
|
||||
if (obj.removedCb) {
|
||||
obj.removedCb()
|
||||
// Clear anchors first, then set parent, then reset anchors.
|
||||
obj.item.anchors.fill = undefined;
|
||||
obj.item.parent = obj.prevParent;
|
||||
obj.item.anchors.fill = obj.prevAnchorsFill;
|
||||
|
||||
// Call removed callback if it's a function.
|
||||
if (typeof obj.removedCb === 'function') {
|
||||
obj.removedCb();
|
||||
}
|
||||
}
|
||||
|
||||
// Reevaluate isCallFullscreen.
|
||||
priv.fullScreenItemsChanged()
|
||||
priv.fullScreenItemsChanged();
|
||||
}
|
||||
|
||||
// Only leave fullscreen mode if our window isn't in fullscreen
|
||||
// mode already.
|
||||
// Only leave fullscreen mode if our window isn't in fullscreen mode already.
|
||||
if (priv.fullScreenItems.length === 0 && priv.windowedVisibility !== Window.Hidden) {
|
||||
// Simply recall the last visibility state.
|
||||
visibility = priv.windowedVisibility
|
||||
visibility = priv.windowedVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,7 +251,10 @@ QtObject {
|
||||
// When fullScreenItems is changed, we can recompute isCallFullscreen.
|
||||
onFullScreenItemsChanged: {
|
||||
isCallFullscreen = fullScreenItems
|
||||
.filter(o => o.item instanceof OngoingCallPage)
|
||||
.filter(o => o.item.objectName === "callViewLoader")
|
||||
.length
|
||||
isWebFullscreen = fullScreenItems
|
||||
.filter(o => o.item instanceof WebEngineView)
|
||||
.length
|
||||
}
|
||||
|
||||
@ -259,7 +265,7 @@ QtObject {
|
||||
function onHasCallChanged() {
|
||||
if (!CallAdapter.hasCall && isCallFullscreen) {
|
||||
priv.fullScreenItems.forEach(o => {
|
||||
if (o.item instanceof OngoingCallPage) {
|
||||
if (o.item.objectName === "callViewLoader") {
|
||||
popFullScreenItem(o)
|
||||
return
|
||||
}
|
||||
|
||||
@ -1,10 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
* Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
* Author: Albert Babí <albert.babi@savoirfairelinux.com>
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Author: Yang Wang <yang.wang@savoirfairelinux.com>
|
||||
* Copyright (C) 2020-2025 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
|
||||
@ -24,18 +19,15 @@ import QtQuick.Window
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import net.jami.Models 1.1
|
||||
import net.jami.Adapters 1.1
|
||||
import net.jami.Enums 1.1
|
||||
import net.jami.Helpers 1.1
|
||||
import net.jami.Constants 1.1
|
||||
|
||||
import "mainview"
|
||||
import "mainview/components"
|
||||
import "wizardview"
|
||||
import "commoncomponents"
|
||||
|
||||
import QWindowKit
|
||||
|
||||
ApplicationWindow {
|
||||
@ -45,6 +37,7 @@ ApplicationWindow {
|
||||
property bool isRTL: UtilsAdapter.isRTL
|
||||
LayoutMirroring.enabled: isRTL
|
||||
LayoutMirroring.childrenInherit: isRTL
|
||||
property var raiseWhenCalled: AppSettingsManager.getValue(Settings.RaiseWhenCalled)
|
||||
|
||||
onActiveFocusItemChanged: {
|
||||
focusOverlay.margin = -5;
|
||||
@ -68,7 +61,7 @@ ApplicationWindow {
|
||||
sourceComponent: GenericErrorsRow {
|
||||
id: genericError
|
||||
text: CurrentAccount.enabled ? JamiStrings.noNetworkConnectivity : JamiStrings.disabledAccount
|
||||
height: visible? JamiTheme.qwkTitleBarHeight : 0
|
||||
height: visible ? JamiTheme.qwkTitleBarHeight : 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,9 +85,11 @@ ApplicationWindow {
|
||||
appContainer: fullscreenContainer
|
||||
}
|
||||
// Used to manage dynamic view loading and unloading.
|
||||
property ViewManager viewManager: ViewManager {}
|
||||
property ViewManager viewManager: ViewManager {
|
||||
}
|
||||
// Used to manage the view stack and the current view.
|
||||
property ViewCoordinator viewCoordinator: ViewCoordinator {}
|
||||
property ViewCoordinator viewCoordinator: ViewCoordinator {
|
||||
}
|
||||
|
||||
// Used to prevent the window from being visible until the
|
||||
// window geometry has been restored and the view stack has
|
||||
@ -204,12 +199,31 @@ ApplicationWindow {
|
||||
if (useFrameless) {
|
||||
windowAgent.setup(appWindow);
|
||||
}
|
||||
|
||||
mainViewLoader.active = true;
|
||||
|
||||
// Dbus error handler for Linux.
|
||||
if (Qt.platform.os.toString() !== "windows" && Qt.platform.os.toString() !== "osx")
|
||||
DBusErrorHandler.setActive(true);
|
||||
|
||||
// Handle potential crash recovery.
|
||||
var crashedLastRun = crashReporter.getHasPendingReport();
|
||||
if (crashedLastRun) {
|
||||
// A crash was detected during the last session. We need to inform the user and offer to send a crash report.
|
||||
var dlg = viewCoordinator.presentDialog(appWindow, "commoncomponents/ConfirmDialog.qml", {
|
||||
"title": JamiStrings.crashReportTitle,
|
||||
"textLabel": JamiStrings.crashReportMessage + "\n\n" + JamiStrings.crashReportMessageExtra,
|
||||
"confirmLabel": JamiStrings.send,
|
||||
"rejectLabel": JamiStrings.dontSend,
|
||||
"textHAlign": Text.AlignLeft,
|
||||
"textMaxWidth": 400
|
||||
});
|
||||
dlg.accepted.connect(function () {
|
||||
crashReporter.uploadLastReport();
|
||||
});
|
||||
dlg.rejected.connect(function () {
|
||||
crashReporter.clearReports();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
@ -278,11 +292,31 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: UtilsAdapter
|
||||
function onRaiseWhenCalledChanged() {
|
||||
raiseWhenCalled = AppSettingsManager.getValue(Settings.RaiseWhenCalled);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: CallAdapter
|
||||
|
||||
function onCallStatusChanged(index, accountId, convUid) {
|
||||
//If we are starting a call with raiseWhenCalled activated
|
||||
if (raiseWhenCalled && index === Call.Status.INCOMING_RINGING) {
|
||||
appWindow.raise();
|
||||
appWindow.requestActivate();
|
||||
layoutManager.restoreApp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: MainApplication
|
||||
|
||||
function onAboutToQuit() {
|
||||
cleanupMainView()
|
||||
cleanupMainView();
|
||||
}
|
||||
|
||||
function onCloseRequested() {
|
||||
@ -320,7 +354,7 @@ ApplicationWindow {
|
||||
});
|
||||
}
|
||||
|
||||
function presentUpdateConfirmInstallDialog(switchToBeta=false) {
|
||||
function presentUpdateConfirmInstallDialog(switchToBeta = false) {
|
||||
return viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
|
||||
"title": JamiStrings.updateDialogTitle,
|
||||
"infoText": switchToBeta ? JamiStrings.confirmBeta : JamiStrings.updateFound,
|
||||
@ -362,7 +396,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;
|
||||
}
|
||||
@ -371,7 +405,7 @@ ApplicationWindow {
|
||||
presentUpdateInfoDialog(JamiStrings.updateNotFound);
|
||||
} else {
|
||||
// Show a dialog describing that an update were found, and offering to install it.
|
||||
presentUpdateConfirmInstallDialog()
|
||||
presentUpdateConfirmInstallDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,4 +416,20 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
onClosing: appWindow.close()
|
||||
|
||||
// Capture the inputs to the main window while the File Dialog is open
|
||||
// This is used to mitigate modality issues on Ubuntu 22.04 systems that use wayland.
|
||||
Loader {
|
||||
active: JamiQmlUtils.openFileDialogCount > 0
|
||||
sourceComponent: Popup {
|
||||
modal: true
|
||||
visible: true
|
||||
closePolicy: Popup.NoAutoClose
|
||||
width: appWindow.width
|
||||
height: appWindow.height
|
||||
background: Rectangle {
|
||||
color: "#80808080" // Semi-transparent grey
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2024-2025 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
|
||||
@ -49,13 +49,13 @@ QtObject {
|
||||
// right side when not in RTL and should represent the main or content-type view.
|
||||
readonly property var visibleViews: {
|
||||
if (!currentView)
|
||||
return []
|
||||
return [];
|
||||
if (isDualPane) {
|
||||
if (isInSinglePaneMode)
|
||||
return [currentView.rightPaneItem]
|
||||
return [currentView.leftPaneItem, currentView.rightPaneItem]
|
||||
return [currentView.rightPaneItem];
|
||||
return [currentView.leftPaneItem, currentView.rightPaneItem];
|
||||
}
|
||||
return [currentView]
|
||||
return [currentView];
|
||||
}
|
||||
// Aggregate this info and expose it as a single string for convenience.
|
||||
// JSON indented by 2 spaces.
|
||||
@ -64,12 +64,12 @@ QtObject {
|
||||
currentViewName: currentViewName,
|
||||
isDualPane: isDualPane,
|
||||
isInSinglePaneMode: isInSinglePaneMode,
|
||||
visibleViews: visibleViews.map(function(view) {
|
||||
return view && view.objectName || null;
|
||||
}),
|
||||
visibleViewWidths: visibleViews.map(function(view) {
|
||||
return view && view.width || null;
|
||||
}),
|
||||
visibleViews: visibleViews.map(function (view) {
|
||||
return view && view.objectName || null;
|
||||
}),
|
||||
visibleViewWidths: visibleViews.map(function (view) {
|
||||
return view && view.width || null;
|
||||
})
|
||||
};
|
||||
return JSON.stringify(info, null, 2);
|
||||
}
|
||||
@ -96,11 +96,12 @@ QtObject {
|
||||
}
|
||||
|
||||
// Create, present, and return a dialog object.
|
||||
function presentDialog(parent, path, props = {}) {
|
||||
function presentDialog(parent, path, props = {}, singleInstance = false) {
|
||||
// Open the dialog once the object is created
|
||||
return viewManager.createUniqueView(path, parent, function (obj) {
|
||||
let createFunc = singleInstance ? viewManager.createView : viewManager.createUniqueView;
|
||||
return createFunc(path, parent, function (obj, viewName) {
|
||||
const doneCb = function () {
|
||||
viewManager.destroyView(path);
|
||||
viewManager.destroyView(viewName);
|
||||
};
|
||||
if (obj.closed !== undefined) {
|
||||
obj.closed.connect(doneCb);
|
||||
@ -145,7 +146,7 @@ QtObject {
|
||||
if (!view.managed)
|
||||
view.presented();
|
||||
}, props)) {
|
||||
print("could not create view:", viewName);
|
||||
print("An error occurred while creating view:", viewName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,7 +185,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 +195,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);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2024-2025 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
|
||||
@ -59,7 +59,7 @@ QtObject {
|
||||
if (views.hasOwnProperty(viewName)) {
|
||||
// an instance of the view already exists
|
||||
if (cb !== null) {
|
||||
cb(views[viewName])
|
||||
cb(views[viewName], viewName)
|
||||
}
|
||||
return views[viewName]
|
||||
}
|
||||
@ -76,7 +76,7 @@ QtObject {
|
||||
viewName.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "")
|
||||
viewPaths[friendlyName] = viewName
|
||||
if (cb !== null) {
|
||||
cb(obj)
|
||||
cb(obj , viewName)
|
||||
}
|
||||
return views[viewName]
|
||||
}
|
||||
@ -103,6 +103,7 @@ QtObject {
|
||||
function destroyView(path) {
|
||||
// The view may already have been destroyed.
|
||||
if (!views.hasOwnProperty(path)) {
|
||||
console.warn("View not found:", path, "Available views:", Object.keys(views))
|
||||
return false
|
||||
}
|
||||
views[path].destroy()
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 Savoir-faire Linux Inc.
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Copyright (C) 2019-2025 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
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Author: Yang Wang <yang.yang@savoirfairelinux.com>
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
* Copyright (C) 2020-2025 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
|
||||
@ -25,8 +22,11 @@
|
||||
#include "systemtray.h"
|
||||
#include "lrcinstance.h"
|
||||
#include "accountlistmodel.h"
|
||||
#include "wizardviewstepmodel.h"
|
||||
#include "global.h"
|
||||
#include "api/account.h"
|
||||
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QThreadPool>
|
||||
|
||||
AccountAdapter::AccountAdapter(AppSettingsManager* settingsManager,
|
||||
SystemTray* systemTray,
|
||||
@ -114,7 +114,10 @@ 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) {
|
||||
@ -162,8 +165,9 @@ AccountAdapter::createJamiAccount(const QVariantMap& settings)
|
||||
|
||||
connectFailure();
|
||||
|
||||
auto futureResult = QtConcurrent::run([this, settings] {
|
||||
QThreadPool::globalInstance()->start([this, settings] {
|
||||
lrcInstance_->accountModel().createNewAccount(lrc::api::profile::Type::JAMI,
|
||||
{},
|
||||
settings["alias"].toString(),
|
||||
settings["archivePath"].toString(),
|
||||
settings["password"].toString(),
|
||||
@ -209,14 +213,14 @@ AccountAdapter::createSIPAccount(const QVariantMap& settings)
|
||||
|
||||
connectFailure();
|
||||
|
||||
auto futureResult = QtConcurrent::run([this, settings] {
|
||||
QThreadPool::globalInstance()->start([this, settings] {
|
||||
lrcInstance_->accountModel().createNewAccount(lrc::api::profile::Type::SIP,
|
||||
{},
|
||||
settings["alias"].toString(),
|
||||
settings["archivePath"].toString(),
|
||||
"",
|
||||
"",
|
||||
settings["username"].toString(),
|
||||
{});
|
||||
settings["username"].toString());
|
||||
});
|
||||
}
|
||||
|
||||
@ -253,7 +257,7 @@ AccountAdapter::createJAMSAccount(const QVariantMap& settings)
|
||||
|
||||
connectFailure();
|
||||
|
||||
auto futureResult = QtConcurrent::run([this, settings] {
|
||||
QThreadPool::globalInstance()->start([this, settings] {
|
||||
lrcInstance_->accountModel().connectToAccountManager(settings["username"].toString(),
|
||||
settings["password"].toString(),
|
||||
settings["manager"].toString());
|
||||
@ -296,29 +300,24 @@ AccountAdapter::setCurrAccDisplayName(const QString& text)
|
||||
void
|
||||
AccountAdapter::setCurrentAccountAvatarFile(const QString& source)
|
||||
{
|
||||
auto futureResult = QtConcurrent::run([this, source]() {
|
||||
QThreadPool::globalInstance()->start([this, source]() {
|
||||
QPixmap image;
|
||||
if (!image.load(source)) {
|
||||
qWarning() << "Not a valid image file";
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
AccountAdapter::setCurrentAccountAvatarBase64(const QString& data)
|
||||
{
|
||||
auto futureResult = QtConcurrent::run([this, data]() {
|
||||
QThreadPool::globalInstance()->start([this, data]() {
|
||||
auto accountId = lrcInstance_->get_currentAccountId();
|
||||
lrcInstance_->accountModel().setAvatar(accountId, data);
|
||||
lrcInstance_->accountModel().setAvatar(accountId, data, true, 1);
|
||||
});
|
||||
}
|
||||
|
||||
@ -347,9 +346,73 @@ AccountAdapter::exportToFile(const QString& accountId,
|
||||
void
|
||||
AccountAdapter::setArchivePasswordAsync(const QString& accountID, const QString& password)
|
||||
{
|
||||
auto futureResult = QtConcurrent::run([this, accountID, password] {
|
||||
QThreadPool::globalInstance()->start([this, accountID, password] {
|
||||
auto config = lrcInstance_->accountModel().getAccountConfig(accountID);
|
||||
config.archivePassword = password;
|
||||
lrcInstance_->accountModel().setAccountConfig(accountID, config);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
AccountAdapter::startImportAccount()
|
||||
{
|
||||
auto wizardModel = qApp->property("WizardViewStepModel").value<WizardViewStepModel*>();
|
||||
wizardModel->set_deviceAuthState(lrc::api::account::DeviceAuthState::INIT);
|
||||
wizardModel->set_deviceLinkDetails({});
|
||||
|
||||
// This will create an account with the ARCHIVE_URL configured to start the import process.
|
||||
importAccountId_ = lrcInstance_->accountModel().createDeviceImportAccount();
|
||||
}
|
||||
|
||||
void
|
||||
AccountAdapter::provideAccountAuthentication(const QString& password)
|
||||
{
|
||||
if (importAccountId_.isEmpty()) {
|
||||
qWarning() << "No import account to provide password to";
|
||||
return;
|
||||
}
|
||||
|
||||
auto wizardModel = qApp->property("WizardViewStepModel").value<WizardViewStepModel*>();
|
||||
wizardModel->set_deviceAuthState(lrc::api::account::DeviceAuthState::IN_PROGRESS);
|
||||
|
||||
Utils::oneShotConnect(
|
||||
&lrcInstance_->accountModel(),
|
||||
&lrc::api::AccountModel::accountAdded,
|
||||
[this](const QString& accountId) {
|
||||
Q_EMIT lrcInstance_->accountListChanged();
|
||||
Q_EMIT accountAdded(accountId,
|
||||
lrcInstance_->accountModel().getAccountList().indexOf(accountId));
|
||||
},
|
||||
this,
|
||||
&AccountAdapter::accountCreationFailed);
|
||||
|
||||
connectFailure();
|
||||
|
||||
QThreadPool::globalInstance()->start([this, password] {
|
||||
lrcInstance_->accountModel().provideAccountAuthentication(importAccountId_, password);
|
||||
});
|
||||
}
|
||||
|
||||
QString
|
||||
AccountAdapter::getImportErrorMessage(QVariantMap details)
|
||||
{
|
||||
QString errorString = details.value("error").toString();
|
||||
if (!errorString.isEmpty() && errorString != "none") {
|
||||
auto error = lrc::api::account::mapLinkDeviceError(errorString.toStdString());
|
||||
return lrc::api::account::getLinkDeviceString(error);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
AccountAdapter::cancelImportAccount()
|
||||
{
|
||||
auto wizardModel = qApp->property("WizardViewStepModel").value<WizardViewStepModel*>();
|
||||
wizardModel->set_deviceAuthState(lrc::api::account::DeviceAuthState::INIT);
|
||||
wizardModel->set_deviceLinkDetails({});
|
||||
|
||||
// Remove the account if it was created
|
||||
lrcInstance_->accountModel().removeAccount(importAccountId_);
|
||||
importAccountId_.clear();
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Savoir-faire Linux Inc.
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Copyright (C) 2021-2025 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
|
||||
@ -82,6 +81,13 @@ public:
|
||||
const bool& state);
|
||||
Q_INVOKABLE QStringList getDefaultModerators(const QString& accountId);
|
||||
|
||||
// New import account / link device functions
|
||||
// import: (note: Listen for: DeviceAuthStateChanged)
|
||||
Q_INVOKABLE void startImportAccount();
|
||||
Q_INVOKABLE void provideAccountAuthentication(const QString& password = {});
|
||||
Q_INVOKABLE QString getImportErrorMessage(QVariantMap details);
|
||||
Q_INVOKABLE void cancelImportAccount();
|
||||
|
||||
Q_SIGNALS:
|
||||
// Trigger other components to reconnect account related signals.
|
||||
void accountStatusChanged(QString accountId);
|
||||
@ -99,6 +105,9 @@ private:
|
||||
|
||||
QMetaObject::Connection registeredNameSavedConnection_;
|
||||
|
||||
// The account ID of the last used import account.
|
||||
QString importAccountId_;
|
||||
|
||||
AppSettingsManager* settingsManager_;
|
||||
SystemTray* systemTray_;
|
||||
};
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Copyright (C) 2019-2025 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
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Copyright (C) 2019-2025 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
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
* Copyright (C) 2021-2025 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
|
||||
@ -24,8 +23,7 @@
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QLibraryInfo>
|
||||
|
||||
#include <locale.h>
|
||||
#include <QDir>
|
||||
|
||||
const QString defaultDownloadPath = QStandardPaths::writableLocation(
|
||||
QStandardPaths::DownloadLocation);
|
||||
@ -36,8 +34,12 @@ AppSettingsManager::AppSettingsManager(QObject* parent)
|
||||
{
|
||||
for (int i = 0; i < static_cast<int>(Settings::Key::COUNT__); ++i) {
|
||||
auto key = static_cast<Settings::Key>(i);
|
||||
if (!settings_->contains(Settings::toString(key)))
|
||||
setValue(key, Settings::defaultValue(key));
|
||||
auto strKey= Settings::toString(key);
|
||||
// If the setting is written in the settings file and is equal to the default value,
|
||||
// remove it from the settings file.
|
||||
// This allow us to change default values without risking to remove user settings
|
||||
if ((settings_->contains(strKey)) && (settings_->value(strKey) == Settings::defaultValue(key)))
|
||||
settings_->remove(strKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
* Copyright (C) 2020-2025 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
|
||||
@ -26,7 +25,6 @@
|
||||
#include <QStandardPaths>
|
||||
#include <QWindow> // for QWindow::AutomaticVisibility
|
||||
#include <QSettings>
|
||||
#include <QDir>
|
||||
|
||||
#include <QTranslator>
|
||||
|
||||
@ -65,6 +63,8 @@ extern const QString defaultDownloadPath;
|
||||
X(WindowState, QWindow::AutomaticVisibility) \
|
||||
X(EnableExperimentalSwarm, false) \
|
||||
X(LANG, "SYSTEM") \
|
||||
X(SpellLang, {}) \
|
||||
X(EnableSpellCheck, true) \
|
||||
X(PluginStoreEndpoint, "https://plugins.jami.net") \
|
||||
X(PositionShareDuration, 15) \
|
||||
X(PositionShareLimit, true) \
|
||||
@ -74,7 +74,10 @@ extern const QString defaultDownloadPath;
|
||||
X(ShowSendOption, false) \
|
||||
X(EnablePtt, false) \
|
||||
X(PttKeys, 32) \
|
||||
X(UseFramelessWindow, USE_FRAMELESS_WINDOW_DEFAULT)
|
||||
X(UseFramelessWindow, USE_FRAMELESS_WINDOW_DEFAULT) \
|
||||
X(EnableCrashReporting, true) \
|
||||
X(EnableAutomaticCrashReporting, false) \
|
||||
X(RaiseWhenCalled, false)
|
||||
#if APPSTORE
|
||||
#define KEYS COMMON_KEYS
|
||||
#else
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2020-2025 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
|
||||
@ -18,7 +18,7 @@
|
||||
#include "appversionmanager.h"
|
||||
|
||||
#include "lrcinstance.h"
|
||||
#include "version.h"
|
||||
#include "version_info.h"
|
||||
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
@ -73,14 +73,14 @@ struct AppVersionManager::Impl : public QObject
|
||||
Q_EMIT parent_.updateCheckReplyReceived(false);
|
||||
return;
|
||||
}
|
||||
auto currentVersion = QString(VERSION_STRING).toULongLong();
|
||||
auto currentVersion = BUILD_VERSION_STRING.toULongLong();
|
||||
auto latestVersion = latestVersionString.toULongLong();
|
||||
const QString channelStr = isBeta ? "beta" : "stable";
|
||||
const auto newVersionFound = latestVersion > currentVersion;
|
||||
qInfo().noquote() << "--------- Version info ------------"
|
||||
<< QString("\n - Current: %1 (%2)").arg(currentVersion).arg(channelStr);
|
||||
qInfo().noquote() << "--------- Version info ------------";
|
||||
qInfo().noquote() << QString("\tCurrent: \t%1 (%2)").arg(currentVersion).arg(channelStr);
|
||||
if (newVersionFound) {
|
||||
qDebug() << " - Latest: " << latestVersion;
|
||||
qInfo().noquote() << QString("\tLatest: \t%1").arg(latestVersion);
|
||||
Q_EMIT parent_.updateCheckReplyReceived(true, true);
|
||||
} else if (!quiet) {
|
||||
Q_EMIT parent_.updateCheckReplyReceived(true, false);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2020-2025 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
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
* Copyright (C) 2021-2025 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
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
* Copyright (C) 2021-2025 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
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 Savoir-faire Linux Inc.
|
||||
* Author: Yang Wang <yang.wang@savoirfairelinux.com>
|
||||
* Copyright (C) 2019-2025 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
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 Savoir-faire Linux Inc.
|
||||
* Author: Yang Wang <yang.wang@savoirfairelinux.com>
|
||||
* Copyright (C) 2019-2025 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
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
* Author : Edric Ladent Milaret<edric.ladent - milaret @savoirfairelinux.com>
|
||||
* Author : Andreas Traczyk<andreas.traczyk @savoirfairelinux.com>
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Copyright (C) 2020-2025 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
|
||||
@ -165,7 +162,7 @@ AvAdapter::shareWayland(bool entireScreen)
|
||||
|
||||
int err = portal->getPipewireFd();
|
||||
if (err == EACCES) {
|
||||
qInfo() << "Can't share screen: permission denied";
|
||||
qInfo() << "Unable to share screen: permission denied";
|
||||
return;
|
||||
} else if (err != 0) {
|
||||
qWarning() << "Failed to get PipeWire fd. Error code:" << err;
|
||||
@ -178,7 +175,7 @@ AvAdapter::shareWayland(bool entireScreen)
|
||||
.arg(portal->pipewireFd)
|
||||
.arg(portal->pipewireNode);
|
||||
#ifndef ENABLE_LIBWRAP
|
||||
// If the daemon is running as a separate process, then it can't directly use the
|
||||
// If the daemon is running as a separate process, then it is unable to directly use the
|
||||
// PipeWire file descriptor opened by the client, so it will attempt to duplicate
|
||||
// it using the pidfd_getfd system call. This requires the daemon process to have
|
||||
// ptrace permission on the client process. On some systems, this will be true by
|
||||
@ -348,9 +345,11 @@ AvAdapter::shareScreenArea(unsigned x, unsigned y, unsigned width, unsigned heig
|
||||
}
|
||||
|
||||
void
|
||||
AvAdapter::shareWindow(const QString& windowProcessId, const QString& windowId)
|
||||
AvAdapter::shareWindow(const QString& windowProcessId, const QString& windowId, const int fps)
|
||||
{
|
||||
auto resource = lrcInstance_->getCurrentCallModel()->getDisplay(windowProcessId, windowId);
|
||||
auto resource = lrcInstance_->getCurrentCallModel()->getDisplay(windowProcessId,
|
||||
windowId,
|
||||
fps);
|
||||
auto callId = lrcInstance_->getCurrentCallId();
|
||||
|
||||
muteCamera_ = !isCapturing();
|
||||
@ -359,7 +358,10 @@ AvAdapter::shareWindow(const QString& windowProcessId, const QString& windowId)
|
||||
}
|
||||
|
||||
QString
|
||||
AvAdapter::getSharingResource(int screenId, const QString& windowProcessId, const QString& windowId)
|
||||
AvAdapter::getSharingResource(int screenId,
|
||||
const QString& windowProcessId,
|
||||
const QString& windowId,
|
||||
const int fps)
|
||||
{
|
||||
if (screenId == -1) {
|
||||
const auto arrangementRect = getAllScreensBoundingRect();
|
||||
@ -390,7 +392,7 @@ AvAdapter::getSharingResource(int screenId, const QString& windowProcessId, cons
|
||||
rect.height()
|
||||
* screen->devicePixelRatio());
|
||||
} else if (!windowId.isEmpty()) {
|
||||
return lrcInstance_->getCurrentCallModel()->getDisplay(windowProcessId, windowId);
|
||||
return lrcInstance_->getCurrentCallModel()->getDisplay(windowProcessId, windowId, fps);
|
||||
}
|
||||
|
||||
return "";
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*!
|
||||
* Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Copyright (C) 2020-2025 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
|
||||
@ -97,7 +96,9 @@ protected:
|
||||
Q_INVOKABLE void shareScreenArea(unsigned x, unsigned y, unsigned width, unsigned height);
|
||||
|
||||
// Select window to display (all platforms except Wayland).
|
||||
Q_INVOKABLE void shareWindow(const QString& windowProcessId, const QString& windowId);
|
||||
Q_INVOKABLE void shareWindow(const QString& windowProcessId,
|
||||
const QString& windowId,
|
||||
const int fps = -1);
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// Share a window on Wayland.
|
||||
@ -111,7 +112,8 @@ protected:
|
||||
// Returns the screensharing resource
|
||||
Q_INVOKABLE QString getSharingResource(int screenId = -2,
|
||||
const QString& windowProcessId = "",
|
||||
const QString& key = "");
|
||||
const QString& key = "",
|
||||
const int fps = -1);
|
||||
|
||||
Q_INVOKABLE void getListWindows();
|
||||
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 Savoir-faire Linux Inc.
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
* Copyright (C) 2020-2025 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
|
||||
@ -24,6 +22,7 @@
|
||||
#include "lrcinstance.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QRegularExpression>
|
||||
|
||||
class AsyncAvatarImageResponseRunnable : public AsyncImageResponseRunnable
|
||||
{
|
||||
@ -71,6 +70,16 @@ public:
|
||||
image = Utils::accountPhoto(lrcInstance_, imageId, requestedSize_);
|
||||
} else if (type == "contact") {
|
||||
image = Utils::contactPhoto(lrcInstance_, imageId, requestedSize_);
|
||||
} else if (type == "temporaryAccount") {
|
||||
// Check if imageId is a SHA-1 hash (jamiId or registered name)
|
||||
static const QRegularExpression sha1Pattern("^[0-9a-fA-F]{40}$");
|
||||
if (sha1Pattern.match(imageId).hasMatch()) {
|
||||
// If we only have a jamiId use default avatar
|
||||
image = Utils::fallbackAvatar("jami:" + imageId, QString(), requestedSize_);
|
||||
} else {
|
||||
// For registered usernames, use fallbackAvatar avatar with the name
|
||||
image = Utils::fallbackAvatar(QString(), imageId, requestedSize_);
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "Missing valid prefix in the image url";
|
||||
return;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user