Compare commits

..

70 Commits

Author SHA1 Message Date
6360e52eb5 Connection monitoring: ajust dark theme color
Change-Id: I1225f1039859946ef2154820d45a6f9682b6ced1
2023-11-01 14:40:51 -04:00
d38858c1f3 filesharing: consider audio in the proposed list
When adding/removing a file sharing we must add/remove
not only the video but also the audio media attributes
to the media change proposal.

GitLab: https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/485
Change-Id: Ifa6be8d500a43b1c2494501a4d6a6a6f009fdb62
2023-11-01 13:52:51 -04:00
088c367485 filesharing: integrate mediaplayer API
GitLab: https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/485
Change-Id: I148f19eb76a526a5ab38c5f4a83f45ea66e348e4
2023-11-01 13:52:46 -04:00
fc7109950b swarm-call: do not create 1:1 conversation for incoming calls in swarm
There was no way to differentiate a 1:1 incoming call and a call
from a swarm, because username couldn't be checked. Now, create
conversation only if it's a 1:1 call

Change-Id: I0094967914b4888d083b9adc1d2b11de467d6f48
2023-11-01 13:52:37 -04:00
5776ab7c7d build: add a script option to clean libjami contribs
Change-Id: I6d3cdfb30e148c0e74fcd1b69b2f1d317425d691
2023-10-31 15:44:51 -04:00
d4d34ad4fc Patch menu: standardize with design
Positionning the menu, change reply icon, close menu when click a second time on the button, and add animation for all menu's buttons

Change-Id: I8567a74ba53de214305cbcf432541803d921f60e
2023-10-31 07:37:39 -04:00
86d55fa985 i18n: automatic bump
Change-Id: If3dbab4b02784722ee2b7785bcf14be58d0fd615
2023-10-30 16:42:38 -04:00
303acbda64 packaging: add python-six to opensuse leap 15.4 (qtwebengine)
Change-Id: Ica84f3169cfe95be9097dce50e311d1e09f65723
2023-10-30 14:23:01 -04:00
a433974340 app Store: disable donations
Change-Id: I359cf1cd538a87f12f0e931b8b2948cf1c721cce
2023-10-30 09:45:44 -04:00
7a759dab7a Push-To-Talk : add global and local ptt
It works with a Pimpl which the right pttlistener.cpp depending
on the platform you are on (macOs, windows or X11). It is a
global PTT which listen to key events during calls. If the
global PTT is not supported, a local PTT is set.

https://git.jami.net/savoirfairelinux/jami-project/-/issues/1402

Change-Id: I8399800966c737bb8e8a656ecbb6af7ac7cdde8c
2023-10-30 09:31:26 -04:00
d2e87150b4 misc: fix build on fedora 39
Change-Id: I0b64db0a418e9992dcafa053c762e153a65515b8
2023-10-30 08:40:46 -04:00
ec60458dbe misc: fix sidepanel and donation date
Change-Id: I98294ccfb1ae68b45260f3e66bdce3e179ee55a9
2023-10-26 15:57:11 -04:00
8a9aea2f28 Patch menu: position of the popup
Change-Id: I9a07dccc7bb4a17c0ce3046906f922d5ace35f8a
2023-10-26 11:15:47 -04:00
ae86464658 Chat setting view: add darktheme color
GitLab: #1369

Change-Id: I863d13dc924e3e0d12dd92f9fb2b8d48bad051f4
2023-10-25 13:10:44 -04:00
5f0163df05 Menu: add some details on menu
GitLab: #1388
Change-Id: Ia38dbd15b176afcaf7c03b6612695ee5b6e89723
2023-10-25 11:34:53 -04:00
493addcbd8 Menu: refactor menu
GitLab: #1388

Change-Id: Ia168dce60ffdafa1ab4d08905c46f47f98625916
2023-10-24 15:20:03 -04:00
f144b27db8 misc: bump daemon
Change-Id: I3d6a777d5b482f0810144780c333a292ce0e3f5c
2023-10-24 14:52:38 -04:00
861c42e3d5 fix: don't remove the daemon cache dir
Change-Id: Icde3c4f5dbb54c2ae93712434f5d08def4e3c3bb
2023-10-24 13:20:29 -04:00
873c4c72b9 i18n: automatic bump
Change-Id: Id0905136d6091270819b9ae8b37d3e9be5d9c1dc
2023-10-23 16:47:01 -04:00
3e012c32d5 Welcome view: set default title to false and resize logo
GitLab: #1334

Change-Id: I71930584b3f5e0925ba8f5f42fff669ff9237dd1
2023-10-23 14:41:23 -04:00
6bff3c54f1 TroubleshootingSetting: Connection monitoring
Change-Id: Idf922df701cdf2efc2d167362dca021897d8e2e5
2023-10-23 13:39:13 -04:00
e55eaa5d8e packaging: add fedora 39, ubuntu 23.10
Change-Id: I2da6a821b25c3a5ae26ba8f59f3dc8b6656751b5
2023-10-20 09:16:08 -04:00
1a17735d55 misc: bump daemon
Change-Id: I20cbebf0bea67385b08fa879884ce2a7f8634d52
2023-10-19 15:52:03 -04:00
4e5f153230 Message button: set circled false
Change-Id: I58aee3397e46025a79321e2a54211f72d299077e
2023-10-19 15:23:12 -04:00
15351a5aae splitview: hide handles when in single-pane mode
Prevents breaking the UI.

Gitlab: #1370
Change-Id: I6bad222c2a05dc66402bc8f86e17f9a6d4d99c99
2023-10-18 13:01:58 -04:00
e89aa95673 Donation: show the tipbox only after the 1st November 2023
Change-Id: If2bb725a0be137a55a29cd7592726c4f2c718c8a
2023-10-17 14:29:49 -04:00
3609dae584 pushbutton: circled default to true
Change-Id: I85967917eae6d69f534aebeaae998454a9a6a4c0
2023-10-17 15:01:45 -03:00
8b21b0fda9 Share popup: fix font size
Change-Id: Ied676c0bcea675735274362ecc35de504c4c7fa9
2023-10-17 10:02:33 -04:00
811a93cc27 Chat settings: refactor chat settings
GitLab: #1369
Change-Id: I1bd9dfab7526a9cd0d84205817ab4eae951dba90
2023-10-17 08:31:05 -04:00
baeb90bced i18n: automatic bump
Change-Id: I5f6e1f01940f43a6e4d8ffd8c497a848ed981971
2023-10-16 16:42:38 -04:00
439fea530d PushButton: Remove transparent color who break the animation
PopUp: Add shadow on the SharePopup

Change-Id: I3829fb651116e2ce8da05e71ecb61a67356748c7
2023-10-16 12:57:16 -04:00
55415d6062 Donation campaign: add toggleswitch setting
GitLab: #1334
Change-Id: Ic0e2a4b08db7228e4a4bdab665f53adfa581e16c
2023-10-13 09:23:36 -04:00
9d3b5cd0c5 Donation campaign: add donate tipbox
GitLab: #1334
Change-Id: Ie32b6278fb28381524936baabf09ee3cbba04eb6
2023-10-11 11:25:05 -04:00
4e549d123e misc: use the cache dir instead of the data dir as the cache dir
Gitlab: #1378
Change-Id: I0249a87fba240eb65165fc79bdbc0ffb55f00af8
2023-10-11 09:51:54 -04:00
77193b26d9 eleutheria: update welcome page for release
GitLab: #1334
Change-Id: Ibe19091076f3b041517f32684a248700c0fce7ff
2023-10-10 15:13:02 -04:00
afb514ee02 i18n: automatic bump
Change-Id: I2a892bc8ee46e169865397d771d3e9d233468911
2023-10-09 16:43:02 -04:00
f1ccd5d05d downloader: use native separators when building target file path
Also reverts waiting on the msiexec process + error checking.

Change-Id: Icfd8c349087d1b9f84c95d855b68b7ef2e45b3ab
2023-10-05 19:12:07 -04:00
6a0963d37b misc: bump daemon
Change-Id: Ia78ee9a1946d79b68b0761642b37f90a77182a68
2023-10-05 17:13:29 -04:00
6fc30b51d6 windows: updates: make UI represent underlying update states
This commit fixes several issues:
- the update confirmation dialog getting stuck in the open state
- secondary attempts to download an update possibly causing a crash
- poor error information presented in the case of missing content
- unhandled errors during MSI package installation

Gitlab: #1367
Change-Id: Ia8855b8268ab13b8e1cbbb15de75d41f593f947a
2023-10-03 17:49:04 -04:00
2719f303d9 misc: bump daemon
Change-Id: I8a3fe51e2d868f25c482b1a57bea82bc976a457a
2023-10-03 16:30:22 -04:00
100756b02d viewmanager: allow creating more than 1 instance of a view
Previously, managed views were always stored in a dictionary using non-unique keys. This commit adds a method to the ViewManager component allowing for automatic unique key generation if the base key (QML component path) is the same. This is used for dialogs because we need to possibly open nested modal dialogs.

Gitlab: #1367
Change-Id: I94e0ef0e0ae79689445be0409dd902dc74554e43
2023-10-03 15:38:39 -04:00
b963a0bdf2 Avoid infinite loops in MainApplication::cleanup
Change-Id: I910ab554c463a3d91c48c297c6c1ed48202283f9
2023-10-03 15:18:47 -04:00
d765fc9297 PluginStoreEndPoint: add possibility to change the plugin store end point
Gitlab: #1341
Change-Id: Ib4516c6cf2361a4976230a6b056a4c072932a92b
2023-10-03 13:55:05 -04:00
f8f1301fa0 i18n: automatic bump
Change-Id: I35a6a56c9e7ddd8f83ef0a388ed7b7ec6d6f72d7
2023-10-02 16:42:38 -04:00
b9d24298f7 Donation campaign: add banner in smartlist
GitLab: #1334
Change-Id: I53b23eabab47389b9bea50f54afac28d41741b0b
2023-09-29 20:04:04 -04:00
6b9ce14ca9 messagerbar: add continue editing tooltip
Change-Id: Ifa69df02610e0d104b6a0bf338ded3128e2be9b7
GitLab: #1359
2023-09-29 05:06:41 -04:00
f88b8584af deploy-packages: add alma
Change-Id: I5ff774d6e2eceb3ce99d16eae34249ee451f9199
2023-09-29 02:18:36 -04:00
ad35d108f2 link-device: apply new design and add QR code
GitLab: #1253
Change-Id: Ib47a081e4e5d714e98fb397732ff9232b62afc36
2023-09-28 16:59:20 -04:00
63c3d0bf2e Build: build without dbus if enable_libwrap is not specified
Change-Id: I8819b193b83f7ee051d78d30990db40e3f295354
2023-09-28 11:37:54 -04:00
6f8f96edfd Correct some bug MessageBar
Change-Id: I198763539ba1b093ef9dfbc6f429ba15dcf93285
2023-09-26 17:03:27 -04:00
1bd7d75d29 Fingerprint : prevent overflow when zooming
GitLab: #1347
Change-Id: I2b1862b1df7b2bcc7c173a04b50c006d861241d2
2023-09-26 12:01:03 -04:00
ad29993e17 AboutJami button : text scale with text size
GitLab: #1348
Change-Id: I442b4ca074113ca4460757780b1bcc0b1675a35e
2023-09-26 11:15:10 -04:00
70ce0c091e i18n: automatic bump
Change-Id: I9b9ac457d4c71a343af793ad15bd6ce8c2ed4089
2023-09-25 16:43:03 -04:00
ea5b2d6589 misc: bump daemon
Change-Id: I9d10579e5bb231f4b457a0fd9f3c36c8bc491dbc
2023-09-22 15:04:16 -04:00
eaababc817 callactionbar: fix submenus layouts
Change-Id: I1d100b48db6ad95bf5e09642e9c12aad8ccf110a
2023-09-21 08:45:09 -04:00
aa96b723bc misc: bump daemon
Change-Id: I8ec5348b0a37c06e81ad3fc46c11822556391694
2023-09-20 21:16:46 -04:00
1616261bef misc: update plugin-store after plugin uninstall
Change-Id: Ibbb428e17f362f3645a530ad55fbd87d6719f98d
2023-09-20 14:58:32 -04:00
926ab72334 markdown: fix keyboard shortcuts
Change-Id: Ic02ab2df7a4a3870dbbe2f0e23160f13281ba2ac
GitLab: #1321
2023-09-20 14:54:54 -04:00
a6d16ba1f8 misc: pass HideSelf to true by default
Change-Id: I507ec00f9d94ae9cec5f63ca948bca1f9cdd82b3
2023-09-20 13:13:23 -04:00
b0c205159e misc: bump daemon
Change-Id: I424250b351a0947fe37c4baebfc27405ff48dad8
2023-09-20 09:20:59 -04:00
0c440660c4 i18n: automatic bump
Change-Id: I65efe898569dff45b9e6341db6e6b9332e60d890
2023-09-19 11:40:04 -04:00
c8cc61520d misc: update version name to Eleutheria
Change-Id: I6679ffec816636d6bb8bfded88b86f23c11f3b03
2023-09-19 11:01:13 -04:00
ab25276e27 Dialog popup: BaseModalDialog redone, every popup based on it checked
GitLab: #1326
Change-Id: Ia72a9f4d2daa60261054e050ab89de18a139ecd2
2023-09-19 10:33:20 -04:00
7b41c6faff UserProfile: display name must be readOnly
Change-Id: I3cd106af5ad7a141d884b948448e25053ab0832b
GitLab: #1349
2023-09-18 14:35:54 -04:00
7a84518f2c misc: cleanup, remove cacheAvatars
Now there is only one client, this doesn't need to be configured

Change-Id: Iba1265fbdb8ab18bfb44fc7c2c70ebfe6000ee2c
GitLab: #1305
2023-09-18 10:25:12 -04:00
1a12cb3b8c misc: replace Swarm Created message in 1:1
Change-Id: I71388da217d4912a4f89c36e8a539cdc65f40097
GitLab: #1342
2023-09-18 10:23:13 -04:00
75a154f4fe plugins: fix background of installed plugin
Change-Id: I0b890270dc10ddb3d77d10f07252d5da7266ba7f
2023-09-18 10:10:25 -04:00
b95abbc891 misc: fix shortcut for tile screenshot
Change-Id: Ic2e18dc9aef3e01d7d8f1f935b90fe73b527127b
GitLab: #1344
2023-09-15 12:34:57 -04:00
bc51b74692 misc: add search tooltip
Change-Id: I55e29557eca3b32c714a313cd18aff66a870fd0f
GitLab: #1343
2023-09-15 12:33:03 -04:00
899ff6120c misc: move GenericErrorsRow in MainApplicationWindow
Change-Id: I09fea85e9fa603481bd2cfe81b15a4d94dcc3ebd
Gitlab: #1135
2023-09-15 12:29:27 -04:00
267 changed files with 104283 additions and 77678 deletions

View File

@ -244,6 +244,8 @@ set(COMMON_SOURCES
${APP_SRC_DIR}/messageparser.cpp ${APP_SRC_DIR}/messageparser.cpp
${APP_SRC_DIR}/previewengine.cpp ${APP_SRC_DIR}/previewengine.cpp
${APP_SRC_DIR}/imagedownloader.cpp ${APP_SRC_DIR}/imagedownloader.cpp
${APP_SRC_DIR}/pluginversionmanager.cpp
${APP_SRC_DIR}/connectioninfolistmodel.cpp
${APP_SRC_DIR}/pluginversionmanager.cpp) ${APP_SRC_DIR}/pluginversionmanager.cpp)
set(COMMON_HEADERS set(COMMON_HEADERS
@ -310,8 +312,9 @@ set(COMMON_HEADERS
${APP_SRC_DIR}/messageparser.h ${APP_SRC_DIR}/messageparser.h
${APP_SRC_DIR}/htmlparser.h ${APP_SRC_DIR}/htmlparser.h
${APP_SRC_DIR}/imagedownloader.h ${APP_SRC_DIR}/imagedownloader.h
${APP_SRC_DIR}/pluginversionmanager.h) ${APP_SRC_DIR}/pluginversionmanager.h
${APP_SRC_DIR}/connectioninfolistmodel.h
${APP_SRC_DIR}/pttlistener.h)
# For libavutil/avframe. # For libavutil/avframe.
set(LIBJAMI_CONTRIB_DIR "${DAEMON_DIR}/contrib") set(LIBJAMI_CONTRIB_DIR "${DAEMON_DIR}/contrib")
@ -493,6 +496,29 @@ else()
OPTIONAL_COMPONENTS LinguistTools) OPTIONAL_COMPONENTS LinguistTools)
endif() endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
if (DEFINED ENV{XDG_SESSION_TYPE})
if ($ENV{XDG_SESSION_TYPE} STREQUAL "x11")
set(PTT_PLATFORM "x11")
list(APPEND COMMON_HEADER ${APP_SRC_DIR}/platform/X11/xcbkeyboard.H)
# TODO: add Wayland support
endif ()
endif ()
elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(PTT_PLATFORM "windows")
elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(PTT_PLATFORM "macos")
endif ()
if (NOT ${PTT_PLATFORM} STREQUAL "")
message(STATUS "Platform: ${PTT_PLATFORM}")
add_definitions(-DHAVE_GLOBAL_PTT)
list(APPEND COMMON_SOURCES ${APP_SRC_DIR}/platform/${PTT_PLATFORM}/pttlistener.cpp)
else ()
message(WARNING "Global push-to-talk not supported.")
list(APPEND COMMON_SOURCES ${APP_SRC_DIR}/platform/local/pttlistener.cpp)
endif ()
# common includes # common includes
include_directories( include_directories(
${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}
@ -593,7 +619,6 @@ elseif (NOT APPLE)
${GLIB_LIBRARIES} ${GLIB_LIBRARIES}
${GIO_LIBRARIES}) ${GIO_LIBRARIES})
# Installation rules
install( install(
TARGETS ${PROJECT_NAME} TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin) RUNTIME DESTINATION bin)
@ -724,7 +749,7 @@ else()
list(APPEND CLIENT_LIBS list(APPEND CLIENT_LIBS
"-framework AVFoundation" "-framework AVFoundation"
"-framework CoreAudio -framework CoreMedia -framework CoreVideo" "-framework CoreAudio -framework CoreMedia -framework CoreVideo"
"-framework VideoToolbox -framework AudioUnit" "-framework VideoToolbox -framework AudioUnit -framework Carbon"
"-framework Security" "-framework Security"
compression compression
resolv resolv
@ -763,6 +788,7 @@ else()
MACOSX_BUNDLE_COPYRIGHT "${PROJ_COPYRIGHT}") MACOSX_BUNDLE_COPYRIGHT "${PROJ_COPYRIGHT}")
if(APPSTORE) if(APPSTORE)
message(STATUS "app store version") message(STATUS "app store version")
add_definitions(-DAPPSTORE)
set_target_properties(${PROJECT_NAME} PROPERTIES set_target_properties(${PROJECT_NAME} PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/resources/entitlements/appstore/Jami.entitlements") XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/resources/entitlements/appstore/Jami.entitlements")
else() else()

View File

@ -458,6 +458,93 @@ def run_clean():
'git submodule foreach git clean -xfd']) 'git submodule foreach git clean -xfd'])
def clean_contribs(contribs):
"""
Helper to clean one or more of the libjami contribs.
Takes a list of contrib names(space separated) to clean, or 'all' to clean all contribs.
Contribs are assumed to be in the contrib_dir: daemon/contrib
Artifacts to remove include:
- build directory: <contrib_dir>/<native_dir>/<contrib_name>
- build stamp: <contrib_dir>/<native_dir>/.<contrib_name>
- tarball: <contrib_dir>/tarballs/<contrib_name>*.tar.*
- build artifacts (we don't care about the contents of share):
- <contrib_dir>/<abi_triplet>/bin/<contrib_name>
- <contrib_dir>/<abi_triplet>/lib/<contrib_name>*
- <contrib_dir>/<abi_triplet>/include/<contrib_name>*
"""
# Not supported on Windows
if platform.system() == 'Windows':
print('Cleaning contribs is not supported on Windows. Exiting.')
sys.exit(1)
# Assume we are using the submodule here.
contrib_dir = 'daemon/contrib'
sub_dirs = os.listdir(contrib_dir)
# Let's find the abi triplet:
# The abi_triplet is 3 parts: <arch>-<vendor>-<sys> and should be the only directory
# named like that in the contrib directory. We can use a regex to find it.
triplet_pattern = re.compile(r'^[a-zA-Z0-9_]+-[a-zA-Z0-9_]+-[a-zA-Z0-9_]+$')
def is_triplet(s):
return bool(triplet_pattern.match(s))
abi_triplet = ''
for sub_dir in sub_dirs:
if is_triplet(sub_dir):
abi_triplet = sub_dir
break
# If we didn't find the abi triplet, we need to stop.
if abi_triplet == '':
print('Could not find the abi triplet for the contribs. Exiting.')
sys.exit(1)
# Let's find the native build source directory (native-*)
native_dir = ''
for sub_dir in sub_dirs:
if sub_dir.startswith('native'):
native_dir = os.path.join(contrib_dir, sub_dir)
break
# If we didn't find the native build source directory, we need to stop.
if native_dir == '':
print('Could not find the native build source directory. Exiting.')
sys.exit(1)
# If contribs is 'all', construct the list of all contribs from the contrib native directory
# list of directories only
if contribs == ['all']:
contribs = [d for d in os.listdir(native_dir) if os.path.isdir(os.path.join(native_dir, d))]
# Clean each contrib
for contrib in contribs:
print(f'Cleaning contrib: {contrib} for {abi_triplet} in {native_dir}')
build_dir = os.path.join(native_dir, contrib, '*')
build_stamp = os.path.join(native_dir, f'.{contrib}*')
tarball = os.path.join(contrib_dir, 'tarballs', f'{contrib}*.tar.*')
bins = os.path.join(contrib_dir, abi_triplet, 'bin', contrib)
libs = os.path.join(contrib_dir, abi_triplet, 'lib', f'lib{contrib}*')
includes = os.path.join(contrib_dir, abi_triplet, 'include', f'{contrib}*')
# EXCEPTIONS: pjproject and ffmpeg
if contrib == 'pjproject':
libs = f' {os.path.join(contrib_dir, abi_triplet, "lib", "libpj*")}' \
f' {os.path.join(contrib_dir, abi_triplet, "lib", "libsrtp*")}'
includes = os.path.join(contrib_dir, abi_triplet, 'include', 'pj*')
elif contrib == 'ffmpeg':
libs = f' {os.path.join(contrib_dir, abi_triplet, "lib", "libav*")}' \
f' {os.path.join(contrib_dir, abi_triplet, "lib", "libsw*")}'
includes = f' {os.path.join(contrib_dir, abi_triplet, "include", "libav*")}' \
f' {os.path.join(contrib_dir, abi_triplet, "include", "libsw*")}'
# For a dry run:
# execute_script([f'find {build_dir} {build_stamp} {tarball} {bins} {libs} {includes}'], fail=False)
execute_script([f'rm -rf {build_dir} {build_stamp} {tarball} {bins} {libs} {includes}'], fail=False)
def run_run(args): def run_run(args):
run_env = os.environ run_env = os.environ
@ -640,6 +727,9 @@ def parse_args():
default=False, action='store_true', default=False, action='store_true',
help='Do not use Qt WebEngine.') help='Do not use Qt WebEngine.')
ap.add_argument('--arch') ap.add_argument('--arch')
ap.add_argument('--clean-contribs', nargs='+',
help='Clean the specified contribs (space separated) or \
"all" to clean all contribs before building.')
dist = choose_distribution() dist = choose_distribution()
@ -686,6 +776,10 @@ def choose_distribution():
def main(): def main():
parsed_args = parse_args() parsed_args = parse_args()
# Clean contribs if specified first.
if parsed_args.clean_contribs:
clean_contribs(parsed_args.clean_contribs)
if parsed_args.dependencies: if parsed_args.dependencies:
run_dependencies(parsed_args) run_dependencies(parsed_args)

2
daemon

Submodule daemon updated: 80be6f46b4...a5a46c0385

View File

@ -49,7 +49,7 @@ QT_MAJOR := 6
QT_MINOR := 4 QT_MINOR := 4
QT_PATCH := 3 QT_PATCH := 3
QT_TARBALL_CHECKSUM := 29a7eebdbba0ea57978dea6083709c93593a60f0f3133a3de08b9571ee8eaab4 QT_TARBALL_CHECKSUM := 29a7eebdbba0ea57978dea6083709c93593a60f0f3133a3de08b9571ee8eaab4
DEBIAN_QT_VERSION := $(QT_MAJOR).$(QT_MINOR).$(QT_PATCH)-2 DEBIAN_QT_VERSION := $(QT_MAJOR).$(QT_MINOR).$(QT_PATCH)-3
DEBIAN_QT_DSC_FILENAME := libqt-jami_$(DEBIAN_QT_VERSION).dsc DEBIAN_QT_DSC_FILENAME := libqt-jami_$(DEBIAN_QT_VERSION).dsc
QT_JAMI_PREFIX := /usr/lib/libqt-jami QT_JAMI_PREFIX := /usr/lib/libqt-jami
@ -167,8 +167,10 @@ DISTRIBUTIONS := \
ubuntu_20.04 \ ubuntu_20.04 \
ubuntu_22.04 \ ubuntu_22.04 \
ubuntu_23.04 \ ubuntu_23.04 \
ubuntu_23.10 \
fedora_37 \ fedora_37 \
fedora_38 \ fedora_38 \
fedora_39 \
opensuse-leap_15.4 \ opensuse-leap_15.4 \
snap snap

View File

@ -0,0 +1,104 @@
FROM fedora:39
RUN dnf clean all
RUN dnf update -y
RUN dnf install -y dnf-command\(builddep\) rpmdevtools && \
dnf install -y mock
RUN dnf groupinstall -y "X Software Development"
RUN dnf install -y \
git \
rpm-build \
tar \
make \
autoconf \
automake \
nasm \
speexdsp-devel \
pulseaudio-libs-devel \
libcanberra-devel \
libcurl-devel \
libtool \
mesa-libgbm-devel \
mesa-dri-drivers \
dbus-devel \
expat-devel \
pcre-devel \
yaml-cpp-devel \
libXext-devel \
libXfixes-devel \
yasm \
speex-devel \
gsm-devel \
chrpath \
check \
astyle \
uuid-c++-devel \
gettext-devel \
gcc-c++ \
which \
alsa-lib-devel \
systemd-devel \
libuuid-devel \
uuid-devel \
gnutls-devel \
nettle-devel \
opus-devel \
patch \
jsoncpp-devel \
libnatpmp-devel \
webkitgtk4-devel \
cryptopp-devel \
libva-devel \
libvdpau-devel \
msgpack-devel \
NetworkManager-libnm-devel \
openssl-devel \
clutter-devel \
clutter-gtk-devel \
libappindicator-gtk3-devel \
libnotify-devel \
libupnp-devel \
qrencode-devel \
libargon2-devel \
libsndfile-devel \
libdrm \
gperf \
bison \
clang \
clang-devel \
llvm-devel \
nodejs \
flex \
gstreamer1 gstreamer1-devel \
gstreamer1-plugins-base-devel \
gstreamer1-plugins-good \
gstreamer1-plugins-bad-free-devel \
nss-devel \
libxcb* \
libxkb* \
libX11-devel \
vulkan-devel \
libXrender-devel \
xcb-util-* \
xz \
xkeyboard-config \
libnotify \
wget \
libstdc++-static \
sqlite-devel \
perl-generators \
perl-English \
libxshmfence-devel \
ninja-build \
clang \
cmake \
fmt-devel \
python3.10 \
cups-devel
ADD extras/packaging/gnu-linux/scripts/build-package-rpm.sh /opt/build-package-rpm.sh
CMD ["/opt/build-package-rpm.sh"]

View File

@ -70,6 +70,7 @@ RUN zypper --non-interactive install -y \
nodejs12 \ nodejs12 \
mozilla-nss-devel \ mozilla-nss-devel \
python-xml \ python-xml \
python-six \
libxcb* \ libxcb* \
libxkb* \ libxkb* \
libX11-devel \ libX11-devel \

View File

@ -0,0 +1,22 @@
FROM ubuntu:23.10
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get clean
RUN apt-get update && \
apt-get install -y -o Acquire::Retries=10 \
devscripts \
equivs \
python-is-python3 \
wget
ADD extras/packaging/gnu-linux/scripts/prebuild-package-debian.sh /opt/prebuild-package-debian.sh
COPY extras/packaging/gnu-linux/rules/debian-qt/control /tmp/builddeps/debian/control
RUN /opt/prebuild-package-debian.sh qt-deps
COPY extras/packaging/gnu-linux/rules/debian/control /tmp/builddeps/debian/control
RUN /opt/prebuild-package-debian.sh jami-deps
ADD extras/packaging/gnu-linux/scripts/build-package-debian.sh /opt/build-package-debian.sh
CMD ["/opt/build-package-debian.sh"]

View File

@ -0,0 +1,81 @@
From ecae5d93b0a89e2b8c16a2227b2d176f58579d04 Mon Sep 17 00:00:00 2001
From: Rémi Denis-Courmont <remi@remlab.net>
Date: Sun, 16 Jul 2023 18:18:02 +0300
Subject: [PATCH] Fix ffmpeg assembly with newer binutil
avcodec/x86/mathops: clip constants used with shift instructions within inline assembly
Fixes assembling with binutil as >= 2.41
FFmpeg commit effadce6c756247ea8bae32dc13bb3e6f464f0eb.
Deals with: "Error: operand type mismatch for `shr'"
Fixes: QTBUG-116649
Change-Id: I094e8c23fed4a61fba3f1e3a9c73c016d129d830
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/495990
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
(cherry picked from commit 29354c7c7def7bdc66bcd25d401677fd9421f657)
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/509219
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/ffmpeg/libavcodec/x86/mathops.h b/qtwebengine/src/3rdparty/chromium/third_party/ffmpeg/libavcodec/x86/mathops.h
index 6298f5e..ca7e2df 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/ffmpeg/libavcodec/x86/mathops.h
+++ b/qtwebengine/src/3rdparty/chromium/third_party/ffmpeg/libavcodec/x86/mathops.h
@@ -35,12 +35,20 @@
static av_always_inline av_const int MULL(int a, int b, unsigned shift)
{
int rt, dummy;
+ if (__builtin_constant_p(shift))
__asm__ (
"imull %3 \n\t"
"shrdl %4, %%edx, %%eax \n\t"
:"=a"(rt), "=d"(dummy)
- :"a"(a), "rm"(b), "ci"((uint8_t)shift)
+ :"a"(a), "rm"(b), "i"(shift & 0x1F)
);
+ else
+ __asm__ (
+ "imull %3 \n\t"
+ "shrdl %4, %%edx, %%eax \n\t"
+ :"=a"(rt), "=d"(dummy)
+ :"a"(a), "rm"(b), "c"((uint8_t)shift)
+ );
return rt;
}
@@ -113,19 +121,31 @@
// avoid +32 for shift optimization (gcc should do that ...)
#define NEG_SSR32 NEG_SSR32
static inline int32_t NEG_SSR32( int32_t a, int8_t s){
+ if (__builtin_constant_p(s))
__asm__ ("sarl %1, %0\n\t"
: "+r" (a)
- : "ic" ((uint8_t)(-s))
+ : "i" (-s & 0x1F)
);
+ else
+ __asm__ ("sarl %1, %0\n\t"
+ : "+r" (a)
+ : "c" ((uint8_t)(-s))
+ );
return a;
}
#define NEG_USR32 NEG_USR32
static inline uint32_t NEG_USR32(uint32_t a, int8_t s){
+ if (__builtin_constant_p(s))
__asm__ ("shrl %1, %0\n\t"
: "+r" (a)
- : "ic" ((uint8_t)(-s))
+ : "i" (-s & 0x1F)
);
+ else
+ __asm__ ("shrl %1, %0\n\t"
+ : "+r" (a)
+ : "c" ((uint8_t)(-s))
+ );
return a;
}

View File

@ -0,0 +1,16 @@
qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp b/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp
index 3488120..120e47a 100644
--- a/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp
+++ b/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp
@@ -472,7 +472,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
}
catch (const DeadlyImportError& e)
{
- if (!is64bits && (length > std::numeric_limits<std::uint32_t>::max())) {
+ if (!is64bits && (length > std::numeric_limits<uint32_t>::max())) {
throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", ai_to_string(version), ") of the FBX format. (", e.what(), ")");
}
throw;

View File

@ -0,0 +1,433 @@
qtbase/src/corelib/debug_script.py | 2 +-
qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/parseTestRecord.py | 2 +-
qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/test/test_monkeyYaml.py | 2 +-
qtwebengine/src/3rdparty/chromium/chrome/browser/resources/PRESUBMIT_test.py | 2 +-
qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/angle/scripts/angle_presubmit_utils_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/blink/PRESUBMIT.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/flatbuffers/src/python/flatbuffers/compat.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/jinja2/environment.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/mako/mako/compat.py | 2 +-
.../src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/converters/call_trees_test.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_test.py | 2 +-
.../src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_testing.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/api_test.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/conversion_test.py | 2 +-
.../src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/inspect_utils_test.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/templates_test.py | 2 +-
.../3rdparty/chromium/third_party/tflite/src/tensorflow/python/tools/api/generator/create_python_api_test.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py | 2 +-
qtwebengine/src/3rdparty/chromium/tools/sublime/ninja_options_script.py | 2 +-
qtwebengine/src/3rdparty/chromium/v8/third_party/test262-harness/src/parseTestRecord.py | 2 +-
31 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/qtbase/src/corelib/debug_script.py b/qtbase/src/corelib/debug_script.py
index f6207c6104..663c8e0ac1 100644
--- a/qtbase/src/corelib/debug_script.py
+++ b/qtbase/src/corelib/debug_script.py
@@ -3,7 +3,7 @@
import os
import sys
-import imp
+import importlib
from distutils.version import LooseVersion
diff --git a/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/parseTestRecord.py b/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/parseTestRecord.py
index 681039d34b..a1fe56fa05 100644
--- a/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/parseTestRecord.py
+++ b/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/parseTestRecord.py
@@ -16,7 +16,7 @@ import subprocess
import sys
import tempfile
import time
-import imp
+import importlib
# from TestCasePackagerConfig import *
diff --git a/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/test/test_monkeyYaml.py b/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/test/test_monkeyYaml.py
index 92d4e6139b..7a18e12ced 100644
--- a/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/test/test_monkeyYaml.py
+++ b/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/test/test_monkeyYaml.py
@@ -7,7 +7,7 @@ import unittest
import os
import yaml
-import imp
+import importlib
# add parent dir to search path
import sys
diff --git a/qtwebengine/src/3rdparty/chromium/chrome/browser/resources/PRESUBMIT_test.py b/qtwebengine/src/3rdparty/chromium/chrome/browser/resources/PRESUBMIT_test.py
index c7412927c8..ad2caff318 100755
--- a/qtwebengine/src/3rdparty/chromium/chrome/browser/resources/PRESUBMIT_test.py
+++ b/qtwebengine/src/3rdparty/chromium/chrome/browser/resources/PRESUBMIT_test.py
@@ -5,7 +5,7 @@
import os
import sys
-import imp
+import importlib
import tempfile
import unittest
import PRESUBMIT
diff --git a/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py b/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py
index 5daee773ba..2d6b124162 100755
--- a/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py
+++ b/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py
@@ -9,7 +9,7 @@
"""
from __future__ import print_function
import abc
-import imp
+import importlib
import optparse
import os
import re
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py
index bf626f5479..3fae129aaa 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py
@@ -3,7 +3,7 @@
# found in the LICENSE file.
import errno
-import imp
+import importlib
import os.path
import sys
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py
index ff5753a291..04fc34f742 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import shutil
import sys
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py
index 32c884a8c0..e761faa54c 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py
index 95a916db08..4331e2fbfa 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py
index 62798631db..28e9dbf705 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py
index cba249b0f3..5a4051827a 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py
index 4a2fefc712..11a9879cb7 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
index cc17ae0253..bcc944f06b 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py
index bd72830e54..f2fdc9ae28 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/angle/scripts/angle_presubmit_utils_unittest.py b/qtwebengine/src/3rdparty/chromium/third_party/angle/scripts/angle_presubmit_utils_unittest.py
index 1feb303a48..8428de61bb 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/angle/scripts/angle_presubmit_utils_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/angle/scripts/angle_presubmit_utils_unittest.py
@@ -6,7 +6,7 @@
angle_presubmit_utils_unittest.py: Top-level unittest script for ANGLE presubmit checks.
"""
-import imp
+import importlib
import os
import unittest
from angle_presubmit_utils import *
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/blink/PRESUBMIT.py b/qtwebengine/src/3rdparty/chromium/third_party/blink/PRESUBMIT.py
index ed4f38c67b..cac734cefa 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/blink/PRESUBMIT.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/blink/PRESUBMIT.py
@@ -7,7 +7,7 @@ See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into gcl.
"""
-import imp
+import importlib
import inspect
import os
import re
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/flatbuffers/src/python/flatbuffers/compat.py b/qtwebengine/src/3rdparty/chromium/third_party/flatbuffers/src/python/flatbuffers/compat.py
index 0244c9787e..f535afe99c 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/flatbuffers/src/python/flatbuffers/compat.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/flatbuffers/src/python/flatbuffers/compat.py
@@ -32,7 +32,7 @@ if PY3:
memoryview_type = memoryview
struct_bool_decl = "?"
else:
- import imp
+ import importlib
string_types = (unicode,)
if PY26 or PY27:
binary_types = (str,bytearray)
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/jinja2/environment.py b/qtwebengine/src/3rdparty/chromium/third_party/jinja2/environment.py
index 8430390eea..29212205bc 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/jinja2/environment.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/jinja2/environment.py
@@ -732,7 +732,7 @@ class Environment(object):
)
py_compile = False
else:
- import imp
+ import importlib
import marshal
py_header = imp.get_magic() + u"\xff\xff\xff\xff".encode("iso-8859-15")
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/mako/mako/compat.py b/qtwebengine/src/3rdparty/chromium/third_party/mako/mako/compat.py
index 06bb8d99f5..05089dc982 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/mako/mako/compat.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/mako/mako/compat.py
@@ -115,7 +115,7 @@ if py3k:
return module
else:
- import imp
+ import importlib
def load_module(module_id, path):
fp = open(path, "rb")
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/converters/call_trees_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/converters/call_trees_test.py
index a7dc683365..68b6804c78 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/converters/call_trees_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/converters/call_trees_test.py
@@ -14,7 +14,7 @@
# ==============================================================================
"""Tests for call_trees module."""
-import imp
+import importlib
from tensorflow.python.autograph.converters import call_trees
from tensorflow.python.autograph.converters import functions
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_test.py
index 81a7fde808..1370f900fd 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_test.py
@@ -14,7 +14,7 @@
# ==============================================================================
"""Tests for converter module."""
-import imp
+import importlib
from tensorflow.python.autograph.core import converter
from tensorflow.python.autograph.core import converter_testing
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_testing.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_testing.py
index b93cbb627b..452ec71f5b 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_testing.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_testing.py
@@ -15,7 +15,7 @@
"""Base class for tests in this module."""
import contextlib
-import imp
+import importlib
import inspect
import sys
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/api_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/api_test.py
index 9a62d7c0d2..7ec4fa6dca 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/api_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/api_test.py
@@ -19,7 +19,7 @@ import collections
import contextlib
import functools
import gc
-import imp
+import importlib
import inspect
import os
import re
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/conversion_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/conversion_test.py
index 852af3efe7..6456c50446 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/conversion_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/conversion_test.py
@@ -14,7 +14,7 @@
# ==============================================================================
"""Tests for conversion module."""
-import imp
+import importlib
import sys
import types
import weakref
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/inspect_utils_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/inspect_utils_test.py
index a50a64534a..ba0f31afa2 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/inspect_utils_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/inspect_utils_test.py
@@ -17,7 +17,7 @@
import abc
import collections
import functools
-import imp
+import importlib
import textwrap
import six
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/templates_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/templates_test.py
index 29f38d853a..7ca88fa371 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/templates_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/templates_test.py
@@ -14,7 +14,7 @@
# ==============================================================================
"""Tests for templates module."""
-import imp
+import importlib
from absl.testing import parameterized
import gast
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/tools/api/generator/create_python_api_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/tools/api/generator/create_python_api_test.py
index e46460574b..a40fea6568 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/tools/api/generator/create_python_api_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/tools/api/generator/create_python_api_test.py
@@ -14,7 +14,7 @@
# =============================================================================
"""Tests for create_python_api."""
-import imp
+import importlib
import sys
from tensorflow.python.platform import test
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py b/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py
index 73d1742714..ea77dd7647 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py
@@ -1,5 +1,5 @@
import importlib
-import imp
+import importlib
from .browsers import product_list
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py b/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py
index 6a744472b5..9175cb5d34 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py
@@ -1,6 +1,6 @@
import copy
import functools
-import imp
+import importlib
import io
import os
from collections import OrderedDict, defaultdict
diff --git a/qtwebengine/src/3rdparty/chromium/tools/sublime/ninja_options_script.py b/qtwebengine/src/3rdparty/chromium/tools/sublime/ninja_options_script.py
index 6912b6f3c0..7d851f7f76 100755
--- a/qtwebengine/src/3rdparty/chromium/tools/sublime/ninja_options_script.py
+++ b/qtwebengine/src/3rdparty/chromium/tools/sublime/ninja_options_script.py
@@ -16,7 +16,7 @@
from __future__ import print_function
-import imp
+import importlib
import optparse
import os
import pipes
diff --git a/qtwebengine/src/3rdparty/chromium/v8/third_party/test262-harness/src/parseTestRecord.py b/qtwebengine/src/3rdparty/chromium/v8/third_party/test262-harness/src/parseTestRecord.py
index 1c2aba80af..55260d697e 100644
--- a/qtwebengine/src/3rdparty/chromium/v8/third_party/test262-harness/src/parseTestRecord.py
+++ b/qtwebengine/src/3rdparty/chromium/v8/third_party/test262-harness/src/parseTestRecord.py
@@ -10,7 +10,7 @@ from __future__ import print_function
import os
import re
-import imp
+import importlib
from _monkeyYaml import load as yamlLoad

View File

@ -1,2 +1,5 @@
0001-fix-gcc13.patch 0001-fix-gcc13.patch
0002-OpenFile-portal-do-not-use-O_PATH-fds.patch 0002-OpenFile-portal-do-not-use-O_PATH-fds.patch
0003-fix-mathops.patch
0004-fix-binary-tokenizer.patch
0005-importlib.patch

View File

@ -101,6 +101,8 @@ if [ -f /etc/os-release ]; then
ENDTAG="ubuntu_22.04" ENDTAG="ubuntu_22.04"
elif [ "${UBUNTU_CODENAME}" = "lunar" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_23.04" ]; then elif [ "${UBUNTU_CODENAME}" = "lunar" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_23.04" ]; then
ENDTAG="ubuntu_23.04" ENDTAG="ubuntu_23.04"
elif [ "${UBUNTU_CODENAME}" = "mantic" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_23.10" ]; then
ENDTAG="ubuntu_23.10"
elif [ "${ID}" = "debian" ] && \ elif [ "${ID}" = "debian" ] && \
[ "$(command -v lsb_release)" ] && \ [ "$(command -v lsb_release)" ] && \
[ "$(lsb_release -rs)" = "testing" ]; then [ "$(lsb_release -rs)" = "testing" ]; then

View File

@ -28,6 +28,9 @@ URL: https://jami.net/
Source: jami-libqt-%{version}.tar.xz Source: jami-libqt-%{version}.tar.xz
Patch0: 0001-fix-gcc13.patch Patch0: 0001-fix-gcc13.patch
Patch1: 0002-OpenFile-portal-do-not-use-O_PATH-fds.patch Patch1: 0002-OpenFile-portal-do-not-use-O_PATH-fds.patch
Patch2: 0003-fix-mathops.patch
Patch3: 0004-fix-binary-tokenizer.patch
Patch4: 0005-importlib.patch
%global gst 0.10 %global gst 0.10
%if 0%{?fedora} || 0%{?rhel} > 7 %if 0%{?fedora} || 0%{?rhel} > 7
@ -42,6 +45,7 @@ BuildRequires: bison
BuildRequires: gperf BuildRequires: gperf
BuildRequires: flex BuildRequires: flex
BuildRequires: vulkan-devel BuildRequires: vulkan-devel
BuildRequires: python-six
%if %{defined suse_version} %if %{defined suse_version}
BuildRequires: ffmpeg-devel BuildRequires: ffmpeg-devel
BuildRequires: ffmpeg BuildRequires: ffmpeg
@ -64,6 +68,9 @@ This package contains Qt libraries for Jami.
%setup -n qt-everywhere-src-%{version} %setup -n qt-everywhere-src-%{version}
%patch0 -p1 %patch0 -p1
%patch1 -p1 %patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%build %build
echo "Building Qt using %{job_count} parallel jobs" echo "Building Qt using %{job_count} parallel jobs"
@ -84,6 +91,15 @@ cat qtbase/src/corelib/global/qendian.h
sed -i 's,#include <string.h>,#include <string.h>\n#include <limits>,g' qtbase/src/corelib/global/qfloat16.h sed -i 's,#include <string.h>,#include <string.h>\n#include <limits>,g' qtbase/src/corelib/global/qfloat16.h
sed -i 's,#include <QtCore/qbytearray.h>,#include <QtCore/qbytearray.h>\n#include <limits>,g' qtbase/src/corelib/text/qbytearraymatcher.h sed -i 's,#include <QtCore/qbytearray.h>,#include <QtCore/qbytearray.h>\n#include <limits>,g' qtbase/src/corelib/text/qbytearraymatcher.h
cat qtwebengine/configure.cmake cat qtwebengine/configure.cmake
#https://bugreports.qt.io/browse/QTBUG-117979
if test -f "/usr/bin/python3.10"; then
/usr/bin/python3.10 -m venv env
source env/bin/activate
python -m pip install html5lib
python -m pip install six
fi
# recent gcc version do not like lto from qt # recent gcc version do not like lto from qt
CXXFLAGS="${CXXFLAGS} -fno-lto" CFLAGS="${CFLAGS} -fno-lto" LDFLAGS="$(CFLAGS) ${LDFLAGS}" ./configure \ CXXFLAGS="${CXXFLAGS} -fno-lto" CFLAGS="${CFLAGS} -fno-lto" LDFLAGS="$(CFLAGS) ${LDFLAGS}" ./configure \
-opensource \ -opensource \

View File

@ -0,0 +1,81 @@
From ecae5d93b0a89e2b8c16a2227b2d176f58579d04 Mon Sep 17 00:00:00 2001
From: Rémi Denis-Courmont <remi@remlab.net>
Date: Sun, 16 Jul 2023 18:18:02 +0300
Subject: [PATCH] Fix ffmpeg assembly with newer binutil
avcodec/x86/mathops: clip constants used with shift instructions within inline assembly
Fixes assembling with binutil as >= 2.41
FFmpeg commit effadce6c756247ea8bae32dc13bb3e6f464f0eb.
Deals with: "Error: operand type mismatch for `shr'"
Fixes: QTBUG-116649
Change-Id: I094e8c23fed4a61fba3f1e3a9c73c016d129d830
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/495990
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
(cherry picked from commit 29354c7c7def7bdc66bcd25d401677fd9421f657)
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/509219
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/ffmpeg/libavcodec/x86/mathops.h b/qtwebengine/src/3rdparty/chromium/third_party/ffmpeg/libavcodec/x86/mathops.h
index 6298f5e..ca7e2df 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/ffmpeg/libavcodec/x86/mathops.h
+++ b/qtwebengine/src/3rdparty/chromium/third_party/ffmpeg/libavcodec/x86/mathops.h
@@ -35,12 +35,20 @@
static av_always_inline av_const int MULL(int a, int b, unsigned shift)
{
int rt, dummy;
+ if (__builtin_constant_p(shift))
__asm__ (
"imull %3 \n\t"
"shrdl %4, %%edx, %%eax \n\t"
:"=a"(rt), "=d"(dummy)
- :"a"(a), "rm"(b), "ci"((uint8_t)shift)
+ :"a"(a), "rm"(b), "i"(shift & 0x1F)
);
+ else
+ __asm__ (
+ "imull %3 \n\t"
+ "shrdl %4, %%edx, %%eax \n\t"
+ :"=a"(rt), "=d"(dummy)
+ :"a"(a), "rm"(b), "c"((uint8_t)shift)
+ );
return rt;
}
@@ -113,19 +121,31 @@
// avoid +32 for shift optimization (gcc should do that ...)
#define NEG_SSR32 NEG_SSR32
static inline int32_t NEG_SSR32( int32_t a, int8_t s){
+ if (__builtin_constant_p(s))
__asm__ ("sarl %1, %0\n\t"
: "+r" (a)
- : "ic" ((uint8_t)(-s))
+ : "i" (-s & 0x1F)
);
+ else
+ __asm__ ("sarl %1, %0\n\t"
+ : "+r" (a)
+ : "c" ((uint8_t)(-s))
+ );
return a;
}
#define NEG_USR32 NEG_USR32
static inline uint32_t NEG_USR32(uint32_t a, int8_t s){
+ if (__builtin_constant_p(s))
__asm__ ("shrl %1, %0\n\t"
: "+r" (a)
- : "ic" ((uint8_t)(-s))
+ : "i" (-s & 0x1F)
);
+ else
+ __asm__ ("shrl %1, %0\n\t"
+ : "+r" (a)
+ : "c" ((uint8_t)(-s))
+ );
return a;
}

View File

@ -0,0 +1,16 @@
qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp b/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp
index 3488120..120e47a 100644
--- a/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp
+++ b/qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp
@@ -472,7 +472,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
}
catch (const DeadlyImportError& e)
{
- if (!is64bits && (length > std::numeric_limits<std::uint32_t>::max())) {
+ if (!is64bits && (length > std::numeric_limits<uint32_t>::max())) {
throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", ai_to_string(version), ") of the FBX format. (", e.what(), ")");
}
throw;

View File

@ -0,0 +1,433 @@
qtbase/src/corelib/debug_script.py | 2 +-
qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/parseTestRecord.py | 2 +-
qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/test/test_monkeyYaml.py | 2 +-
qtwebengine/src/3rdparty/chromium/chrome/browser/resources/PRESUBMIT_test.py | 2 +-
qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/angle/scripts/angle_presubmit_utils_unittest.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/blink/PRESUBMIT.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/flatbuffers/src/python/flatbuffers/compat.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/jinja2/environment.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/mako/mako/compat.py | 2 +-
.../src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/converters/call_trees_test.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_test.py | 2 +-
.../src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_testing.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/api_test.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/conversion_test.py | 2 +-
.../src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/inspect_utils_test.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/templates_test.py | 2 +-
.../3rdparty/chromium/third_party/tflite/src/tensorflow/python/tools/api/generator/create_python_api_test.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py | 2 +-
qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py | 2 +-
qtwebengine/src/3rdparty/chromium/tools/sublime/ninja_options_script.py | 2 +-
qtwebengine/src/3rdparty/chromium/v8/third_party/test262-harness/src/parseTestRecord.py | 2 +-
31 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/qtbase/src/corelib/debug_script.py b/qtbase/src/corelib/debug_script.py
index f6207c6104..663c8e0ac1 100644
--- a/qtbase/src/corelib/debug_script.py
+++ b/qtbase/src/corelib/debug_script.py
@@ -3,7 +3,7 @@
import os
import sys
-import imp
+import importlib
from distutils.version import LooseVersion
diff --git a/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/parseTestRecord.py b/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/parseTestRecord.py
index 681039d34b..a1fe56fa05 100644
--- a/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/parseTestRecord.py
+++ b/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/parseTestRecord.py
@@ -16,7 +16,7 @@ import subprocess
import sys
import tempfile
import time
-import imp
+import importlib
# from TestCasePackagerConfig import *
diff --git a/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/test/test_monkeyYaml.py b/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/test/test_monkeyYaml.py
index 92d4e6139b..7a18e12ced 100644
--- a/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/test/test_monkeyYaml.py
+++ b/qtdeclarative/tests/auto/qml/ecmascripttests/test262/tools/packaging/test/test_monkeyYaml.py
@@ -7,7 +7,7 @@ import unittest
import os
import yaml
-import imp
+import importlib
# add parent dir to search path
import sys
diff --git a/qtwebengine/src/3rdparty/chromium/chrome/browser/resources/PRESUBMIT_test.py b/qtwebengine/src/3rdparty/chromium/chrome/browser/resources/PRESUBMIT_test.py
index c7412927c8..ad2caff318 100755
--- a/qtwebengine/src/3rdparty/chromium/chrome/browser/resources/PRESUBMIT_test.py
+++ b/qtwebengine/src/3rdparty/chromium/chrome/browser/resources/PRESUBMIT_test.py
@@ -5,7 +5,7 @@
import os
import sys
-import imp
+import importlib
import tempfile
import unittest
import PRESUBMIT
diff --git a/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py b/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py
index 5daee773ba..2d6b124162 100755
--- a/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py
+++ b/qtwebengine/src/3rdparty/chromium/components/resources/protobufs/binary_proto_generator.py
@@ -9,7 +9,7 @@
"""
from __future__ import print_function
import abc
-import imp
+import importlib
import optparse
import os
import re
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py
index bf626f5479..3fae129aaa 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil.py
@@ -3,7 +3,7 @@
# found in the LICENSE file.
import errno
-import imp
+import importlib
import os.path
import sys
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py
index ff5753a291..04fc34f742 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/fileutil_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import shutil
import sys
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py
index 32c884a8c0..e761faa54c 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/generator_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py
index 95a916db08..4331e2fbfa 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/generate/translate_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py
index 62798631db..28e9dbf705 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/ast_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py
index cba249b0f3..5a4051827a 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/conditional_features_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py
index 4a2fefc712..11a9879cb7 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
index cc17ae0253..bcc944f06b 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/lexer_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py
index bd72830e54..f2fdc9ae28 100644
--- a/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/mojo/public/tools/mojom/mojom/parse/parser_unittest.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import imp
+import importlib
import os.path
import sys
import unittest
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/angle/scripts/angle_presubmit_utils_unittest.py b/qtwebengine/src/3rdparty/chromium/third_party/angle/scripts/angle_presubmit_utils_unittest.py
index 1feb303a48..8428de61bb 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/angle/scripts/angle_presubmit_utils_unittest.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/angle/scripts/angle_presubmit_utils_unittest.py
@@ -6,7 +6,7 @@
angle_presubmit_utils_unittest.py: Top-level unittest script for ANGLE presubmit checks.
"""
-import imp
+import importlib
import os
import unittest
from angle_presubmit_utils import *
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/blink/PRESUBMIT.py b/qtwebengine/src/3rdparty/chromium/third_party/blink/PRESUBMIT.py
index ed4f38c67b..cac734cefa 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/blink/PRESUBMIT.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/blink/PRESUBMIT.py
@@ -7,7 +7,7 @@ See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into gcl.
"""
-import imp
+import importlib
import inspect
import os
import re
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/flatbuffers/src/python/flatbuffers/compat.py b/qtwebengine/src/3rdparty/chromium/third_party/flatbuffers/src/python/flatbuffers/compat.py
index 0244c9787e..f535afe99c 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/flatbuffers/src/python/flatbuffers/compat.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/flatbuffers/src/python/flatbuffers/compat.py
@@ -32,7 +32,7 @@ if PY3:
memoryview_type = memoryview
struct_bool_decl = "?"
else:
- import imp
+ import importlib
string_types = (unicode,)
if PY26 or PY27:
binary_types = (str,bytearray)
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/jinja2/environment.py b/qtwebengine/src/3rdparty/chromium/third_party/jinja2/environment.py
index 8430390eea..29212205bc 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/jinja2/environment.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/jinja2/environment.py
@@ -732,7 +732,7 @@ class Environment(object):
)
py_compile = False
else:
- import imp
+ import importlib
import marshal
py_header = imp.get_magic() + u"\xff\xff\xff\xff".encode("iso-8859-15")
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/mako/mako/compat.py b/qtwebengine/src/3rdparty/chromium/third_party/mako/mako/compat.py
index 06bb8d99f5..05089dc982 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/mako/mako/compat.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/mako/mako/compat.py
@@ -115,7 +115,7 @@ if py3k:
return module
else:
- import imp
+ import importlib
def load_module(module_id, path):
fp = open(path, "rb")
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/converters/call_trees_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/converters/call_trees_test.py
index a7dc683365..68b6804c78 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/converters/call_trees_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/converters/call_trees_test.py
@@ -14,7 +14,7 @@
# ==============================================================================
"""Tests for call_trees module."""
-import imp
+import importlib
from tensorflow.python.autograph.converters import call_trees
from tensorflow.python.autograph.converters import functions
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_test.py
index 81a7fde808..1370f900fd 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_test.py
@@ -14,7 +14,7 @@
# ==============================================================================
"""Tests for converter module."""
-import imp
+import importlib
from tensorflow.python.autograph.core import converter
from tensorflow.python.autograph.core import converter_testing
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_testing.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_testing.py
index b93cbb627b..452ec71f5b 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_testing.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/core/converter_testing.py
@@ -15,7 +15,7 @@
"""Base class for tests in this module."""
import contextlib
-import imp
+import importlib
import inspect
import sys
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/api_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/api_test.py
index 9a62d7c0d2..7ec4fa6dca 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/api_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/api_test.py
@@ -19,7 +19,7 @@ import collections
import contextlib
import functools
import gc
-import imp
+import importlib
import inspect
import os
import re
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/conversion_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/conversion_test.py
index 852af3efe7..6456c50446 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/conversion_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/impl/conversion_test.py
@@ -14,7 +14,7 @@
# ==============================================================================
"""Tests for conversion module."""
-import imp
+import importlib
import sys
import types
import weakref
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/inspect_utils_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/inspect_utils_test.py
index a50a64534a..ba0f31afa2 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/inspect_utils_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/inspect_utils_test.py
@@ -17,7 +17,7 @@
import abc
import collections
import functools
-import imp
+import importlib
import textwrap
import six
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/templates_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/templates_test.py
index 29f38d853a..7ca88fa371 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/templates_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/autograph/pyct/templates_test.py
@@ -14,7 +14,7 @@
# ==============================================================================
"""Tests for templates module."""
-import imp
+import importlib
from absl.testing import parameterized
import gast
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/tools/api/generator/create_python_api_test.py b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/tools/api/generator/create_python_api_test.py
index e46460574b..a40fea6568 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/tools/api/generator/create_python_api_test.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/tflite/src/tensorflow/python/tools/api/generator/create_python_api_test.py
@@ -14,7 +14,7 @@
# =============================================================================
"""Tests for create_python_api."""
-import imp
+import importlib
import sys
from tensorflow.python.platform import test
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py b/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py
index 73d1742714..ea77dd7647 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py
@@ -1,5 +1,5 @@
import importlib
-import imp
+import importlib
from .browsers import product_list
diff --git a/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py b/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py
index 6a744472b5..9175cb5d34 100644
--- a/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py
+++ b/qtwebengine/src/3rdparty/chromium/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py
@@ -1,6 +1,6 @@
import copy
import functools
-import imp
+import importlib
import io
import os
from collections import OrderedDict, defaultdict
diff --git a/qtwebengine/src/3rdparty/chromium/tools/sublime/ninja_options_script.py b/qtwebengine/src/3rdparty/chromium/tools/sublime/ninja_options_script.py
index 6912b6f3c0..7d851f7f76 100755
--- a/qtwebengine/src/3rdparty/chromium/tools/sublime/ninja_options_script.py
+++ b/qtwebengine/src/3rdparty/chromium/tools/sublime/ninja_options_script.py
@@ -16,7 +16,7 @@
from __future__ import print_function
-import imp
+import importlib
import optparse
import os
import pipes
diff --git a/qtwebengine/src/3rdparty/chromium/v8/third_party/test262-harness/src/parseTestRecord.py b/qtwebengine/src/3rdparty/chromium/v8/third_party/test262-harness/src/parseTestRecord.py
index 1c2aba80af..55260d697e 100644
--- a/qtwebengine/src/3rdparty/chromium/v8/third_party/test262-harness/src/parseTestRecord.py
+++ b/qtwebengine/src/3rdparty/chromium/v8/third_party/test262-harness/src/parseTestRecord.py
@@ -10,7 +10,7 @@ from __future__ import print_function
import os
import re
-import imp
+import importlib
from _monkeyYaml import load as yamlLoad

View File

@ -46,7 +46,7 @@ CMAKE_PREFIX_PATH="${QT_JAMI_PREFIX}/lib/cmake:${CMAKE_PREFIX_PATH}"
QT_MAJOR=6 QT_MAJOR=6
QT_MINOR=4 QT_MINOR=4
QT_PATCH=3 QT_PATCH=3
QT_RELEASE_PATCH=2 QT_RELEASE_PATCH=3
QT_MAJOR_MINOR=${QT_MAJOR}.${QT_MINOR} QT_MAJOR_MINOR=${QT_MAJOR}.${QT_MINOR}
QT_MAJOR_MINOR_PATCH=${QT_MAJOR}.${QT_MINOR}.${QT_PATCH} QT_MAJOR_MINOR_PATCH=${QT_MAJOR}.${QT_MINOR}.${QT_PATCH}
@ -105,18 +105,14 @@ if [ ! -f "${RPM_PATH}" ]; then
# Cache the built Qt RPM package. # Cache the built Qt RPM package.
if [[ "${DISTRIBUTION:0:4}" == "rhel" ]]; then if [[ "${DISTRIBUTION:0:4}" == "rhel" ]]; then
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.el8.x86_64.rpm "${RPM_PATH}" cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.el8.x86_64.rpm "${RPM_PATH}"
elif [[ "${DISTRIBUTION}" == "fedora_33" ]]; then
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc33.x86_64.rpm "${RPM_PATH}"
elif [[ "${DISTRIBUTION}" == "fedora_34" ]]; then
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc34.x86_64.rpm "${RPM_PATH}"
elif [[ "${DISTRIBUTION}" == "fedora_35" ]]; then
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc35.x86_64.rpm "${RPM_PATH}"
elif [[ "${DISTRIBUTION}" == "fedora_36" ]]; then elif [[ "${DISTRIBUTION}" == "fedora_36" ]]; then
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc36.x86_64.rpm "${RPM_PATH}" cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc36.x86_64.rpm "${RPM_PATH}"
elif [[ "${DISTRIBUTION}" == "fedora_37" ]]; then elif [[ "${DISTRIBUTION}" == "fedora_37" ]]; then
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc37.x86_64.rpm "${RPM_PATH}" cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc37.x86_64.rpm "${RPM_PATH}"
elif [[ "${DISTRIBUTION}" == "fedora_38" ]]; then elif [[ "${DISTRIBUTION}" == "fedora_38" ]]; then
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-$QT_MAJOR_MINOR_PATCH-*.fc38.x86_64.rpm "${RPM_PATH}" 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}"
else else
cp /root/rpmbuild/RPMS/x86_64/jami-libqt-*.rpm "${RPM_PATH}" cp /root/rpmbuild/RPMS/x86_64/jami-libqt-*.rpm "${RPM_PATH}"
fi fi

View File

@ -272,7 +272,7 @@ function package()
{ {
if [[ $DISTRIBUTION =~ debian|ubuntu|raspbian|guix-deb-pack ]]; then if [[ $DISTRIBUTION =~ debian|ubuntu|raspbian|guix-deb-pack ]]; then
package_deb package_deb
elif [[ $DISTRIBUTION =~ fedora|rhel|opensuse|guix-rpm-pack ]]; then elif [[ $DISTRIBUTION =~ alma|fedora|rhel|opensuse|guix-rpm-pack ]]; then
package_rpm package_rpm
elif [[ $DISTRIBUTION =~ snap ]]; then elif [[ $DISTRIBUTION =~ snap ]]; then
package_snap package_snap

View File

@ -125,6 +125,8 @@ else
if [[ "$OSTYPE" != "darwin"* ]]; then if [[ "$OSTYPE" != "darwin"* ]]; then
CONFIGURE_FLAGS+=" --disable-shared" CONFIGURE_FLAGS+=" --disable-shared"
fi fi
else
CONFIGURE_FLAGS+="--without-dbus"
fi fi
BUILD_TYPE="Release" BUILD_TYPE="Release"

View File

@ -36,5 +36,7 @@
<string>Jami requires to access your microphone to make calls and record audio</string> <string>Jami requires to access your microphone to make calls and record audio</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<true/> <true/>
<key>NSAppleEventsUsageDescription</key>
<string>Jami requires to monitor global key events for push-to-talk functionality.</string>
</dict> </dict>
</plist> </plist>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<path id="noun-connection-5025318" d="M18,6.3c1.2,0,2.2-1,2.2-2.1C20.1,3,19.2,2,18,2c-1.2,0-2.2,1-2.2,2.1c0,0.5,0.2,1.1,0.6,1.5
l-3.3,3.8c-0.8-0.6-2-0.5-2.7,0.2L7.3,7.1c0.5-0.8,0.2-1.9-0.6-2.4C5.9,4.2,4.8,4.5,4.3,5.3C3.8,6.1,4,7.2,4.9,7.7
C5.6,8.1,6.4,8,7,7.5l3.1,2.5c-0.5,0.8-0.4,1.9,0.3,2.6l-2.9,2.9c-1.1-0.7-2.5-0.4-3.2,0.7c-0.7,1.1-0.4,2.5,0.7,3.2
c1.1,0.7,2.5,0.4,3.2-0.7c0.6-0.9,0.5-2.1-0.3-2.9l2.9-2.9c0.3,0.2,0.7,0.3,1.2,0.3c0,0,0.1,0,0.1,0l0.8,4.8
c-1.1,0.3-1.7,1.4-1.4,2.5c0.3,1.1,1.4,1.7,2.5,1.4c1.1-0.3,1.7-1.4,1.4-2.5c-0.3-0.9-1-1.4-1.9-1.4c0,0-0.1,0-0.1,0l-0.8-4.8
c0.4-0.1,0.7-0.3,0.9-0.6l3.6,2.7c-0.4,0.8-0.2,1.8,0.6,2.2c0.8,0.4,1.8,0.2,2.2-0.6c0.4-0.8,0.2-1.8-0.6-2.2
c-0.6-0.4-1.4-0.3-1.9,0.2l-3.6-2.7c0.2-0.3,0.3-0.7,0.3-1.1c0-0.5-0.2-1.1-0.6-1.5l3.3-3.8C17.1,6.2,17.5,6.3,18,6.3L18,6.3z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<g id="noun-waiting-3611673" transform="translate(-13.64 -30.48)">
<path id="Path_278" d="M25.9,34.5c0.5,0,0.8-0.4,0.8-0.8c0-0.5-0.4-0.8-0.8-0.8c-0.5,0-0.8,0.4-0.8,0.8c0,0.2,0.1,0.4,0.2,0.6
C25.4,34.4,25.6,34.5,25.9,34.5z"/>
<path id="Path_279" d="M32.7,36.9c0.4-0.4,0.4-1.1,0-1.5c-0.4-0.4-1.1-0.4-1.5,0c-0.4,0.4-0.4,1.1,0,1.5c0.2,0.2,0.5,0.3,0.8,0.3
C32.2,37.2,32.5,37.1,32.7,36.9z"/>
<path id="Path_280" d="M34.5,41c-0.7,0-1.2,0.5-1.2,1.2s0.5,1.2,1.2,1.2c0.7,0,1.2-0.5,1.2-1.2c0-0.3-0.1-0.6-0.3-0.8
C35.1,41.1,34.8,41,34.5,41z"/>
<path id="Path_281" d="M31.9,47c-0.7,0-1.3,0.6-1.3,1.3c0,0.7,0.6,1.3,1.3,1.3c0.7,0,1.3-0.6,1.3-1.3c0-0.3-0.1-0.7-0.4-0.9
C32.6,47.1,32.3,47,31.9,47z"/>
<path id="Path_282" d="M25.9,49.4c-0.8,0-1.4,0.6-1.4,1.4c0,0.8,0.6,1.4,1.4,1.4c0.8,0,1.4-0.6,1.4-1.4c0-0.4-0.1-0.7-0.4-1
C26.6,49.5,26.2,49.4,25.9,49.4z"/>
<path id="Path_283" d="M18.7,47.2L18.7,47.2c-0.6,0.6-0.6,1.6,0,2.2c0.6,0.6,1.6,0.6,2.2,0c0.6-0.6,0.6-1.6,0-2.2
c-0.3-0.3-0.7-0.5-1.1-0.5C19.4,46.7,19,46.9,18.7,47.2z"/>
<path id="Path_284" d="M18.9,42.2c0-0.9-0.7-1.7-1.6-1.7s-1.7,0.7-1.7,1.6c0,0.9,0.7,1.7,1.6,1.7c0.4,0,0.9-0.2,1.2-0.5
C18.8,43,18.9,42.6,18.9,42.2z"/>
<path id="Path_285" d="M21.1,34.9c-0.7-0.3-1.5-0.1-1.9,0.6c-0.3,0.7-0.1,1.5,0.6,1.9c0.7,0.3,1.5,0.1,1.9-0.6
c0.1-0.2,0.2-0.5,0.1-0.7C21.8,35.5,21.5,35.1,21.1,34.9z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="43" height="52.655" viewBox="0 0 43 52.655">
<defs>
<clipPath id="clip-path">
<rect id="Rectangle_268" data-name="Rectangle 268" width="38" height="24" transform="translate(-0.407 0.083)" fill="#fff" stroke="#707070" stroke-width="1"/>
</clipPath>
</defs>
<g id="Icon_Donate" transform="translate(-22 -189.345)">
<rect id="Rectangle_267" data-name="Rectangle 267" width="43" height="10" rx="5" transform="translate(22 232)" fill="#9eb3c3"/>
<path id="Path_459" data-name="Path 459" d="M9.674,17.083,8.562,16.07C4.609,12.486,2,10.122,2,7.221A4.18,4.18,0,0,1,6.221,3,4.6,4.6,0,0,1,9.674,4.6,4.6,4.6,0,0,1,13.128,3a4.18,4.18,0,0,1,4.221,4.221c0,2.9-2.609,5.265-6.562,8.856Z" transform="translate(22.407 199.828)" fill="#ff0045" opacity="0.3"/>
<path id="Path_460" data-name="Path 460" d="M6.953,12.088l-.718-.654C3.684,9.122,2,7.6,2,5.724A2.7,2.7,0,0,1,4.724,3,2.966,2.966,0,0,1,6.953,4.035,2.966,2.966,0,0,1,9.182,3a2.7,2.7,0,0,1,2.724,2.724c0,1.872-1.684,3.4-4.235,5.716Z" transform="translate(45.571 186.345)" fill="#ff0045" opacity="0.16"/>
<g id="Mask_Group_38" data-name="Mask Group 38" transform="translate(24.407 213.918)" clip-path="url(#clip-path)">
<path id="Path_270" data-name="Path 270" d="M12.649,22.542l-1.544-1.406C5.621,16.163,2,12.883,2,8.857A5.8,5.8,0,0,1,7.857,3a6.377,6.377,0,0,1,4.792,2.226A6.377,6.377,0,0,1,17.442,3,5.8,5.8,0,0,1,23.3,8.857c0,4.025-3.621,7.306-9.105,12.289Z" transform="translate(5.992 5.54)" fill="#ff0045"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="21.5" height="20.112" viewBox="0 0 21.5 20.112">
<g id="favorite_black_24dp" transform="translate(-1.25 -2.25)">
<path id="Path_270" data-name="Path 270" d="M12,21.35l-1.45-1.32C5.4,15.36,2,12.28,2,8.5A5.447,5.447,0,0,1,7.5,3,5.988,5.988,0,0,1,12,5.09,5.988,5.988,0,0,1,16.5,3,5.447,5.447,0,0,1,22,8.5c0,3.78-3.4,6.86-8.55,11.54Z" fill="none" stroke="#03b9e9" stroke-width="1.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 448 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M39 38v-8.7q0-2.7-1.9-4.6-1.9-1.9-4.6-1.9H11.7l7.7 7.7-2.1 2.1L6 21.3 17.3 10l2.1 2.1-7.7 7.7h20.8q3.9 0 6.7 2.775Q42 25.35 42 29.3V38Z"/></svg>

Before

Width:  |  Height:  |  Size: 216 B

View File

@ -0,0 +1,4 @@
<svg id="reply_black_24dp" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path id="Path_333" data-name="Path 333" d="M0,0H24V24H0Z" fill="none"/>
<path id="Path_334" data-name="Path 334" d="M10,9V5L3,12l7,7V14.9c5,0,8.5,1.6,11,5.1C20,15,17,10,10,9Z" fill="none" stroke="#000" stroke-linecap="round" stroke-width="1.5"/>
</svg>

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 KiB

View File

@ -65,6 +65,15 @@ ApplicationWindow {
} }
} }
header: Loader {
active: true
sourceComponent: GenericErrorsRow {
id: genericError
text: CurrentAccount.enabled ? JamiStrings.noNetworkConnectivity : JamiStrings.disabledAccount
height: visible? JamiTheme.chatViewHeaderPreferredHeight : 0
}
}
Rectangle { Rectangle {
id: focusOverlay id: focusOverlay
objectName: "focusOverlay" objectName: "focusOverlay"
@ -259,7 +268,7 @@ ApplicationWindow {
} }
function presentUpdateInfoDialog(infoText) { function presentUpdateInfoDialog(infoText) {
viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", { return viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
"title": JamiStrings.updateDialogTitle, "title": JamiStrings.updateDialogTitle,
"infoText": infoText, "infoText": infoText,
"buttonTitles": [JamiStrings.optionOk], "buttonTitles": [JamiStrings.optionOk],
@ -268,6 +277,36 @@ ApplicationWindow {
}); });
} }
function presentUpdateConfirmInstallDialog(switchToBeta=false) {
return viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
"title": JamiStrings.updateDialogTitle,
"infoText": switchToBeta ? JamiStrings.confirmBeta : JamiStrings.updateFound,
"buttonTitles": [JamiStrings.optionUpgrade, JamiStrings.optionLater],
"buttonStyles": [SimpleMessageDialog.ButtonStyle.TintedBlue, SimpleMessageDialog.ButtonStyle.TintedBlue],
"buttonCallBacks": [function () {
AppVersionManager.applyUpdates(switchToBeta);
}]
});
}
function translateErrorToString(error) {
switch (error) {
case NetworkManager.DISCONNECTED:
return JamiStrings.networkDisconnected;
case NetworkManager.CONTENT_NOT_FOUND:
return JamiStrings.contentNotFoundError;
case NetworkManager.ACCESS_DENIED:
return JamiStrings.accessError;
case NetworkManager.SSL_ERROR:
return JamiStrings.updateSSLError;
case NetworkManager.CANCELED:
return JamiStrings.updateDownloadCanceled;
case NetworkManager.NETWORK_ERROR:
default:
return JamiStrings.updateNetworkError;
}
}
Connections { Connections {
target: AppVersionManager target: AppVersionManager
@ -279,41 +318,22 @@ ApplicationWindow {
function onUpdateCheckReplyReceived(ok, found) { function onUpdateCheckReplyReceived(ok, found) {
if (!ok) { if (!ok) {
// Show an error dialog describing that we could not successfully check for an update.
presentUpdateInfoDialog(JamiStrings.updateCheckError); presentUpdateInfoDialog(JamiStrings.updateCheckError);
return; return;
} }
if (!found) { if (!found) {
// Show a dialog describing that no update was found.
presentUpdateInfoDialog(JamiStrings.updateNotFound); presentUpdateInfoDialog(JamiStrings.updateNotFound);
} else { } else {
viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", { // Show a dialog describing that an update were found, and offering to install it.
"title": JamiStrings.updateDialogTitle, presentUpdateConfirmInstallDialog()
"infoText": JamiStrings.updateFound,
"buttonTitles": [JamiStrings.optionUpgrade, JamiStrings.optionLater],
"buttonStyles": [SimpleMessageDialog.ButtonStyle.TintedBlue, SimpleMessageDialog.ButtonStyle.TintedBlue],
"buttonCallBacks": [function () {
AppVersionManager.applyUpdates();
}]
});
} }
} }
function onUpdateErrorOccurred(error) { function onNetworkErrorOccurred(error) {
presentUpdateInfoDialog((function () { var errorStr = translateErrorToString(error);
switch (error) { presentUpdateInfoDialog(errorStr);
case NetworkManager.ACCESS_DENIED:
return JamiStrings.genericError;
case NetworkManager.DISCONNECTED:
return JamiStrings.networkDisconnected;
case NetworkManager.NETWORK_ERROR:
return JamiStrings.updateNetworkError;
case NetworkManager.SSL_ERROR:
return JamiStrings.updateSSLError;
case NetworkManager.CANCELED:
return JamiStrings.updateDownloadCanceled;
default:
return {};
}
})());
} }
} }

View File

@ -74,7 +74,7 @@ QtObject {
// Create, present, and return a dialog object. // Create, present, and return a dialog object.
function presentDialog(parent, path, props = {}) { function presentDialog(parent, path, props = {}) {
// Open the dialog once the object is created // Open the dialog once the object is created
return viewManager.createView(path, parent, function (obj) { return viewManager.createUniqueView(path, parent, function (obj) {
const doneCb = function () { const doneCb = function () {
viewManager.destroyView(path); viewManager.destroyView(path);
}; };

View File

@ -36,36 +36,70 @@ QtObject {
} }
} }
// Create a view from a path only if it doesn't already exist. This is used
// by the view coordinator to create views that are not self-destructing
// (main views) and only exist once per instance of the app.
function createView(path, parent = null, cb = null, props = {}) { function createView(path, parent = null, cb = null, props = {}) {
if (views.hasOwnProperty(path)) { const component = Qt.createComponent(Qt.resolvedUrl(path));
// an instance of <path> already exists return createViewFromComponent(component, path, parent, cb, props);
}
// Create a new view. Useful when we want to create multiple views that are
// self-destructing (dialogs).
function createUniqueView(path, parent = null, cb = null, props = {}) {
const component = Qt.createComponent(Qt.resolvedUrl(path));
return createViewFromComponent(component, getViewName(path), parent, cb,
props);
}
// Create a new view from a component. If a view with the same path already
// exists, it is returned instead.
function createViewFromComponent(component, viewName, parent = null,
cb = null, props = {}) {
if (views.hasOwnProperty(viewName)) {
// an instance of the view already exists
if (cb !== null) { if (cb !== null) {
cb(views[path]) cb(views[viewName])
} }
return views[path] return views[viewName]
} }
const component = Qt.createComponent(Qt.resolvedUrl(path))
if (component.status === Component.Ready) { if (component.status === Component.Ready) {
const obj = component.createObject(parent, props) const obj = component.createObject(parent, props)
if (obj === null) { if (obj === null) {
print("error creating object") console.error("error creating object")
return null return null
} }
views[path] = obj views[viewName] = obj
// Set the view name to the object name if it has one. // Set the view name to the object name if it has one.
const viewName = obj.objectName.toString() !== '' ? obj.objectName : path.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "") const friendlyName = obj.objectName.toString() !== '' ?
viewPaths[viewName] = path obj.objectName :
viewName.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "")
viewPaths[friendlyName] = viewName
if (cb !== null) { if (cb !== null) {
cb(obj) cb(obj)
} }
return views[path] return views[viewName]
} }
print("error creating component", path) console.error("error creating component", component.url)
console.error(component.errorString()) console.error(component.errorString())
Qt.exit(1) Qt.exit(1)
return null return null
} }
// Finds a unique view name for a given path by appending a number to the
// base name. For example, if a view named "MyView" already exists, the next
// view will be named "MyView_1".
function getViewName(path) {
const baseName = path.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "")
let viewName = baseName
let suffix = 1
while (views.hasOwnProperty(viewName)) {
viewName = `${baseName}_${suffix}`
suffix++
}
return viewName
}
function destroyView(path) { function destroyView(path) {
// The view may already have been destroyed. // The view may already have been destroyed.
if (!views.hasOwnProperty(path)) { if (!views.hasOwnProperty(path)) {

View File

@ -33,6 +33,7 @@
extern const QString defaultDownloadPath; extern const QString defaultDownloadPath;
// clang-format off // clang-format off
#ifdef APPSTORE
#define KEYS \ #define KEYS \
X(MinimizeOnClose, false) \ X(MinimizeOnClose, false) \
X(DownloadPath, defaultDownloadPath) \ X(DownloadPath, defaultDownloadPath) \
@ -46,7 +47,7 @@ extern const QString defaultDownloadPath;
X(AppTheme, "System") \ X(AppTheme, "System") \
X(BaseZoom, 1.0) \ X(BaseZoom, 1.0) \
X(ParticipantsSide, false) \ X(ParticipantsSide, false) \
X(HideSelf, false) \ X(HideSelf, true) \
X(HideSpectators, false) \ X(HideSpectators, false) \
X(AutoUpdate, true) \ X(AutoUpdate, true) \
X(PluginAutoUpdate, false) \ X(PluginAutoUpdate, false) \
@ -57,12 +58,53 @@ extern const QString defaultDownloadPath;
X(WindowState, QWindow::AutomaticVisibility) \ X(WindowState, QWindow::AutomaticVisibility) \
X(EnableExperimentalSwarm, false) \ X(EnableExperimentalSwarm, false) \
X(LANG, "SYSTEM") \ X(LANG, "SYSTEM") \
X(PluginStoreEndpoint, "https://plugins.jami.net") \
X(PositionShareDuration, 15) \ X(PositionShareDuration, 15) \
X(PositionShareLimit, true) \ X(PositionShareLimit, true) \
X(FlipSelf, true) \ X(FlipSelf, true) \
X(ShowMardownOption, false) \ X(ShowMardownOption, false) \
X(ChatViewEnterIsNewLine, false) \ X(ChatViewEnterIsNewLine, false) \
X(ShowSendOption, false) X(ShowSendOption, false) \
X(EnablePtt, false) \
X(pttKey, 36)
#else
#define KEYS \
X(MinimizeOnClose, false) \
X(DownloadPath, defaultDownloadPath) \
X(ScreenshotPath, {}) \
X(EnableNotifications, true) \
X(EnableTypingIndicator, true) \
X(EnableReadReceipt, true) \
X(AcceptTransferBelow, 20) \
X(AutoAcceptFiles, true) \
X(DisplayHyperlinkPreviews, true) \
X(AppTheme, "System") \
X(BaseZoom, 1.0) \
X(ParticipantsSide, false) \
X(HideSelf, true) \
X(HideSpectators, false) \
X(AutoUpdate, true) \
X(PluginAutoUpdate, false) \
X(StartMinimized, false) \
X(ShowChatviewHorizontally, true) \
X(NeverShowMeAgain, false) \
X(WindowGeometry, QRectF(qQNaN(), qQNaN(), 0., 0.)) \
X(WindowState, QWindow::AutomaticVisibility) \
X(EnableExperimentalSwarm, false) \
X(LANG, "SYSTEM") \
X(PluginStoreEndpoint, "https://plugins.jami.net") \
X(PositionShareDuration, 15) \
X(PositionShareLimit, true) \
X(FlipSelf, true) \
X(ShowMardownOption, false) \
X(ChatViewEnterIsNewLine, false) \
X(ShowSendOption, false) \
X(DonationVisibleDate, "2023-11-01 05:00") \
X(IsDonationVisible, true) \
X(DonationEndDate, "2024-01-01 00:00") \
X(EnablePtt, false) \
X(pttKey, 36)
#endif
/* /*
* A class to expose settings keys in both c++ and QML. * A class to expose settings keys in both c++ and QML.

View File

@ -44,7 +44,6 @@ struct AppVersionManager::Impl : public QObject
, parent_(parent) , parent_(parent)
, lrcInstance_(instance) , lrcInstance_(instance)
, baseUrlString_(url.isEmpty() ? downloadUrl : url) , baseUrlString_(url.isEmpty() ? downloadUrl : url)
, tempPath_(QDir::tempPath())
, updateTimer_(new QTimer(this)) , updateTimer_(new QTimer(this))
{ {
connect(updateTimer_, &QTimer::timeout, this, [this] { connect(updateTimer_, &QTimer::timeout, this, [this] {
@ -62,11 +61,11 @@ struct AppVersionManager::Impl : public QObject
connect(&parent_, connect(&parent_,
&NetworkManager::errorOccurred, &NetworkManager::errorOccurred,
&parent_, &parent_,
&AppVersionManager::updateErrorOccurred); &AppVersionManager::networkErrorOccurred);
cleanUpdateFiles(); cleanUpdateFiles();
QUrl versionUrl {isBeta ? QUrl::fromUserInput(baseUrlString_ + betaVersionSubUrl) const QUrl versionUrl {isBeta ? QUrl::fromUserInput(baseUrlString_ + betaVersionSubUrl)
: QUrl::fromUserInput(baseUrlString_ + versionSubUrl)}; : QUrl::fromUserInput(baseUrlString_ + versionSubUrl)};
parent_.sendGetRequest(versionUrl, [this, quiet](const QByteArray& latestVersionString) { parent_.sendGetRequest(versionUrl, [this, quiet](const QByteArray& latestVersionString) {
if (latestVersionString.isEmpty()) { if (latestVersionString.isEmpty()) {
qWarning() << "Error checking version"; qWarning() << "Error checking version";
@ -76,14 +75,15 @@ struct AppVersionManager::Impl : public QObject
} }
auto currentVersion = QString(VERSION_STRING).toULongLong(); auto currentVersion = QString(VERSION_STRING).toULongLong();
auto latestVersion = latestVersionString.toULongLong(); auto latestVersion = latestVersionString.toULongLong();
qDebug() << "latest: " << latestVersion << " current: " << currentVersion; const QString channelStr = isBeta ? "beta" : "stable";
if (latestVersion > currentVersion) { const auto newVersionFound = latestVersion > currentVersion;
qDebug() << "New version found"; qInfo().noquote() << "--------- Version info ------------"
<< QString("\n - Current: %1 (%2)").arg(currentVersion).arg(channelStr);
if (newVersionFound) {
qDebug() << " - Latest: " << latestVersion;
Q_EMIT parent_.updateCheckReplyReceived(true, true); Q_EMIT parent_.updateCheckReplyReceived(true, true);
} else { } else if (!quiet) {
qDebug() << "No new version found"; Q_EMIT parent_.updateCheckReplyReceived(true, false);
if (!quiet)
Q_EMIT parent_.updateCheckReplyReceived(true, false);
} }
}); });
}; };
@ -94,20 +94,21 @@ struct AppVersionManager::Impl : public QObject
connect(&parent_, connect(&parent_,
&NetworkManager::errorOccurred, &NetworkManager::errorOccurred,
&parent_, &parent_,
&AppVersionManager::updateErrorOccurred); &AppVersionManager::networkErrorOccurred);
const QUrl downloadUrl {(beta || isBeta) const QUrl downloadUrl {(beta || isBeta)
? QUrl::fromUserInput(baseUrlString_ + betaMsiSubUrl) ? QUrl::fromUserInput(baseUrlString_ + betaMsiSubUrl)
: QUrl::fromUserInput(baseUrlString_ + msiSubUrl)}; : QUrl::fromUserInput(baseUrlString_ + msiSubUrl)};
int uuid = parent_.downloadFile( const auto lastDownloadReplyId = parent_.replyId_;
parent_.replyId_ = parent_.downloadFile(
downloadUrl, downloadUrl,
*(parent_.replyId_), lastDownloadReplyId,
[this, downloadUrl](bool success, const QString& errorMessage) { [downloadUrl](bool success, const QString& errorMessage) {
Q_UNUSED(success) Q_UNUSED(success)
Q_UNUSED(errorMessage) Q_UNUSED(errorMessage)
const QProcess process; QProcess process;
auto basePath = tempPath_ + QDir::separator(); auto basePath = QDir::tempPath() + QDir::separator();
auto msiPath = QDir::toNativeSeparators(basePath + downloadUrl.fileName()); auto msiPath = QDir::toNativeSeparators(basePath + downloadUrl.fileName());
auto logPath = QDir::toNativeSeparators(basePath + "jami_x64_install.log"); auto logPath = QDir::toNativeSeparators(basePath + "jami_x64_install.log");
process.startDetached("msiexec", process.startDetached("msiexec",
@ -116,13 +117,12 @@ struct AppVersionManager::Impl : public QObject
<< "WIXNONUILAUNCH=1" << "WIXNONUILAUNCH=1"
<< "/L*V" << logPath); << "/L*V" << logPath);
}, },
tempPath_); QDir::tempPath());
parent_.replyId_.reset(&uuid);
}; };
void cancelUpdate() void cancelUpdate()
{ {
parent_.cancelDownload(*(parent_.replyId_)); parent_.cancelDownload(parent_.replyId_);
}; };
void setAutoUpdateCheck(bool state) void setAutoUpdateCheck(bool state)
@ -138,7 +138,7 @@ struct AppVersionManager::Impl : public QObject
void cleanUpdateFiles() void cleanUpdateFiles()
{ {
// Delete all logs and msi in the temporary directory before launching. // Delete all logs and msi in the temporary directory before launching.
QString dir = QDir::tempPath(); const QString dir = QDir::tempPath();
QDir log_dir(dir, {"jami*.log"}); QDir log_dir(dir, {"jami*.log"});
for (const QString& filename : log_dir.entryList()) { for (const QString& filename : log_dir.entryList()) {
log_dir.remove(filename); log_dir.remove(filename);
@ -157,7 +157,6 @@ struct AppVersionManager::Impl : public QObject
LRCInstance* lrcInstance_ {nullptr}; LRCInstance* lrcInstance_ {nullptr};
QString baseUrlString_; QString baseUrlString_;
QString tempPath_;
QTimer* updateTimer_; QTimer* updateTimer_;
}; };
@ -166,13 +165,13 @@ AppVersionManager::AppVersionManager(const QString& url,
LRCInstance* instance, LRCInstance* instance,
QObject* parent) QObject* parent)
: NetworkManager(cm, parent) : NetworkManager(cm, parent)
, replyId_(new int(0)) , replyId_(0)
, pimpl_(std::make_unique<Impl>(url, instance, *this)) , pimpl_(std::make_unique<Impl>(url, instance, *this))
{} {}
AppVersionManager::~AppVersionManager() AppVersionManager::~AppVersionManager()
{ {
cancelDownload(*replyId_); cancelDownload(replyId_);
} }
void void

View File

@ -47,10 +47,10 @@ Q_SIGNALS:
void appCloseRequested(); void appCloseRequested();
void updateCheckReplyReceived(bool ok, bool found = false); void updateCheckReplyReceived(bool ok, bool found = false);
void updateDownloadProgressChanged(qint64 bytesRead, qint64 totalBytes); void updateDownloadProgressChanged(qint64 bytesRead, qint64 totalBytes);
void updateErrorOccurred(const NetworkManager::GetError& error); void networkErrorOccurred(const NetworkManager::GetError& error);
private: private:
QScopedPointer<int> replyId_; int replyId_;
struct Impl; struct Impl;
friend struct Impl; friend struct Impl;
std::unique_ptr<Impl> pimpl_; std::unique_ptr<Impl> pimpl_;

View File

@ -195,8 +195,28 @@ AvAdapter::shareFile(const QString& filePath)
auto callId = lrcInstance_->getCurrentCallId(); auto callId = lrcInstance_->getCurrentCallId();
if (!callId.isEmpty()) { if (!callId.isEmpty()) {
muteCamera_ = !isCapturing(); muteCamera_ = !isCapturing();
lrcInstance_->getCurrentCallModel() auto resource = QString("%1%2%3")
->addMedia(callId, filePath, lrc::api::CallModel::MediaRequestType::FILESHARING); .arg(libjami::Media::VideoProtocolPrefix::FILE)
.arg(libjami::Media::VideoProtocolPrefix::SEPARATOR)
.arg(QUrl(filePath).toLocalFile());
Utils::oneShotConnect(&lrcInstance_->avModel(),
&lrc::api::AVModel::fileOpened,
this,
[this, callId, filePath, resource](bool hasAudio, bool hasVideo) {
// TODO: allow audio only sharing
if (hasVideo) { // only start sharing if video is available
lrcInstance_->avModel().pausePlayer(resource, false);
lrcInstance_->avModel().setAutoRestart(resource, true);
lrcInstance_->getCurrentCallModel()
->addMedia(callId, filePath, lrc::api::CallModel::MediaRequestType::FILESHARING, false, hasAudio);
} else {
// Close media player because we are not going to start sharing
lrcInstance_->avModel().closeMediaPlayer(resource);
}
});
lrcInstance_->avModel().createMediaPlayer(resource);
} }
} }

View File

@ -7,6 +7,7 @@
* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* Author: Capucine Berthet <capucine.berthet@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -47,7 +48,7 @@ CallAdapter::CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject*
timer = new QTimer(this); timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &CallAdapter::updateAdvancedInformation); connect(timer, &QTimer::timeout, this, &CallAdapter::updateAdvancedInformation);
overlayModel_.reset(new CallOverlayModel(lrcInstance_, this)); overlayModel_.reset(new CallOverlayModel(lrcInstance_, listener_, this));
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, overlayModel_.get(), "CallOverlayModel"); QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, overlayModel_.get(), "CallOverlayModel");
accountId_ = lrcInstance_->get_currentAccountId(); accountId_ = lrcInstance_->get_currentAccountId();
@ -97,6 +98,65 @@ CallAdapter::CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject*
&LRCInstance::selectedConvUidChanged, &LRCInstance::selectedConvUidChanged,
this, this,
&CallAdapter::saveConferenceSubcalls); &CallAdapter::saveConferenceSubcalls);
#ifdef HAVE_GLOBAL_PTT
connectPtt();
#endif
}
CallAdapter::~CallAdapter()
{
#ifdef HAVE_GLOBAL_PTT
disconnectPtt();
#endif
}
void
CallAdapter::connectPtt()
{
#ifdef HAVE_GLOBAL_PTT
if (listener_->getPttState()) {
QObject::connect(
listener_,
&PTTListener::pttKeyPressed,
this,
[this]() {
const auto callId
= lrcInstance_->getCallIdForConversationUid(lrcInstance_->get_selectedConvUid(),
accountId_);
try {
isMicrophoneMuted_ = isMuted(callId);
if (isMicrophoneMuted_)
muteAudioToggle();
} catch (const std::exception& e) {
qWarning() << e.what();
}
},
Qt::QueuedConnection);
QObject::connect(
listener_,
&PTTListener::pttKeyReleased,
this,
[this]() {
if (isMicrophoneMuted_) {
muteAudioToggle();
}
},
Qt::QueuedConnection);
}
#endif
}
void
CallAdapter::disconnectPtt()
{
#ifdef HAVE_GLOBAL_PTT
if (listener_->getPttState()) {
QObject::disconnect(listener_, &PTTListener::pttKeyPressed, this, nullptr);
QObject::disconnect(listener_, &PTTListener::pttKeyReleased, this, nullptr);
}
#endif
} }
void void
@ -172,6 +232,12 @@ CallAdapter::onCallStarted(const QString& callId)
// update call Information list by adding the new information related to the callId // update call Information list by adding the new information related to the callId
callInformationListModel_->addElement( callInformationListModel_->addElement(
qMakePair(callId, callModel->advancedInformationForCallId(callId))); qMakePair(callId, callModel->advancedInformationForCallId(callId)));
if (listener_->getPttState()){
#ifdef HAVE_GLOBAL_PTT
listener_->startListening();
toMute += callId;
#endif
}
} }
void void
@ -181,6 +247,10 @@ CallAdapter::onCallEnded(const QString& callId)
return; return;
// update call Information list by removing information related to the callId // update call Information list by removing information related to the callId
callInformationListModel_->removeElement(callId); callInformationListModel_->removeElement(callId);
#ifdef HAVE_GLOBAL_PTT
if (listener_->getPttState() && !hasCall_)
listener_->stopListening();
#endif
} }
void void
@ -271,6 +341,15 @@ CallAdapter::onCallStatusChanged(const QString& callId, int code)
} }
} }
void
CallAdapter::onCallInfosChanged(const QString& accountId, const QString& callId)
{
Q_UNUSED(accountId)
auto mute = toMute.remove(callId);
if (mute && listener_->getPttState())
muteAudioToggle();
}
void void
CallAdapter::onCallAddedToConference(const QString& callId, const QString& confId) CallAdapter::onCallAddedToConference(const QString& callId, const QString& confId)
{ {
@ -494,6 +573,12 @@ CallAdapter::connectCallModel(const QString& accountId)
QOverload<const QString&, int>::of(&CallAdapter::onCallStatusChanged), QOverload<const QString&, int>::of(&CallAdapter::onCallStatusChanged),
Qt::UniqueConnection); Qt::UniqueConnection);
connect(accInfo.callModel.get(),
&CallModel::callInfosChanged,
this,
&CallAdapter::onCallInfosChanged,
Qt::UniqueConnection);
connect(accInfo.callModel.get(), connect(accInfo.callModel.get(),
&CallModel::callAddedToConference, &CallModel::callAddedToConference,
this, this,
@ -816,6 +901,23 @@ CallAdapter::holdThisCallToggle()
} }
} }
bool
CallAdapter::isMuted(const QString& callId)
{
if (!(callId.isEmpty() || !lrcInstance_->getCurrentCallModel()->hasCall(callId))) {
auto* callModel = lrcInstance_->getCurrentCallModel();
if (callModel->hasCall(callId)) {
const auto callInfo = lrcInstance_->getCurrentCallModel()->getCall(callId);
auto mute = false;
for (const auto& m : callInfo.mediaList)
if (m[libjami::Media::MediaAttributeKey::LABEL] == "audio_0")
mute = m[libjami::Media::MediaAttributeKey::MUTED] == TRUE_STR;
return mute;
}
}
throw std::runtime_error("CallAdapter::isMuted: callId is empty or call does not exist");
}
void void
CallAdapter::muteAudioToggle() CallAdapter::muteAudioToggle()
{ {
@ -825,13 +927,10 @@ CallAdapter::muteAudioToggle()
return; return;
} }
auto* callModel = lrcInstance_->getCurrentCallModel(); auto* callModel = lrcInstance_->getCurrentCallModel();
if (callModel->hasCall(callId)) { try {
const auto callInfo = lrcInstance_->getCurrentCallModel()->getCall(callId); callModel->muteMedia(callId, "audio_0", !isMuted(callId));
auto mute = false; } catch (const std::exception& e) {
for (const auto& m : callInfo.mediaList) qWarning() << e.what();
if (m[libjami::Media::MediaAttributeKey::LABEL] == "audio_0")
mute = m[libjami::Media::MediaAttributeKey::MUTED] == FALSE_STR;
callModel->muteMedia(callId, "audio_0", mute);
} }
} }

View File

@ -25,6 +25,10 @@
#include "screensaver.h" #include "screensaver.h"
#include "calloverlaymodel.h" #include "calloverlaymodel.h"
#ifdef HAVE_GLOBAL_PTT
#include "pttlistener.h"
#endif
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QVariant> #include <QVariant>
@ -46,7 +50,7 @@ public:
Q_ENUM(MuteStates) Q_ENUM(MuteStates)
explicit CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* parent = nullptr); explicit CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* parent = nullptr);
~CallAdapter() = default; ~CallAdapter();
public: public:
Q_INVOKABLE void startTimerInformation(); Q_INVOKABLE void startTimerInformation();
@ -76,6 +80,9 @@ public:
Q_INVOKABLE void holdThisCallToggle(); Q_INVOKABLE void holdThisCallToggle();
Q_INVOKABLE void recordThisCallToggle(); Q_INVOKABLE void recordThisCallToggle();
Q_INVOKABLE void muteAudioToggle(); Q_INVOKABLE void muteAudioToggle();
Q_INVOKABLE bool isMuted(const QString& callId);
Q_INVOKABLE void connectPtt();
Q_INVOKABLE void disconnectPtt();
Q_INVOKABLE void muteCameraToggle(); Q_INVOKABLE void muteCameraToggle();
Q_INVOKABLE bool isRecordingThisCall(); Q_INVOKABLE bool isRecordingThisCall();
Q_INVOKABLE void muteParticipant(const QString& accountUri, Q_INVOKABLE void muteParticipant(const QString& accountUri,
@ -109,6 +116,7 @@ public Q_SLOTS:
void onCallAddedToConference(const QString& callId, const QString& confId); void onCallAddedToConference(const QString& callId, const QString& confId);
void onCallStarted(const QString& callId); void onCallStarted(const QString& callId);
void onCallEnded(const QString& callId); void onCallEnded(const QString& callId);
void onCallInfosChanged(const QString& accountId, const QString& callId);
private: private:
void showNotification(const QString& accountId, const QString& convUid); void showNotification(const QString& accountId, const QString& convUid);
@ -121,6 +129,9 @@ private:
SystemTray* systemTray_; SystemTray* systemTray_;
QScopedPointer<CallOverlayModel> overlayModel_; QScopedPointer<CallOverlayModel> overlayModel_;
VectorString currentConfSubcalls_; VectorString currentConfSubcalls_;
std::unique_ptr<CallInformationListModel> callInformationListModel_; std::unique_ptr<CallInformationListModel> callInformationListModel_;
PTTListener* listener_ = new PTTListener(systemTray_->getSettingsManager());
bool isMicrophoneMuted_ = true;
QSet<QString> toMute;
}; };

View File

@ -22,6 +22,7 @@
#include <QEvent> #include <QEvent>
#include <QMouseEvent> #include <QMouseEvent>
#include <QQuickWindow> #include <QQuickWindow>
#include <QKeyEvent>
IndexRangeFilterProxyModel::IndexRangeFilterProxyModel(QAbstractListModel* parent) IndexRangeFilterProxyModel::IndexRangeFilterProxyModel(QAbstractListModel* parent)
: QSortFilterProxyModel(parent) : QSortFilterProxyModel(parent)
@ -74,10 +75,10 @@ PendingConferenceesListModel::data(const QModelIndex& index, int role) const
using namespace PendingConferences; using namespace PendingConferences;
// WARNING: not swarm ready // WARNING: not swarm ready
lrc::api::call::Status callStatus;
QString pendingConferenceeCallId; QString pendingConferenceeCallId;
QString pendingConferenceeContactUri; QString pendingConferenceeContactUri;
ContactModel* contactModel {nullptr}; ContactModel* contactModel {nullptr};
lrc::api::call::Status callStatus;
try { try {
auto callModel = lrcInstance_->getCurrentCallModel(); auto callModel = lrcInstance_->getCurrentCallModel();
auto currentPendingConferenceeInfo = callModel->getPendingConferencees().at(index.row()); auto currentPendingConferenceeInfo = callModel->getPendingConferencees().at(index.row());
@ -268,7 +269,7 @@ CallControlListModel::clearData()
data_.clear(); data_.clear();
} }
CallOverlayModel::CallOverlayModel(LRCInstance* instance, QObject* parent) CallOverlayModel::CallOverlayModel(LRCInstance* instance, PTTListener* listener, QObject* parent)
: QObject(parent) : QObject(parent)
, lrcInstance_(instance) , lrcInstance_(instance)
, primaryModel_(new CallControlListModel(this)) , primaryModel_(new CallControlListModel(this))
@ -283,6 +284,10 @@ CallOverlayModel::CallOverlayModel(LRCInstance* instance, QObject* parent)
this, this,
&CallOverlayModel::setControlRanges); &CallOverlayModel::setControlRanges);
overflowVisibleModel_->setFilterRole(CallControl::Role::UrgentCount); overflowVisibleModel_->setFilterRole(CallControl::Role::UrgentCount);
#ifndef HAVE_GLOBAL_PTT
listener_ = listener;
#endif
} }
void void
@ -386,6 +391,19 @@ CallOverlayModel::eventFilter(QObject* object, QEvent* event)
} }
} }
} }
#ifndef HAVE_GLOBAL_PTT
else if (event->type() == QEvent::KeyPress && listener_->getPttState()) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == listener_->getCurrentKey() && !keyEvent->isAutoRepeat()) {
Q_EMIT pttKeyPressed();
}
} else if (event->type() == QEvent::KeyRelease && listener_->getPttState()) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == listener_->getCurrentKey() && !keyEvent->isAutoRepeat()) {
Q_EMIT pttKeyReleased();
}
}
#endif
return QObject::eventFilter(object, event); return QObject::eventFilter(object, event);
} }

View File

@ -21,6 +21,9 @@
#include "lrcinstance.h" #include "lrcinstance.h"
#include "qtutils.h" #include "qtutils.h"
#include "mainapplication.h"
#include "pttlistener.h"
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QObject> #include <QObject>
@ -36,7 +39,7 @@
namespace CallControl { namespace CallControl {
Q_NAMESPACE Q_NAMESPACE
enum Role { ItemAction = Qt::UserRole + 1, UrgentCount, Enabled}; enum Role { ItemAction = Qt::UserRole + 1, UrgentCount, Enabled };
Q_ENUM_NS(Role) Q_ENUM_NS(Role)
struct Item struct Item
@ -121,7 +124,7 @@ class CallOverlayModel : public QObject
QML_PROPERTY(int, overflowIndex) QML_PROPERTY(int, overflowIndex)
public: public:
CallOverlayModel(LRCInstance* instance, QObject* parent = nullptr); CallOverlayModel(LRCInstance* instance, PTTListener* listener, QObject* parent = nullptr);
Q_INVOKABLE void addPrimaryControl(const QVariant& action, bool enabled); Q_INVOKABLE void addPrimaryControl(const QVariant& action, bool enabled);
Q_INVOKABLE void addSecondaryControl(const QVariant& action, bool enabled); Q_INVOKABLE void addSecondaryControl(const QVariant& action, bool enabled);
@ -142,6 +145,8 @@ public:
Q_SIGNALS: Q_SIGNALS:
void mouseMoved(QQuickItem* item); void mouseMoved(QQuickItem* item);
void pttKeyPressed();
void pttKeyReleased();
private Q_SLOTS: private Q_SLOTS:
void setControlRanges(); void setControlRanges();
@ -157,4 +162,8 @@ private:
PendingConferenceesListModel* pendingConferenceesModel_; PendingConferenceesListModel* pendingConferenceesModel_;
QList<QQuickItem*> watchedItems_; QList<QQuickItem*> watchedItems_;
#ifndef HAVE_GLOBAL_PTT
PTTListener* listener_ {nullptr};
#endif
}; };

View File

@ -20,6 +20,7 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import Qt5Compat.GraphicalEffects import Qt5Compat.GraphicalEffects
import net.jami.Constants 1.1 import net.jami.Constants 1.1
import "../mainview/components"
Popup { Popup {
id: root id: root
@ -28,65 +29,80 @@ Popup {
property bool autoClose: true property bool autoClose: true
property alias backgroundColor: container.color property alias backgroundColor: container.color
property alias title: titleText.text property alias title: titleText.text
property var popupContentLoader: containerSubContentLoader property var popupcontainerSubContentLoader: containerSubContentLoader
property bool topLayoutVisible: true
property alias popupContentLoadStatus: containerSubContentLoader.status property alias popupContentLoadStatus: containerSubContentLoader.status
property alias popupContent: containerSubContentLoader.sourceComponent property alias popupContent: containerSubContentLoader.sourceComponent
property int popupContentPreferredHeight: 0 property int popupContentMargins: JamiTheme.preferredMarginSize
property int popupContentPreferredWidth: 0
property int popupContentMargins: 0
parent: Overlay.overlay parent: Overlay.overlay
anchors.centerIn: parent
// center in parent
x: Math.round((parent.width - width) / 2)
y: Math.round((parent.height - height) / 2)
modal: true modal: true
padding: popupContentMargins
padding: 0
// A popup is invisible until opened.
visible: false
focus: true focus: true
closePolicy: autoClose ? (Popup.CloseOnEscape | Popup.CloseOnPressOutside) : Popup.NoAutoClose closePolicy: autoClose ? (Popup.CloseOnEscape | Popup.CloseOnPressOutside) : Popup.NoAutoClose
Rectangle { contentItem: Control {
id: container id: container
anchors.fill: parent property color color: JamiTheme.secondaryBackgroundColor
padding: popupContentMargins
anchors.margins: popupContentMargins
anchors.centerIn: parent
ColumnLayout { background: Rectangle {
anchors.fill: parent id: bgRect
radius: JamiTheme.modalPopupRadius
color: container.color
layer.enabled: true
layer.effect: DropShadow {
horizontalOffset: 3.0
verticalOffset: 3.0
radius: bgRect.radius * 4
color: JamiTheme.shadowColor
source: bgRect
transparentBorder: true
samples: radius + 1
}
}
spacing: 0 contentItem: ColumnLayout {
id: contentLayout
Text { RowLayout {
id: titleText Layout.preferredWidth: parent.width
Layout.bottomMargin: JamiTheme.preferredMarginSize
visible: topLayoutVisible
Layout.alignment: Qt.AlignTop | Qt.AlignLeft Label {
Layout.margins: text.length === 0 ? 0 : 10 id: titleText
Layout.preferredHeight: text.length === 0 ? 0 : contentHeight Layout.alignment: Qt.AlignTop | Qt.AlignLeft
font.pointSize: JamiTheme.menuFontSize
color: JamiTheme.textColor
font.pointSize: JamiTheme.menuFontSize
color: JamiTheme.textColor visible: text.length > 0
}
JamiPushButton {
id: closeButton
Layout.alignment: Qt.AlignRight
imageColor: "grey"
normalColor: "transparent"
source: JamiResources.round_close_24dp_svg
onClicked: close()
}
} }
Loader { Loader {
id: containerSubContentLoader id: containerSubContentLoader
Layout.topMargin: popupContentMargins
Layout.bottomMargin: popupContentMargins
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.fillWidth: popupContentPreferredWidth === 0
Layout.fillHeight: popupContentPreferredHeight === 0
Layout.preferredHeight: popupContentPreferredHeight
Layout.preferredWidth: popupContentPreferredWidth
} }
} }
radius: JamiTheme.modalPopupRadius
color: JamiTheme.secondaryBackgroundColor
} }
background: Rectangle { background: Rectangle {
@ -103,19 +119,6 @@ Popup {
} }
} }
DropShadow {
z: -1
width: root.width
height: root.height
horizontalOffset: 3.0
verticalOffset: 3.0
radius: container.radius * 4
color: JamiTheme.shadowColor
source: container
transparentBorder: true
samples: radius + 1
}
enter: Transition { enter: Transition {
NumberAnimation { NumberAnimation {
properties: "opacity" properties: "opacity"

View File

@ -0,0 +1,123 @@
/*
* Copyright (C) 2023 Savoir-faire Linux Inc.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
BaseModalDialog {
id: pttPage
property string bestName: ""
property string accountId: ""
property int pressedKey: Qt.Key_unknown
signal accepted
signal choiceMade(int chosenKey)
title: JamiStrings.changeShortcut
popupContent: ColumnLayout {
id: deleteAccountContentColumnLayout
anchors.centerIn: parent
spacing: JamiTheme.preferredMarginSize
Component.onCompleted: keyItem.forceActiveFocus()
Label {
id: instructionLabel
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: JamiTheme.preferredDialogWidth - 4*JamiTheme.preferredMarginSize
color: JamiTheme.textColor
text: JamiStrings.assignmentIndication
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pointSize: JamiTheme.textFontSize
font.kerning: true
wrapMode: Text.Wrap
}
Label {
id: keyLabel
Layout.alignment: Qt.AlignCenter
color: JamiTheme.blackColor
wrapMode: Text.WordWrap
text: ""
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
background: Rectangle {
id: backgroundRect
anchors.centerIn: parent
width: keyLabel.width + 2 * JamiTheme.preferredMarginSize
height: keyLabel.height + JamiTheme.preferredMarginSize
color: JamiTheme.lightGrey_
border.color: JamiTheme.darkGreyColor
radius: 4
}
}
MaterialButton {
id: btnAssign
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: JamiTheme.preferredMarginSize
preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8
buttontextHeightMargin: JamiTheme.buttontextHeightMargin
color: JamiTheme.buttonTintedBlack
hoveredColor: JamiTheme.buttonTintedBlackHovered
pressedColor: JamiTheme.buttonTintedBlackPressed
secondary: true
text: JamiStrings.assign
autoAccelerator: true
onClicked: {
if (!(pressedKey === Qt.Key_unknown)){
pttListener.setPttKey(pressedKey);
choiceMade(pressedKey);
}
close();
}
}
Item {
id: keyItem
Keys.onPressed: (event)=>{
keyLabel.text = pttListener.keyToString(event.key);
pressedKey = event.key;
}
}
}
}

View File

@ -27,9 +27,6 @@ BaseModalDialog {
signal accepted signal accepted
width: Math.min(appWindow.width - 2 * JamiTheme.preferredMarginSize, JamiTheme.preferredDialogWidth)
height: Math.min(appWindow.height - 2 * JamiTheme.preferredMarginSize, JamiTheme.preferredDialogHeight)
property string confirmLabel: "" property string confirmLabel: ""
property string textLabel: "" property string textLabel: ""
@ -40,7 +37,7 @@ BaseModalDialog {
id: labelAction id: labelAction
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: column.width - JamiTheme.preferredMarginSize * 2 Layout.maximumWidth: root.width - JamiTheme.preferredMarginSize * 4
color: JamiTheme.textColor color: JamiTheme.textColor
text: root.textLabel text: root.textLabel
@ -55,8 +52,8 @@ BaseModalDialog {
RowLayout { RowLayout {
spacing: 16 spacing: 16
Layout.fillWidth: true
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.topMargin: JamiTheme.preferredMarginSize
MaterialButton { MaterialButton {
id: primaryBtn id: primaryBtn

View File

@ -68,7 +68,8 @@ BaseModalDialog {
id: daemonReconnectPopupTextLabel id: daemonReconnectPopupTextLabel
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.topMargin: preferredMargin Layout.maximumWidth: root.parent.width - 4 * JamiTheme.preferredMarginSize
wrapMode: Text.Wrap
text: connectionFailed ? JamiStrings.reconnectionFailed : JamiStrings.reconnectDaemon text: connectionFailed ? JamiStrings.reconnectionFailed : JamiStrings.reconnectDaemon
font.pointSize: JamiTheme.textFontSize + 2 font.pointSize: JamiTheme.textFontSize + 2

View File

@ -33,17 +33,15 @@ BaseModalDialog {
title: JamiStrings.deleteAccount title: JamiStrings.deleteAccount
width: Math.min(appWindow.width - 2 * JamiTheme.preferredMarginSize, JamiTheme.preferredDialogWidth)
height: Math.min(appWindow.height - 2 * JamiTheme.preferredMarginSize, JamiTheme.preferredDialogHeight)
popupContent: ColumnLayout { popupContent: ColumnLayout {
id: deleteAccountContentColumnLayout id: deleteAccountContentColumnLayout
anchors.centerIn: parent
Label { Label {
id: labelDeletion id: labelDeletion
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: deleteAccountContentColumnLayout.width - JamiTheme.preferredMarginSize * 2 Layout.maximumWidth: root.width - 4*JamiTheme.preferredMarginSize
color: JamiTheme.textColor color: JamiTheme.textColor
text: JamiStrings.confirmDeleteQuestion text: JamiStrings.confirmDeleteQuestion
@ -51,8 +49,6 @@ BaseModalDialog {
font.pointSize: JamiTheme.textFontSize font.pointSize: JamiTheme.textFontSize
font.kerning: true font.kerning: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.Wrap wrapMode: Text.Wrap
} }
@ -60,7 +56,6 @@ BaseModalDialog {
id: labelBestId id: labelBestId
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: deleteAccountContentColumnLayout.width - JamiTheme.preferredMarginSize * 2
color: JamiTheme.textColor color: JamiTheme.textColor
text: bestName text: bestName
@ -68,9 +63,6 @@ BaseModalDialog {
font.pointSize: JamiTheme.textFontSize font.pointSize: JamiTheme.textFontSize
font.kerning: true font.kerning: true
font.bold: true font.bold: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.Wrap wrapMode: Text.Wrap
} }
@ -78,7 +70,7 @@ BaseModalDialog {
id: labelAccountHash id: labelAccountHash
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: deleteAccountContentColumnLayout.width - JamiTheme.preferredMarginSize * 2 Layout.preferredWidth: root.width - 4*JamiTheme.preferredMarginSize
color: JamiTheme.textColor color: JamiTheme.textColor
text: accountId text: accountId
@ -87,7 +79,6 @@ BaseModalDialog {
font.kerning: true font.kerning: true
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.Wrap wrapMode: Text.Wrap
} }
@ -97,7 +88,7 @@ BaseModalDialog {
visible: !isSIP visible: !isSIP
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: deleteAccountContentColumnLayout.width - JamiTheme.preferredMarginSize * 2 Layout.preferredWidth: root.width - 4*JamiTheme.preferredMarginSize
text: JamiStrings.deleteAccountInfos text: JamiStrings.deleteAccountInfos
@ -120,6 +111,7 @@ BaseModalDialog {
id: btnDelete id: btnDelete
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.topMargin: JamiTheme.preferredMarginSize
preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8 preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8
buttontextHeightMargin: JamiTheme.buttontextHeightMargin buttontextHeightMargin: JamiTheme.buttontextHeightMargin
@ -164,6 +156,7 @@ BaseModalDialog {
id: btnCancel id: btnCancel
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.topMargin: JamiTheme.preferredMarginSize
preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8 preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8
buttontextHeightMargin: JamiTheme.buttontextHeightMargin buttontextHeightMargin: JamiTheme.buttontextHeightMargin

View File

@ -25,19 +25,13 @@ import net.jami.Constants 1.1
BaseModalDialog { BaseModalDialog {
id: root id: root
width: 488 width: JamiTheme.secondaryDialogDimension
height: 256
property var previousBodies: undefined property var previousBodies: undefined
popupContent: Item { popupContent: JamiListView {
id: rect width: root.width - 4 * JamiTheme.preferredMarginSize
height: Math.min(count * 50, 150)
width: root.width
JamiListView {
anchors.fill: parent
anchors.margins: JamiTheme.preferredMarginSize
model: root.previousBodies model: root.previousBodies
@ -79,17 +73,4 @@ BaseModalDialog {
} }
} }
} }
PushButton {
id: btnCancel
imageColor: "grey"
normalColor: "transparent"
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 10
anchors.rightMargin: 10
source: JamiResources.round_close_24dp_svg
onClicked: close()
}
} }
}

View File

@ -24,6 +24,7 @@ import net.jami.Constants 1.1
Item { Item {
id: jamiId id: jamiId
property bool slimDisplay: true property bool slimDisplay: true
property color backgroundColor: JamiTheme.welcomeBlockColor property color backgroundColor: JamiTheme.welcomeBlockColor
property color contentColor: JamiTheme.tintedBlue property color contentColor: JamiTheme.tintedBlue
@ -104,6 +105,8 @@ Item {
visible: usernameTextEdit.readOnly visible: usernameTextEdit.readOnly
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.rightMargin: JamiTheme.pushButtonMargins Layout.rightMargin: JamiTheme.pushButtonMargins
Layout.maximumWidth: leftRect.width - 50
elide: Text.ElideRight
color: jamiId.contentColor color: jamiId.contentColor
font.pixelSize : text.length > 16 ? JamiTheme.jamiIdSmallFontSize : JamiTheme.bigFontSize font.pixelSize : text.length > 16 ? JamiTheme.jamiIdSmallFontSize : JamiTheme.bigFontSize
property string registeredName: CurrentAccount.registeredName property string registeredName: CurrentAccount.registeredName

View File

@ -68,6 +68,7 @@ SplitView {
} }
handle: Rectangle { handle: Rectangle {
visible: !isSinglePane
implicitWidth: JamiTheme.splitViewHandlePreferredWidth implicitWidth: JamiTheme.splitViewHandlePreferredWidth
implicitHeight: root.height implicitHeight: root.height
color: JamiTheme.primaryBackgroundColor color: JamiTheme.primaryBackgroundColor

View File

@ -35,8 +35,10 @@ ContextMenuAutoLoader {
GeneralMenuItem { GeneralMenuItem {
id: copy id: copy
canTrigger: lineEditObj.selectedText.length canTrigger: true
isActif: lineEditObj.selectedText.length
itemName: JamiStrings.copy itemName: JamiStrings.copy
hasIcon: false
onClicked: { onClicked: {
lineEditObj.copy(); lineEditObj.copy();
} }
@ -44,9 +46,10 @@ ContextMenuAutoLoader {
GeneralMenuItem { GeneralMenuItem {
id: cut id: cut
canTrigger: lineEditObj.selectedText.length && !selectOnly canTrigger: true
isActif: lineEditObj.selectedText.length && !selectOnly
itemName: JamiStrings.cut itemName: JamiStrings.cut
hasIcon: false
onClicked: { onClicked: {
lineEditObj.cut(); lineEditObj.cut();
} }
@ -56,6 +59,7 @@ ContextMenuAutoLoader {
canTrigger: !selectOnly canTrigger: !selectOnly
itemName: JamiStrings.paste itemName: JamiStrings.paste
hasIcon: false
onClicked: { onClicked: {
if (customizePaste) if (customizePaste)
root.contextMenuRequirePaste(); root.contextMenuRequirePaste();
@ -76,10 +80,6 @@ ContextMenuAutoLoader {
lineEditObj.select(selectionStart, selectionEnd); lineEditObj.select(selectionStart, selectionEnd);
} }
contextMenuItemPreferredHeight: JamiTheme.lineEditContextMenuItemsHeight
contextMenuItemPreferredWidth: JamiTheme.lineEditContextMenuItemsWidth
contextMenuSeparatorPreferredHeight: JamiTheme.lineEditContextMenuSeparatorsHeight
Connections { Connections {
target: root.item target: root.item
enabled: root.status === Loader.Ready enabled: root.status === Loader.Ready

View File

@ -1,309 +0,0 @@
/*
* Copyright (C) 2022-2023 Savoir-faire Linux Inc.
* Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
import QtQuick.Layouts
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
Popup {
id: root
width: emojiColumn.width + JamiTheme.emojiMargins
height: emojiColumn.height + JamiTheme.emojiMargins
padding: 0
background.visible: false
required property var emojiReactions
property var emojiReplied: emojiReactions.ownEmojis
required property string msgId
required property string msgBody
required property bool isOutgoing
required property int type
required property string transferName
required property Item msgBubble
required property ListView listView
property string transferId: msgId
property string location: msgBody
property bool closeWithoutAnimation: false
property var emojiPicker
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
function xPositionProvider(width) {
// Use the width at function scope to retrigger property evaluation.
const listViewWidth = listView.width
if (isOutgoing) {
const leftMargin = msgBubble.mapToItem(listView, 0, 0).x
return width > leftMargin ? -leftMargin : -width
} else {
const rightMargin = listViewWidth - (msgBubble.x + msgBubble.width)
return width > rightMargin ? msgBubble.width - width : msgBubble.width
}
}
function yPositionProvider(height) {
const topOffset = msgBubble.mapToItem(listView, 0, 0).y
if (topOffset < 0) return -topOffset
const bottomOffset = topOffset + height - listView.height
if (bottomOffset > 0) return -bottomOffset
return 0
}
x: xPositionProvider(width)
y: yPositionProvider(height)
signal addMoreEmoji
onAddMoreEmoji: {
JamiQmlUtils.updateMessageBarButtonsPoints()
openEmojiPicker()
}
function openEmojiPicker() {
var component = WITH_WEBENGINE ?
Qt.createComponent("qrc:/webengine/emojipicker/EmojiPicker.qml") :
Qt.createComponent("qrc:/nowebengine/EmojiPicker.qml")
emojiPicker = component.createObject(root.parent, { listView: listView })
emojiPicker.emojiIsPicked.connect(function(content) {
if (emojiReplied.includes(content)) {
MessagesAdapter.removeEmojiReaction(CurrentConversation.id, content, msgId)
} else {
MessagesAdapter.addEmojiReaction(CurrentConversation.id, content, msgId)
}
})
if (emojiPicker !== null) {
root.opacity = 0
emojiPicker.closed.connect(() => close())
emojiPicker.x = xPositionProvider(JamiTheme.emojiPickerWidth)
emojiPicker.y = yPositionProvider(JamiTheme.emojiPickerHeight)
emojiPicker.open()
} else {
console.log("Error creating emojiPicker from message options popup");
}
}
// Close the picker when listView vertical properties change.
property real listViewHeight: listView.height
onListViewHeightChanged: close()
property bool isScrolling: listView.verticalScrollBar.active
onIsScrollingChanged: close()
onOpened: root.closeWithoutAnimation = false
onClosed: if (emojiPicker) emojiPicker.closeEmojiPicker()
function getModel() {
const defaultModel = ["👍", "👎", "😂"]
const reactedEmojis = Array.isArray(emojiReplied) ? emojiReplied.slice(0, defaultModel.length) : []
const uniqueEmojis = Array.from(new Set(reactedEmojis))
const missingEmojis = defaultModel.filter(emoji => !uniqueEmojis.includes(emoji))
return uniqueEmojis.concat(missingEmojis)
}
Rectangle {
id: bubble
color: JamiTheme.chatviewBgColor
anchors.fill: parent
radius: JamiTheme.modalPopupRadius
ColumnLayout {
id: emojiColumn
anchors.centerIn: parent
RowLayout {
id: emojiRow
Layout.alignment: Qt.AlignCenter
Repeater {
model: root.getModel()
delegate: Button {
id: emojiButton
height: 50
width: 50
text: modelData
font.pointSize: JamiTheme.emojiBubbleSize
Text {
visible: emojiButton.hovered
anchors.centerIn: parent
text: modelData
font.pointSize: JamiTheme.emojiBubbleSizeBig
z: 1
}
background: Rectangle {
anchors.fill: parent
opacity: emojiReplied ? (emojiReplied.includes(modelData) ? 1 : 0) : 0
color: JamiTheme.emojiReactPushButtonColor
radius: 10
}
onClicked: {
if (emojiReplied.includes(modelData))
MessagesAdapter.removeEmojiReaction(CurrentConversation.id,text,msgId)
else
MessagesAdapter.addEmojiReaction(CurrentConversation.id,text,msgId)
close()
}
}
}
PushButton {
toolTipText: JamiStrings.moreEmojis
source: JamiResources.add_reaction_svg
normalColor: JamiTheme.emojiReactBubbleBgColor
imageColor: JamiTheme.emojiReactPushButtonColor
visible: WITH_WEBENGINE
onClicked: {
root.closeWithoutAnimation = true
root.addMoreEmoji()
//close()
}
}
}
Rectangle {
Layout.margins: 5
color: JamiTheme.timestampColor
Layout.fillWidth: true
Layout.preferredHeight: 1
radius: width * 0.5
opacity: 0.6
}
MessageOptionButton {
textButton: JamiStrings.copy
iconSource: JamiResources.copy_svg
Layout.fillWidth: true
Layout.margins: 5
onClicked: {
UtilsAdapter.setClipboardText(msgBody)
close()
}
}
MessageOptionButton {
visible: type === Interaction.Type.DATA_TRANSFER
textButton: JamiStrings.saveFile
iconSource: JamiResources.save_file_svg
Layout.fillWidth: true
Layout.margins: 5
onClicked: {
MessagesAdapter.copyToDownloads(root.transferId, root.transferName)
close()
}
}
MessageOptionButton {
visible: type === Interaction.Type.DATA_TRANSFER
textButton: JamiStrings.openLocation
iconSource: JamiResources.round_folder_24dp_svg
Layout.fillWidth: true
Layout.margins: 5
onClicked: {
MessagesAdapter.openDirectory(root.location)
close()
}
}
MessageOptionButton {
visible: type === Interaction.Type.DATA_TRANSFER && Status === Interaction.Status.TRANSFER_FINISHED
textButton: JamiStrings.removeLocally
iconSource: JamiResources.trash_black_24dp_svg
Layout.fillWidth: true
Layout.margins: 5
onClicked: {
MessagesAdapter.removeFile(msgId, root.location)
close()
}
}
MessageOptionButton {
id: buttonEdit
visible: root.isOutgoing && type === Interaction.Type.TEXT
textButton: JamiStrings.editMessage
iconSource: JamiResources.edit_svg
Layout.fillWidth: true
Layout.margins: 5
onClicked: {
MessagesAdapter.replyToId = ""
MessagesAdapter.editId = root.msgId
close()
}
}
MessageOptionButton {
visible: root.isOutgoing && type === Interaction.Type.TEXT
textButton: JamiStrings.deleteMessage
iconSource: JamiResources.delete_svg
Layout.fillWidth: true
Layout.margins: 5
onClicked: {
MessagesAdapter.editMessage(CurrentConversation.id, "", root.msgId)
close()
}
}
}
}
Overlay.modal: Rectangle {
color: JamiTheme.transparentColor
// Color animation for overlay when pop up is shown.
ColorAnimation on color {
to: JamiTheme.popupOverlayColor
duration: 500
}
}
DropShadow {
z: -1
width: bubble.width
height: bubble.height
horizontalOffset: 3.0
verticalOffset: 3.0
radius: bubble.radius * 4
color: JamiTheme.shadowColor
source: bubble
transparentBorder: true
samples: radius + 1
}
enter: Transition {
NumberAnimation {
properties: "opacity"; from: 0.0; to: 1.0
duration: JamiTheme.shortFadeDuration
}
}
exit: Transition {
NumberAnimation {
properties: "opacity"; from: 1.0; to: 0.0
duration: root.closeWithoutAnimation ? 0 : JamiTheme.shortFadeDuration
}
}
}

View File

@ -35,9 +35,6 @@ BaseModalDialog {
signal done(bool success, int purpose) signal done(bool success, int purpose)
width: Math.min(appWindow.width - 2 * JamiTheme.preferredMarginSize, JamiTheme.preferredDialogWidth)
height: Math.min(appWindow.height - 2 * JamiTheme.preferredMarginSize, JamiTheme.preferredDialogHeight)
title: { title: {
switch (purpose) { switch (purpose) {
case PasswordDialog.ExportAccount: case PasswordDialog.ExportAccount:
@ -75,7 +72,7 @@ BaseModalDialog {
popupContent: ColumnLayout { popupContent: ColumnLayout {
id: popupContentColumnLayout id: popupContentColumnLayout
spacing: 0 spacing: 16
function validatePassword() { function validatePassword() {
switch (purpose) { switch (purpose) {
@ -128,6 +125,8 @@ BaseModalDialog {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: JamiTheme.preferredFieldWidth Layout.preferredWidth: JamiTheme.preferredFieldWidth
Layout.preferredHeight: visible ? 48 : 0 Layout.preferredHeight: visible ? 48 : 0
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.ExportAccount visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.ExportAccount
placeholderText: JamiStrings.enterCurrentPassword placeholderText: JamiStrings.enterCurrentPassword
@ -141,6 +140,8 @@ BaseModalDialog {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: JamiTheme.preferredFieldWidth Layout.preferredWidth: JamiTheme.preferredFieldWidth
Layout.preferredHeight: visible ? 48 : 0 Layout.preferredHeight: visible ? 48 : 0
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.SetPassword visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.SetPassword
@ -155,6 +156,8 @@ BaseModalDialog {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: JamiTheme.preferredFieldWidth Layout.preferredWidth: JamiTheme.preferredFieldWidth
Layout.preferredHeight: visible ? 48 : 0 Layout.preferredHeight: visible ? 48 : 0
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.SetPassword visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.SetPassword
@ -163,49 +166,24 @@ BaseModalDialog {
onDynamicTextChanged: popupContentColumnLayout.validatePassword() onDynamicTextChanged: popupContentColumnLayout.validatePassword()
} }
RowLayout { MaterialButton {
spacing: 16 id: btnConfirm
Layout.fillWidth: true
Layout.alignment: Qt.AlignCenter
MaterialButton { Layout.alignment: Qt.AlignHCenter
id: btnConfirm preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8
Layout.alignment: Qt.AlignHCenter color: enabled ? JamiTheme.buttonTintedBlack : JamiTheme.buttonTintedGrey
hoveredColor: JamiTheme.buttonTintedBlackHovered
pressedColor: JamiTheme.buttonTintedBlackPressed
secondary: true
autoAccelerator: true
enabled: purpose === PasswordDialog.SetPassword
preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8 text: (purpose === PasswordDialog.ExportAccount) ? JamiStrings.exportAccount : JamiStrings.change
color: enabled ? JamiTheme.buttonTintedBlack : JamiTheme.buttonTintedGrey onClicked: {
hoveredColor: JamiTheme.buttonTintedBlackHovered btnConfirm.enabled = false;
pressedColor: JamiTheme.buttonTintedBlackPressed timerToOperate.restart();
secondary: true
autoAccelerator: true
enabled: purpose === PasswordDialog.SetPassword
text: (purpose === PasswordDialog.ExportAccount) ? JamiStrings.exportAccount : JamiStrings.change
onClicked: {
btnConfirm.enabled = false;
timerToOperate.restart();
}
}
MaterialButton {
id: btnCancel
Layout.alignment: Qt.AlignHCenter
preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8
color: JamiTheme.buttonTintedBlack
hoveredColor: JamiTheme.buttonTintedBlackHovered
pressedColor: JamiTheme.buttonTintedBlackPressed
secondary: true
autoAccelerator: true
text: JamiStrings.optionCancel
onClicked: close()
} }
} }
} }

View File

@ -32,15 +32,12 @@ import "../mainview/components"
BaseModalDialog { BaseModalDialog {
id: root id: root
height: 157
x: - width / 2
y: - height / 5
property string imageId property string imageId
property bool newItem property bool newItem
property real buttonSize: JamiTheme.smartListAvatarSize property real buttonSize: JamiTheme.smartListAvatarSize
property real imageSize: 25 property real imageSize: 25
signal focusOnPreviousItem signal focusOnPreviousItem
signal focusOnNextItem signal focusOnNextItem
@ -60,9 +57,15 @@ BaseModalDialog {
importButton.forceActiveFocus() importButton.forceActiveFocus()
} }
width: JamiTheme.preferredDialogWidth
title: JamiStrings.chooseAvatarPicture
RecordBox { RecordBox {
id: recordBox id: recordBox
anchors.centerIn: parent
isPhoto: true isPhoto: true
visible: false visible: false
@ -77,223 +80,176 @@ BaseModalDialog {
} }
} }
popupContent: Item { popupContent: RowLayout {
id: buttonsRowLayout
Component.onCompleted: { spacing: 10
root.width = Qt.binding(() => clearButton.visible ? 283 : 210)
}
Rectangle {
id: container
anchors.fill: parent
radius: JamiTheme.photoPopupRadius
color: JamiTheme.inviteHoverColor
PushButton { PushButton {
id: btnCancel id: takePhotoButton
imageColor: "grey"
objectName: "takePhotoButton"
Layout.alignment: Qt.AlignHCenter
height: buttonSize
width: buttonSize
imageContainerWidth: imageSize
imageContainerHeight: imageSize
radius: height / 2
border.color: JamiTheme.buttonTintedBlue
normalColor: "transparent" normalColor: "transparent"
anchors.right: parent.right imageColor: JamiTheme.buttonTintedBlue
anchors.top: parent.top toolTipText: JamiStrings.takePhoto
anchors.topMargin: 10 source: JamiResources.baseline_camera_alt_24dp_svg
anchors.rightMargin: 10 hoveredColor: JamiTheme.smartListHoveredColor
source: JamiResources.round_close_24dp_svg
onClicked: { close();}
}
Keys.onPressed: function (keyEvent) {
ColumnLayout { if (keyEvent.key === Qt.Key_Enter ||
id: mainLayout keyEvent.key === Qt.Key_Return) {
anchors.fill: parent clicked()
anchors.margins: JamiTheme.preferredMarginSize keyEvent.accepted = true
} else if (keyEvent.key === Qt.Key_Up) {
Text { root.focusOnPreviousItem()
id: informativeLabel keyEvent.accepted = true
}
Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true
Layout.topMargin: 26
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: JamiStrings.chooseAvatarPicture
color: JamiTheme.primaryForegroundColor
font.pixelSize: JamiTheme.popupPhotoTextSize
elide: Text.ElideRight
} }
RowLayout { KeyNavigation.tab: {
id: buttonsRowLayout if (clearButton.visible)
Layout.preferredHeight: childrenRect.height return clearButton
Layout.alignment: Qt.AlignCenter return importButton
spacing: 10 }
KeyNavigation.down: KeyNavigation.tab
PushButton { onClicked: {
id: takePhotoButton recordBox.parent = buttonsRowLayout
objectName: "takePhotoButton" recordBox.x = Qt.binding(function() {
var buttonCenterX = buttonsRowLayout.width / 2
return buttonCenterX - recordBox.width / 2
})
recordBox.y = Qt.binding(function() {
return - recordBox.height / 2
})
startBooth()
}
}
Layout.alignment: Qt.AlignHCenter PushButton {
id: importButton
height: buttonSize objectName: "photoboothViewImportButton"
width: buttonSize
imageContainerWidth: imageSize
imageContainerHeight: imageSize
radius: height / 2
border.color: JamiTheme.buttonTintedBlue
normalColor: "transparent"
imageColor: JamiTheme.buttonTintedBlue
toolTipText: JamiStrings.takePhoto
source: JamiResources.baseline_camera_alt_24dp_svg
hoveredColor: JamiTheme.smartListHoveredColor
Keys.onPressed: function (keyEvent) { Layout.alignment: Qt.AlignHCenter
if (keyEvent.key === Qt.Key_Enter || visible: parent.visible
keyEvent.key === Qt.Key_Return) {
clicked()
keyEvent.accepted = true
} else if (keyEvent.key === Qt.Key_Up) {
root.focusOnPreviousItem()
keyEvent.accepted = true
}
}
KeyNavigation.tab: { height: buttonSize
if (clearButton.visible) width: buttonSize
return clearButton imageContainerWidth: imageSize
return importButton imageContainerHeight: imageSize
} radius: height / 2
KeyNavigation.down: KeyNavigation.tab border.color: JamiTheme.buttonTintedBlue
normalColor: "transparent"
source: JamiResources.round_folder_24dp_svg
toolTipText: JamiStrings.importFromFile
imageColor: JamiTheme.buttonTintedBlue
hoveredColor: JamiTheme.smartListHoveredColor
onClicked: {
recordBox.parent = buttonsRowLayout
recordBox.x = Qt.binding(function() { Keys.onPressed: function (keyEvent) {
var buttonCenterX = buttonsRowLayout.width / 2 if (keyEvent.key === Qt.Key_Enter ||
return buttonCenterX - recordBox.width / 2 keyEvent.key === Qt.Key_Return) {
}) clicked()
recordBox.y = Qt.binding(function() { keyEvent.accepted = true
return - recordBox.height / 2 } else if (keyEvent.key === Qt.Key_Down ||
}) keyEvent.key === Qt.Key_Tab) {
startBooth() clearButton.forceActiveFocus()
} keyEvent.accepted = true
} }
}
PushButton { KeyNavigation.up: takePhotoButton
id: importButton
objectName: "photoboothViewImportButton" onClicked: {
stopBooth()
Layout.alignment: Qt.AlignHCenter var dlg = viewCoordinator.presentDialog(
visible: parent.visible appWindow,
"commoncomponents/JamiFileDialog.qml",
height: buttonSize {
width: buttonSize title: JamiStrings.chooseAvatarImage,
imageContainerWidth: imageSize fileMode: JamiFileDialog.OpenFile,
imageContainerHeight: imageSize folder: StandardPaths.writableLocation(
radius: height / 2 StandardPaths.PicturesLocation),
border.color: JamiTheme.buttonTintedBlue nameFilters: [JamiStrings.imageFiles,
normalColor: "transparent" JamiStrings.allFiles]
source: JamiResources.round_folder_24dp_svg })
toolTipText: JamiStrings.importFromFile dlg.fileAccepted.connect(function(file) {
imageColor: JamiTheme.buttonTintedBlue var filePath = UtilsAdapter.getAbsPath(file)
hoveredColor: JamiTheme.smartListHoveredColor if (!root.newItem) {
AccountAdapter.setCurrentAccountAvatarFile(filePath)
} else {
Keys.onPressed: function (keyEvent) { UtilsAdapter.setTempCreationImageFromFile(filePath, root.imageId)
if (keyEvent.key === Qt.Key_Enter ||
keyEvent.key === Qt.Key_Return) {
clicked()
keyEvent.accepted = true
} else if (keyEvent.key === Qt.Key_Down ||
keyEvent.key === Qt.Key_Tab) {
clearButton.forceActiveFocus()
keyEvent.accepted = true
}
} }
root.close()
})
}
}
KeyNavigation.up: takePhotoButton PushButton {
id: clearButton
onClicked: { objectName: "photoboothViewClearButton"
stopBooth()
var dlg = viewCoordinator.presentDialog( Layout.alignment: Qt.AlignHCenter
appWindow,
"commoncomponents/JamiFileDialog.qml", height: buttonSize
{ width: buttonSize
title: JamiStrings.chooseAvatarImage, imageContainerWidth: imageSize
fileMode: JamiFileDialog.OpenFile, imageContainerHeight: imageSize
folder: StandardPaths.writableLocation( radius: height / 2
StandardPaths.PicturesLocation), border.color: JamiTheme.buttonTintedBlue
nameFilters: [JamiStrings.imageFiles, normalColor: "transparent"
JamiStrings.allFiles] source: JamiResources.ic_hangup_participant_24dp_svg
}) toolTipText: JamiStrings.clearAvatar
dlg.fileAccepted.connect(function(file) { imageColor: JamiTheme.buttonTintedBlue
var filePath = UtilsAdapter.getAbsPath(file) hoveredColor: JamiTheme.smartListHoveredColor
if (!root.newItem) {
AccountAdapter.setCurrentAccountAvatarFile(filePath)
} else { visible: {
UtilsAdapter.setTempCreationImageFromFile(filePath, root.imageId) if (!newItem && LRCInstance.currentAccountAvatarSet)
} return true
root.close() if (newItem && UtilsAdapter.tempCreationImage(imageId).length !== 0)
}) return true
} return false
}
KeyNavigation.up: importButton
Keys.onPressed: function (keyEvent) {
if (keyEvent.key === Qt.Key_Enter ||
keyEvent.key === Qt.Key_Return) {
clicked()
importButton.forceActiveFocus()
keyEvent.accepted = true
} else if (keyEvent.key === Qt.Key_Down ||
keyEvent.key === Qt.Key_Tab) {
btnCancel.forceActiveFocus()
keyEvent.accepted = true
} }
}
PushButton { onClicked: {
id: clearButton if (!root.newItem)
AccountAdapter.setCurrentAccountAvatarBase64()
objectName: "photoboothViewClearButton" else
UtilsAdapter.setTempCreationImageFromString("", imageId)
Layout.alignment: Qt.AlignHCenter visible = false
stopBooth()
height: buttonSize root.close()
width: buttonSize
imageContainerWidth: imageSize
imageContainerHeight: imageSize
radius: height / 2
border.color: JamiTheme.buttonTintedBlue
normalColor: "transparent"
source: JamiResources.ic_hangup_participant_24dp_svg
toolTipText: JamiStrings.clearAvatar
imageColor: JamiTheme.buttonTintedBlue
hoveredColor: JamiTheme.smartListHoveredColor
visible: {
if (!newItem && LRCInstance.currentAccountAvatarSet)
return true
if (newItem && UtilsAdapter.tempCreationImage(imageId).length !== 0)
return true
return false
}
KeyNavigation.up: importButton
Keys.onPressed: function (keyEvent) {
if (keyEvent.key === Qt.Key_Enter ||
keyEvent.key === Qt.Key_Return) {
clicked()
importButton.forceActiveFocus()
keyEvent.accepted = true
} else if (keyEvent.key === Qt.Key_Down ||
keyEvent.key === Qt.Key_Tab) {
btnCancel.forceActiveFocus()
keyEvent.accepted = true
}
}
onClicked: {
if (!root.newItem)
AccountAdapter.setCurrentAccountAvatarBase64()
else
UtilsAdapter.setTempCreationImageFromString("", imageId)
visible = false
stopBooth()
root.close()
}
}
} }
} }
} }
} }
}

View File

@ -53,6 +53,7 @@ AbstractButton {
property alias toolTipText: toolTip.text property alias toolTipText: toolTip.text
property alias hasShortcut: toolTip.hasShortcut property alias hasShortcut: toolTip.hasShortcut
property alias shortcutKey: toolTip.shortcutKey property alias shortcutKey: toolTip.shortcutKey
property int buttonTextFontSize: 12
// State colors // State colors
property string pressedColor: JamiTheme.pressedButtonColor property string pressedColor: JamiTheme.pressedButtonColor
@ -143,7 +144,7 @@ AbstractButton {
color: JamiTheme.primaryForegroundColor color: JamiTheme.primaryForegroundColor
font.kerning: true font.kerning: true
font.pixelSize: 12 font.pixelSize: buttonTextFontSize
elide: Qt.ElideRight elide: Qt.ElideRight
} }

View File

@ -37,6 +37,7 @@ ContextMenuAutoLoader {
canTrigger: root.transferId !== "" canTrigger: root.transferId !== ""
itemName: JamiStrings.saveFile itemName: JamiStrings.saveFile
iconSource: JamiResources.save_file_svg
onClicked: MessagesAdapter.copyToDownloads(root.transferId, root.transferName) onClicked: MessagesAdapter.copyToDownloads(root.transferId, root.transferName)
}, },
GeneralMenuItem { GeneralMenuItem {
@ -44,6 +45,7 @@ ContextMenuAutoLoader {
canTrigger: root.transferId !== "" canTrigger: root.transferId !== ""
itemName: JamiStrings.openLocation itemName: JamiStrings.openLocation
iconSource: JamiResources.round_folder_24dp_svg
onClicked: { onClicked: {
MessagesAdapter.openDirectory(root.location); MessagesAdapter.openDirectory(root.location);
} }
@ -52,6 +54,7 @@ ContextMenuAutoLoader {
id: reply id: reply
itemName: JamiStrings.reply itemName: JamiStrings.reply
iconSource: JamiResources.reply_black_24dp_svg
onClicked: { onClicked: {
MessagesAdapter.editId = ""; MessagesAdapter.editId = "";
MessagesAdapter.replyToId = root.msgId; MessagesAdapter.replyToId = root.msgId;
@ -62,6 +65,7 @@ ContextMenuAutoLoader {
canTrigger: transferId === "" && isOutgoing canTrigger: transferId === "" && isOutgoing
itemName: JamiStrings.edit itemName: JamiStrings.edit
iconSource: JamiResources.edit_svg
onClicked: { onClicked: {
MessagesAdapter.replyToId = ""; MessagesAdapter.replyToId = "";
MessagesAdapter.editId = root.msgId; MessagesAdapter.editId = root.msgId;
@ -73,6 +77,7 @@ ContextMenuAutoLoader {
canTrigger: transferId === "" && isOutgoing canTrigger: transferId === "" && isOutgoing
itemName: JamiStrings.optionDelete itemName: JamiStrings.optionDelete
iconSource: JamiResources.delete_svg
onClicked: { onClicked: {
MessagesAdapter.editMessage(CurrentConversation.id, "", root.msgId); MessagesAdapter.editMessage(CurrentConversation.id, "", root.msgId);
} }

View File

@ -243,6 +243,7 @@ Control {
anchors.fill: bubble anchors.fill: bubble
hoverEnabled: true hoverEnabled: true
onClicked: function (mouse) { onClicked: function (mouse) {
if (root.hoveredLink) { if (root.hoveredLink) {
MessagesAdapter.openUrl(root.hoveredLink); MessagesAdapter.openUrl(root.hoveredLink);
@ -277,8 +278,8 @@ Control {
anchors.rightMargin: isOutgoing ? 10 : 0 anchors.rightMargin: isOutgoing ? 10 : 0
anchors.leftMargin: !isOutgoing ? 10 : 0 anchors.leftMargin: !isOutgoing ? 10 : 0
imageColor: JamiTheme.emojiReactPushButtonColor imageColor: hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor
normalColor: JamiTheme.transparentColor normalColor: JamiTheme.primaryBackgroundColor
toolTipText: JamiStrings.moreOptions toolTipText: JamiStrings.moreOptions
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.right: isOutgoing ? optionButtonItem.right : undefined anchors.right: isOutgoing ? optionButtonItem.right : undefined
@ -287,33 +288,54 @@ Control {
source: JamiResources.more_vert_24dp_svg source: JamiResources.more_vert_24dp_svg
width: optionButtonItem.width / 2 width: optionButtonItem.width / 2
height: optionButtonItem.height height: optionButtonItem.height
circled: false
property bool isOpen: false
property var obj: undefined
function bind() {
more.isOpen = false;
visible = Qt.binding(() => CurrentAccount.type !== Profile.Type.SIP && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || bgHandler.hovered));
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
}
onClicked: { onClicked: {
var component = Qt.createComponent("qrc:/commoncomponents/MessageOptionsPopup.qml"); if (more.isOpen) {
var obj = component.createObject(bubble, { more.bind();
"emojiReactions": emojiReactions, obj.close();
"isOutgoing": isOutgoing, } else {
"msgId": Id, var component = Qt.createComponent("qrc:/commoncomponents/ShowMoreMenu.qml");
"msgBody": Body, obj = component.createObject(more, {
"type": Type, "emojiReactions": emojiReactions,
"transferName": TransferName, "isOutgoing": isOutgoing,
"msgBubble": bubble, "msgId": Id,
"listView": listView "msgBody": Body,
}); "type": Type,
obj.open(); "transferName": TransferName,
"msgBubble": bubble,
"listView": listView
});
obj.open();
more.isOpen = true;
visible = true;
imageColor = JamiTheme.chatViewFooterImgHoverColor;
normalColor = JamiTheme.hoveredButtonColor;
}
} }
} }
PushButton { PushButton {
id: reply id: reply
imageColor: JamiTheme.emojiReactPushButtonColor circled: false
normalColor: JamiTheme.transparentColor imageColor: hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor
normalColor: JamiTheme.primaryBackgroundColor
toolTipText: JamiStrings.reply toolTipText: JamiStrings.reply
source: JamiResources.reply_svg source: JamiResources.reply_black_24dp_svg
width: optionButtonItem.width / 2 width: optionButtonItem.width / 2
height: optionButtonItem.height height: optionButtonItem.height
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: 5
anchors.right: isOutgoing ? more.left : undefined anchors.right: isOutgoing ? more.left : undefined
anchors.left: !isOutgoing ? more.right : undefined anchors.left: !isOutgoing ? more.right : undefined
visible: CurrentAccount.type !== Profile.Type.SIP && Body !== "" && (bubbleArea.bubbleHovered || hovered || more.hovered || bgHandler.hovered) visible: CurrentAccount.type !== Profile.Type.SIP && Body !== "" && (bubbleArea.bubbleHovered || hovered || more.hovered || bgHandler.hovered)

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2020-2023 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import net.jami.Constants 1.1
import "contextmenu"
BaseContextMenu {
id: root
property var modelList
signal audioRecordMessageButtonClicked
signal videoRecordMessageButtonClicked
signal showMapClicked
property list<GeneralMenuItem> menuItems: [
GeneralMenuItem {
id: audioMessage
canTrigger: true
iconSource: JamiResources.message_audio_black_24dp_svg
itemName: JamiStrings.leaveAudioMessage
onClicked: {
root.audioRecordMessageButtonClicked();
}
},
GeneralMenuItem {
id: videoMessage
canTrigger: true
iconSource: JamiResources.message_video_black_24dp_svg
itemName: JamiStrings.leaveVideoMessage
onClicked: {
root.videoRecordMessageButtonClicked();
}
},
GeneralMenuItem {
id: shareLocation
canTrigger: true
iconSource: JamiResources.localisation_sharing_send_pin_svg
itemName: JamiStrings.shareLocation
onClicked: {
root.showMapClicked();
}
}
]
Component.onCompleted: {
root.loadMenuItems(menuItems);
}
}

View File

@ -1,134 +0,0 @@
/*
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Qt.labs.platform
import Qt5Compat.GraphicalEffects
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
import "../mainview/components"
Popup {
id: root
padding: 0
property list<Action> menuMoreButton
height: childrenRect.height
width: childrenRect.width
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
Rectangle {
id: rect
color: JamiTheme.primaryBackgroundColor
border.color: JamiTheme.chatViewFooterRectangleBorderColor
border.width: 2
radius: 5
height: listViewMoreButton.childrenRect.height + 16
width: listViewMoreButton.childrenRect.width + 16
ListView {
id: listViewMoreButton
anchors.centerIn: parent
orientation: ListView.Vertical
spacing: 0
width: contentItem.childrenRect.width
height: contentHeight
model: menuMoreButton
Rectangle {
z: -1
anchors.fill: parent
color: "transparent"
}
onCountChanged: {
for (var i = 0; i < count; i++) {
var item = listViewMoreButton.itemAtIndex(i);
item.width = listViewMoreButton.width;
}
}
delegate: ItemDelegate {
id: control
text: modelData.toolTip
contentItem: RowLayout {
Rectangle {
id: image
width: 26
height: 26
radius: 5
color: JamiTheme.transparentColor
ResponsiveImage {
anchors.fill: parent
source: modelData.iconSrc
color: control.hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor
}
}
Text {
Layout.alignment: Qt.AlignLeft
text: control.text
color: control.hovered ? JamiTheme.chatViewFooterImgHoverColor : "#7f7f7f"
}
}
background: Rectangle {
color: control.hovered ? JamiTheme.showMoreButtonOpenColor : JamiTheme.transparentColor
}
action: modelData
onClicked: {
root.close();
}
}
}
}
background: Rectangle {
anchors.fill: parent
color: JamiTheme.transparentColor
radius: 5
z: -1
}
enter: Transition {
NumberAnimation {
properties: "opacity"
from: 0.0
to: 1.0
duration: JamiTheme.shortFadeDuration
}
}
exit: Transition {
NumberAnimation {
properties: "opacity"
from: 1.0
to: 0.0
duration: JamiTheme.shortFadeDuration
}
}
}

View File

@ -0,0 +1,190 @@
/*
* Copyright (C) 2020-2023 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import net.jami.Constants 1.1
import Qt5Compat.GraphicalEffects
import QtQuick.Controls
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import "contextmenu"
BaseContextMenu {
id: root
required property var emojiReactions
property var emojiReplied: emojiReactions.ownEmojis
required property string msgId
required property string msgBody
required property bool isOutgoing
required property int type
required property string transferName
required property Item msgBubble
required property ListView listView
property string location: msgBody
property bool closeWithoutAnimation: false
property var emojiPicker
function xPositionProvider(width) {
// Use the width at function scope to retrigger property evaluation.
const listViewWidth = listView.width;
const parentX = parent.x;
if (isOutgoing) {
return parentX - width - 21;
} else {
return parentX + 21;
}
}
x: xPositionProvider(width)
y: parent.y
signal addMoreEmoji
onAddMoreEmoji: {
JamiQmlUtils.updateMessageBarButtonsPoints();
openEmojiPicker();
}
function openEmojiPicker() {
var component = WITH_WEBENGINE ? Qt.createComponent("qrc:/webengine/emojipicker/EmojiPicker.qml") : Qt.createComponent("qrc:/nowebengine/EmojiPicker.qml");
emojiPicker = component.createObject(root.parent, {
"listView": listView
});
emojiPicker.emojiIsPicked.connect(function (content) {
if (emojiReplied.includes(content)) {
MessagesAdapter.removeEmojiReaction(CurrentConversation.id, content, msgId);
} else {
MessagesAdapter.addEmojiReaction(CurrentConversation.id, content, msgId);
}
});
if (emojiPicker !== null) {
root.opacity = 0;
emojiPicker.closed.connect(() => close());
emojiPicker.x = xPositionProvider(JamiTheme.emojiPickerWidth);
emojiPicker.y = yPositionProvider(JamiTheme.emojiPickerHeight);
emojiPicker.open();
} else {
console.log("Error creating emojiPicker from message options popup");
}
}
// Close the picker when listView vertical properties change.
property real listViewHeight: listView.height
onListViewHeightChanged: close()
property bool isScrolling: listView.verticalScrollBar.active
onIsScrollingChanged: close()
onOpened: root.closeWithoutAnimation = false
onClosed: if (emojiPicker)
emojiPicker.closeEmojiPicker()
function getModel() {
const defaultModel = ["👍", "👎", "😂"];
const reactedEmojis = Array.isArray(emojiReplied) ? emojiReplied.slice(0, defaultModel.length) : [];
const uniqueEmojis = Array.from(new Set(reactedEmojis));
const missingEmojis = defaultModel.filter(emoji => !uniqueEmojis.includes(emoji));
return uniqueEmojis.concat(missingEmojis);
}
property list<MenuItem> menuItems: [
GeneralMenuItemList {
id: audioMessage
modelList: getModel()
canTrigger: true
iconSource: JamiResources.add_reaction_svg
itemName: JamiStrings.copy
addMenuSeparatorAfter: true
messageId: msgId
},
GeneralMenuItem {
id: saveFile
canTrigger: type === Interaction.Type.DATA_TRANSFER
iconSource: JamiResources.save_file_svg
itemName: JamiStrings.saveFile
onClicked: {
MessagesAdapter.copyToDownloads(root.msgId, root.transferName);
}
},
GeneralMenuItem {
id: openLocation
canTrigger: type === Interaction.Type.DATA_TRANSFER
iconSource: JamiResources.round_folder_24dp_svg
itemName: JamiStrings.openLocation
onClicked: {
MessagesAdapter.openDirectory(root.location);
}
},
GeneralMenuItem {
id: removeLocally
canTrigger: type === Interaction.Type.DATA_TRANSFER && Status === Interaction.Status.TRANSFER_FINISHED
iconSource: JamiResources.trash_black_24dp_svg
itemName: JamiStrings.removeLocally
onClicked: {
MessagesAdapter.removeFile(msgId, root.location);
;
}
},
GeneralMenuItem {
id: editMessage
canTrigger: root.isOutgoing && type === Interaction.Type.TEXT
iconSource: JamiResources.edit_svg
itemName: JamiStrings.editMessage
onClicked: {
MessagesAdapter.replyToId = "";
MessagesAdapter.editId = root.msgId;
}
},
GeneralMenuItem {
id: deleteMessage
canTrigger: root.isOutgoing && type === Interaction.Type.TEXT
iconSource: JamiResources.delete_svg
itemName: JamiStrings.deleteMessage
onClicked: {
MessagesAdapter.editMessage(CurrentConversation.id, "", root.msgId);
}
},
GeneralMenuItem {
id: copyMessage
canTrigger: true
iconSource: JamiResources.copy_svg
itemName: JamiStrings.copy
onClicked: {
UtilsAdapter.setClipboardText(msgBody);
}
}
]
Component.onCompleted: {
root.loadMenuItems(menuItems);
}
onAboutToHide: {
root.destroy();
}
Component.onDestruction: {
parent.bind();
}
}

View File

@ -44,9 +44,6 @@ BaseModalDialog {
open(); open();
} }
width: Math.max(JamiTheme.preferredDialogWidth, buttonTitles.length * (JamiTheme.preferredFieldWidth / 2 + JamiTheme.preferredMarginSize))
height: JamiTheme.preferredDialogHeight / 2 - JamiTheme.preferredMarginSize
popupContent: ColumnLayout { popupContent: ColumnLayout {
Label { Label {
id: infoTextLabel id: infoTextLabel
@ -72,12 +69,10 @@ BaseModalDialog {
data: innerContentData data: innerContentData
} }
RowLayout { RowLayout {
spacing: JamiTheme.preferredMarginSize spacing: JamiTheme.preferredMarginSize
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: contentHeight
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.bottomMargin: JamiTheme.preferredMarginSize Layout.bottomMargin: JamiTheme.preferredMarginSize

View File

@ -23,6 +23,8 @@ import net.jami.Constants 1.1
Menu { Menu {
id: root id: root
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside | Popup.CloseOnPressOutsideParent
property int menuPreferredWidth: 0 property int menuPreferredWidth: 0
property int menuItemsPreferredHeight: 0 property int menuItemsPreferredHeight: 0
property int menuSeparatorPreferredHeight: 0 property int menuSeparatorPreferredHeight: 0
@ -43,11 +45,9 @@ Menu {
function loadMenuItems(menuItems) { function loadMenuItems(menuItems) {
root.addItem(menuTopBorder); root.addItem(menuTopBorder);
// use the maximum text width as the preferred width for menu
for (var j = 0; j < menuItems.length; ++j) { for (var j = 0; j < menuItems.length; ++j) {
var currentItemWidth = menuItems[j].itemPreferredWidth; var currentItemWidth = menuItems[j].itemPreferredWidth;
if (currentItemWidth !== JamiTheme.menuItemsPreferredWidth && currentItemWidth > menuPreferredWidth) if (currentItemWidth !== JamiTheme.menuItemsPreferredWidth && currentItemWidth > menuPreferredWidth && menuItems[j].canTrigger)
menuPreferredWidth = currentItemWidth; menuPreferredWidth = currentItemWidth;
} }
for (var i = 0; i < menuItems.length; ++i) { for (var i = 0; i < menuItems.length; ++i) {
@ -55,17 +55,28 @@ Menu {
menuItems[i].parentMenu = root; menuItems[i].parentMenu = root;
root.addItem(menuItems[i]); root.addItem(menuItems[i]);
if (menuPreferredWidth) if (menuPreferredWidth)
menuItems[i].itemPreferredWidth = menuPreferredWidth; menuItems[i].itemRealWidth = menuPreferredWidth;
if (menuItemsPreferredHeight) if (menuItemsPreferredHeight)
menuItems[i].itemPreferredHeight = menuItemsPreferredHeight; menuItems[i].itemPreferredHeight = menuItemsPreferredHeight;
} if (i !== menuItems.length - 1) {
if (menuItems[i].addMenuSeparatorAfter) { var menuSeparatorComponent = Qt.createComponent("GeneralMenuSeparator.qml", Component.PreferSynchronous, root);
// If the QML file to be loaded is a local file, var menuSeparatorComponentObj = menuSeparatorComponent.createObject();
// you could omit the finishCreation() function generalMenuSeparatorList.push(menuSeparatorComponentObj);
var menuSeparatorComponent = Qt.createComponent("GeneralMenuSeparator.qml", Component.PreferSynchronous, root); root.addItem(menuSeparatorComponentObj);
var menuSeparatorComponentObj = menuSeparatorComponent.createObject(); }
generalMenuSeparatorList.push(menuSeparatorComponentObj); if (menuItems[i].addMenuSeparatorAfter) {
root.addItem(menuSeparatorComponentObj); var menuSeparatorComponent = Qt.createComponent("GeneralMenuSeparator.qml", Component.PreferSynchronous, root);
var menuSeparatorComponentObj = menuSeparatorComponent.createObject(root, {
"separatorColor": "#DEDEDE",
"separatorPreferredHeight": 0
});
generalMenuSeparatorList.push(menuSeparatorComponentObj);
root.addItem(menuSeparatorComponentObj);
var menuSeparatorComponent = Qt.createComponent("GeneralMenuSeparator.qml", Component.PreferSynchronous, root);
var menuSeparatorComponentObj = menuSeparatorComponent.createObject();
generalMenuSeparatorList.push(menuSeparatorComponentObj);
root.addItem(menuSeparatorComponentObj);
}
} }
} }
root.addItem(menuBottomBorder); root.addItem(menuBottomBorder);
@ -77,28 +88,22 @@ Menu {
root.close(); root.close();
} }
modal: true
Overlay.modal: Rectangle {
color: "transparent"
}
font.pointSize: JamiTheme.menuFontSize font.pointSize: JamiTheme.menuFontSize
background: Rectangle { background: Rectangle {
id: container
implicitWidth: menuPreferredWidth ? menuPreferredWidth : JamiTheme.menuItemsPreferredWidth implicitWidth: menuPreferredWidth ? menuPreferredWidth : JamiTheme.menuItemsPreferredWidth
border.width: JamiTheme.menuItemsCommonBorderWidth color: JamiTheme.primaryBackgroundColor
border.color: JamiTheme.tabbarBorderColor radius: 5
color: JamiTheme.backgroundColor
layer.enabled: true layer.enabled: true
layer.effect: DropShadow { layer.effect: DropShadow {
z: -1 z: -1
horizontalOffset: 3.0 horizontalOffset: 0.0
verticalOffset: 3.0 verticalOffset: 3.0
radius: 16.0 radius: 6
color: JamiTheme.shadowColor color: "#29000000"
transparentBorder: true transparentBorder: true
samples: radius + 1 samples: radius + 1
} }

View File

@ -30,6 +30,8 @@ Loader {
active: false active: false
visible: false
function openMenu() { function openMenu() {
root.active = true; root.active = true;
root.sourceComponent = menuComponent; root.sourceComponent = menuComponent;

View File

@ -1,6 +1,5 @@
/* /*
* Copyright (C) 2020-2023 Savoir-faire Linux Inc. * Copyright (C) 2020-2023 Savoir-faire Linux Inc.
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -32,34 +31,41 @@ MenuItem {
property alias iconSource: contextMenuItemImage.source property alias iconSource: contextMenuItemImage.source
property string iconColor: "" property string iconColor: ""
property bool canTrigger: true property bool canTrigger: true
property bool hasIcon: true
property bool addMenuSeparatorAfter: false property bool addMenuSeparatorAfter: false
property bool autoTextSizeAdjustment: true property bool autoTextSizeAdjustment: true
property bool dangerous: false property bool dangerous: false
property BaseContextMenu parentMenu property BaseContextMenu parentMenu
property bool isActif: true
property int itemPreferredWidth: JamiTheme.menuItemsPreferredWidth property int itemPreferredWidth: hasIcon ? 50 + contextMenuItemText.contentWidth + contextMenuItemImage.width : 35 + contextMenuItemText.contentWidth
property int itemRealWidth: itemPreferredWidth
property int itemPreferredHeight: JamiTheme.menuItemsPreferredHeight property int itemPreferredHeight: JamiTheme.menuItemsPreferredHeight
property int leftBorderWidth: JamiTheme.menuItemsCommonBorderWidth property int leftBorderWidth: JamiTheme.menuItemsCommonBorderWidth
property int rightBorderWidth: JamiTheme.menuItemsCommonBorderWidth property int rightBorderWidth: JamiTheme.menuItemsCommonBorderWidth
property int itemImageLeftMargin: 24 property int itemImageLeftMargin: 10
property int itemTextMargin: 20 property int itemTextMargin: 10
signal clicked signal clicked
property bool itemHovered: menuItemContentRect.hovered property bool itemHovered: menuItemContentRect.hovered
contentItem: AbstractButton { width: itemRealWidth
contentItem: PushButton {
id: menuItemContentRect id: menuItemContentRect
background: Rectangle { enabled: isActif
id: background hoverEnabled: isActif
anchors.fill: parent hoveredColor: JamiTheme.hoverColor
anchors.leftMargin: 1 normalColor: JamiTheme.primaryBackgroundColor
anchors.rightMargin: 1 circled: false
radius: 5
color: menuItemContentRect.hovered ? JamiTheme.hoverColor : JamiTheme.backgroundColor //duration: 1000
} anchors.leftMargin: 6
anchors.rightMargin: 6
anchors.fill: parent anchors.fill: parent
@ -76,41 +82,25 @@ MenuItem {
visible: status === Image.Ready visible: status === Image.Ready
color: iconColor !== "" ? iconColor : JamiTheme.textColor color: menuItemContentRect.hovered ? JamiTheme.textColor : JamiTheme.chatViewFooterImgColor
opacity: 0.7
} }
Text { Item {
id: contextMenuItemText
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: contextMenuItemImage.status === Image.Ready ? itemTextMargin : itemTextMargin / 2 Layout.leftMargin: contextMenuItemImage.status === Image.Ready ? itemTextMargin : itemTextMargin
Layout.rightMargin: contextMenuItemImage.status === Image.Ready ? itemTextMargin : itemTextMargin / 2 Layout.rightMargin: contextMenuItemImage.status === Image.Ready ? itemImageLeftMargin : itemTextMargin
Layout.preferredHeight: itemPreferredHeight Layout.preferredHeight: itemPreferredHeight
Layout.fillWidth: true Layout.fillWidth: true
text: itemName Text {
color: dangerous ? JamiTheme.redColor : JamiTheme.textColor id: contextMenuItemText
font.pointSize: JamiTheme.textFontSize height: parent.height
horizontalAlignment: Text.AlignLeft text: itemName
verticalAlignment: Text.AlignVCenter color: dangerous ? JamiTheme.redColor : isActif ? JamiTheme.textColor : JamiTheme.chatViewFooterImgColor
font.pointSize: JamiTheme.textFontSize
TextMetrics { horizontalAlignment: Text.AlignLeft
id: contextMenuItemTextMetrics verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
font: contextMenuItemText.font
text: contextMenuItemText.text
onBoundingRectChanged: {
var sizeToCompare = itemPreferredWidth - (contextMenuItemImage.source.toString().length > 0 ? itemTextMargin + itemImageLeftMargin + contextMenuItemImage.width : itemTextMargin / 2);
if (autoTextSizeAdjustment && boundingRect.width > sizeToCompare) {
if (boundingRect.width > JamiTheme.contextMenuItemTextMaxWidth) {
itemPreferredWidth += JamiTheme.contextMenuItemTextMaxWidth - JamiTheme.contextMenuItemTextPreferredWidth + itemTextMargin;
contextMenuItemText.elide = Text.ElideRight;
} else
itemPreferredWidth += boundingRect.width + itemTextMargin - sizeToCompare;
}
}
} }
} }
} }
@ -130,7 +120,9 @@ MenuItem {
anchors.leftMargin: leftBorderWidth anchors.leftMargin: leftBorderWidth
anchors.rightMargin: rightBorderWidth anchors.rightMargin: rightBorderWidth
implicitWidth: itemPreferredWidth color: JamiTheme.primaryBackgroundColor
implicitWidth: itemRealWidth
implicitHeight: itemPreferredHeight implicitHeight: itemPreferredHeight
border.width: 0 border.width: 0
@ -141,7 +133,7 @@ MenuItem {
rBorderwidth: rightBorderWidth rBorderwidth: rightBorderWidth
tBorderwidth: 0 tBorderwidth: 0
bBorderwidth: 0 bBorderwidth: 0
borderColor: JamiTheme.tabbarBorderColor borderColor: JamiTheme.primaryBackgroundColor
} }
} }
} }

View File

@ -0,0 +1,231 @@
/*
* Copyright (C) 2020-2023 Savoir-faire Linux Inc.
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import net.jami.Constants 1.1
import "../"
import net.jami.Adapters 1.1
// General menu item.
// Can control top, bottom, left, right border width.
// Use onClicked slot to simulate item click event.
// Can have image icon at the left of the text.
MenuItem {
id: menuItem
property var modelList: undefined
property string itemName: ""
property var iconSource: undefined
property string iconColor: ""
property bool canTrigger: true
property bool hasIcon: true
property bool addMenuSeparatorAfter: false
property bool autoTextSizeAdjustment: true
property bool dangerous: false
property BaseContextMenu parentMenu
property string messageId
signal addMoreEmoji
property int itemPreferredWidth: 207
property int itemRealWidth: itemPreferredWidth
property int itemPreferredHeight: JamiTheme.menuItemsPreferredHeight
property int leftBorderWidth: JamiTheme.menuItemsCommonBorderWidth
property int rightBorderWidth: JamiTheme.menuItemsCommonBorderWidth
property int itemImageLeftMargin: 18
signal clicked
width: itemRealWidth
contentItem: Item {
id: menuItemContentRect
anchors.fill: parent
RowLayout {
spacing: 0
anchors.fill: menuItemContentRect
Rectangle {
id: contextMenuItemImage
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: itemImageLeftMargin
height: 36
width: 36
color: emojiReplied.includes(modelList[0]) ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor
radius: 5
Behavior on color {
ColorAnimation {
duration: JamiTheme.shortFadeDuration
}
}
Text {
anchors.centerIn: parent
text: modelList[0]
font.pointSize: JamiTheme.emojiBubbleSize
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
contextMenuItemImage.color = JamiTheme.hoveredButtonColor;
}
onExited: {
contextMenuItemImage.color = emojiReplied.includes(modelList[0]) ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor;
}
onClicked: {
if (emojiReplied.includes(modelList[0])) {
MessagesAdapter.removeEmojiReaction(CurrentConversation.id, modelList[0], msgId);
} else {
MessagesAdapter.addEmojiReaction(CurrentConversation.id, modelList[0], msgId);
}
close();
}
}
}
Rectangle {
id: contextMenuItemImage2
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: itemImageLeftMargin / 2
height: 36
width: 36
color: emojiReplied.includes(modelList[1]) ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor
radius: 5
Behavior on color {
ColorAnimation {
duration: JamiTheme.shortFadeDuration
}
}
Text {
anchors.centerIn: parent
text: modelList[1]
font.pointSize: JamiTheme.emojiBubbleSize
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
contextMenuItemImage2.color = JamiTheme.hoveredButtonColor;
}
onExited: {
contextMenuItemImage2.color = emojiReplied.includes(modelList[1]) ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor;
}
onClicked: {
if (emojiReplied.includes(modelList[1])) {
MessagesAdapter.removeEmojiReaction(CurrentConversation.id, modelList[1], msgId);
} else {
MessagesAdapter.addEmojiReaction(CurrentConversation.id, modelList[1], msgId);
}
close();
}
}
}
Rectangle {
id: contextMenuItemImage3
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: itemImageLeftMargin / 2
height: 36
width: 36
color: emojiReplied.includes(modelList[2]) ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor
radius: 5
Behavior on color {
ColorAnimation {
duration: JamiTheme.shortFadeDuration
}
}
Text {
anchors.centerIn: parent
text: modelList[2]
font.pointSize: JamiTheme.emojiBubbleSize
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
contextMenuItemImage3.color = JamiTheme.hoveredButtonColor;
}
onExited: {
contextMenuItemImage3.color = emojiReplied.includes(modelList[2]) ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor;
}
onClicked: {
if (emojiReplied.includes(modelList[2])) {
MessagesAdapter.removeEmojiReaction(CurrentConversation.id, modelList[2], msgId);
} else {
MessagesAdapter.addEmojiReaction(CurrentConversation.id, modelList[2], msgId);
}
close();
}
}
}
PushButton {
id: contextMenuItemImage4
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: itemImageLeftMargin / 2
Layout.rightMargin: itemImageLeftMargin
height: 36
width: 36
imageColor: hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor
normalColor: JamiTheme.primaryBackgroundColor
radius: 5
source: iconSource
onClicked: {
root.addMoreEmoji();
}
}
}
}
highlighted: true
background: Rectangle {
id: contextMenuBackgroundRect
anchors.fill: parent
anchors.leftMargin: leftBorderWidth
anchors.rightMargin: rightBorderWidth
color: JamiTheme.primaryBackgroundColor
implicitWidth: itemRealWidth
implicitHeight: itemPreferredHeight
border.width: 0
CustomBorder {
commonBorder: false
lBorderwidth: leftBorderWidth
rBorderwidth: rightBorderWidth
tBorderwidth: 0
bBorderwidth: 0
borderColor: JamiTheme.primaryBackgroundColor
}
}
}

View File

@ -23,19 +23,24 @@ MenuSeparator {
id: menuSeparator id: menuSeparator
property int separatorPreferredWidth: JamiTheme.menuItemsPreferredWidth property int separatorPreferredWidth: JamiTheme.menuItemsPreferredWidth
property int separatorPreferredHeight: 1 property int separatorPreferredHeight: 5
property string separatorColor: JamiTheme.tabbarBorderColor property string separatorColor: JamiTheme.primaryBackgroundColor
padding: 0 padding: 0
topPadding: 1 topPadding: 1
bottomPadding: 1 bottomPadding: 1
contentItem: Rectangle { contentItem: Rectangle {
implicitWidth: separatorPreferredWidth implicitWidth: separatorPreferredWidth
implicitHeight: separatorPreferredHeight implicitHeight: separatorPreferredHeight
color: separatorColor color: separatorColor
radius: 5
} }
background: Rectangle { background: Rectangle {
color: JamiTheme.backgroundColor width: parent.width - 10
anchors.horizontalCenter: parent.horizontalCenter
color: separatorColor
radius: 5
} }
} }

View File

@ -0,0 +1,228 @@
/*
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "connectioninfolistmodel.h"
ConnectionInfoListModel::ConnectionInfoListModel(LRCInstance* instance, QObject* parent)
: AbstractListModelBase(parent)
{
lrcInstance_ = instance;
connect(lrcInstance_,
&LRCInstance::currentAccountIdChanged,
this,
&ConnectionInfoListModel::resetData);
}
int
ConnectionInfoListModel::rowCount(const QModelIndex& parent) const
{
return peerIds_.size();
}
QVariant
ConnectionInfoListModel::data(const QModelIndex& index, int role) const
{
const auto accountId = lrcInstance_->get_currentAccountId();
if (accountId.isEmpty()) {
qWarning() << "ConnectionInfoListModel::data: accountId or peerID is empty";
return {};
}
const auto peerId = peerIds_[index.row()];
const auto peerData = peerData_[peerId];
switch (role) {
case ConnectionInfoList::ChannelsMap: {
QVariantMap channelsMapMap;
int i = 0;
for (const auto& device : peerData.keys()) {
QString channelsId = peerData[device]["id"].toString();
QVariantMap channelsMap;
const auto channelInfoList = lrcInstance_->getChannelList(accountId, channelsId);
for (const auto& channelInfo : channelInfoList) {
channelsMap.insert(channelInfo["id"], channelInfo["name"]);
}
channelsMapMap.insert(QString::number(i++), channelsMap);
}
return QVariant(channelsMapMap);
}
case ConnectionInfoList::ConnectionDatas: {
QString peerString;
peerString += "Peer:" + peerId;
for (const auto& device : peerData.keys()) {
peerString += "{";
peerString += "Device:" + device + ",";
peerString += "Status:" + peerData[device]["status"].toString() + ",";
peerString += "Channels:" + peerData[device]["channels"].toString() + ",";
peerString += "Remote Address" + peerData[device]["remoteAddress"].toString();
peerString += "}";
}
return peerString;
}
case ConnectionInfoList::PeerId:
return peerId;
case ConnectionInfoList::RemoteAddress: {
QVariantMap remoteAddressMap;
int i = 0;
for (const auto& device : peerData.keys()) {
remoteAddressMap.insert(QString::number(i++), peerData[device]["remoteAddress"]);
}
return QVariant(remoteAddressMap);
}
case ConnectionInfoList::DeviceId: {
QVariantMap deviceMap;
int i = 0;
for (const auto& device : peerData.keys()) {
deviceMap.insert(QString::number(i++), device);
}
return QVariant(deviceMap);
}
case ConnectionInfoList::Status: {
QVariantMap statusMap;
int i = 0;
for (const auto& device : peerData.keys()) {
statusMap.insert(QString::number(i++), peerData[device]["status"]);
}
return QVariantMap(statusMap);
}
case ConnectionInfoList::Channels: {
QVariantMap channelsMap;
int i = 0;
for (const auto& device : peerData.keys()) {
channelsMap.insert(QString::number(i++), peerData[device]["channels"]);
}
return QVariant(channelsMap);
}
case ConnectionInfoList::Count:
return peerData.size();
}
return {};
}
QHash<int, QByteArray>
ConnectionInfoListModel::roleNames() const
{
using namespace ConnectionInfoList;
QHash<int, QByteArray> roles;
#define X(role) roles[role] = #role;
CONNECTONINFO_ROLES
#undef X
return roles;
}
void
ConnectionInfoListModel::update()
{
const auto accountId = lrcInstance_->get_currentAccountId();
if (accountId.isEmpty()) {
return;
}
aggregateData();
}
template<typename T>
std::tuple<QVector<T>, QVector<T>>
getSetDiff(QVector<T> u, QVector<T> v)
{
using namespace std;
QVector<T> a, r;
set_difference(v.begin(), v.end(), u.begin(), u.end(), inserter(a, a.begin()));
set_difference(u.begin(), u.end(), v.begin(), v.end(), inserter(r, r.begin()));
return {a, r};
}
void
ConnectionInfoListModel::aggregateData()
{
const auto accountId = lrcInstance_->get_currentAccountId();
if (accountId.isEmpty()) {
return;
}
connectionInfoList_ = lrcInstance_->getConnectionList(accountId);
peerData_ = {};
QSet<QString> newPeerIds;
for (const auto& connectionInfo : connectionInfoList_) {
if (!connectionInfo["peer"].isEmpty()) {
newPeerIds.insert(connectionInfo["peer"]);
}
const auto channelInfoList = lrcInstance_->getChannelList(accountId, connectionInfo["id"]);
peerData_[connectionInfo["peer"]][connectionInfo["device"]] = {};
peerData_[connectionInfo["peer"]][connectionInfo["device"]]["status"]
= connectionInfo["status"];
peerData_[connectionInfo["peer"]][connectionInfo["device"]]["channels"] = channelInfoList
.size();
peerData_[connectionInfo["peer"]][connectionInfo["device"]]["id"] = connectionInfo["id"];
peerData_[connectionInfo["peer"]][connectionInfo["device"]]["remoteAddress"]
= connectionInfo["remoteAddress"];
}
QVector<QString> oldVector;
for (const auto& peerId : peerIds_) {
oldVector << peerId;
}
QVector<QString> newVector;
for (const auto& peerId : newPeerIds) {
newVector << peerId;
}
std::sort(oldVector.begin(), oldVector.end());
std::sort(newVector.begin(), newVector.end());
QVector<QString> removed, added;
std::tie(added, removed) = getSetDiff(oldVector, newVector);
Q_FOREACH (const auto& key, added) {
auto index = std::distance(newVector.begin(),
std::find(newVector.begin(), newVector.end(), key));
beginInsertRows(QModelIndex(), index, index);
peerIds_.insert(index, key);
endInsertRows();
}
Q_FOREACH (const auto& key, removed) {
auto index = std::distance(oldVector.begin(),
std::find(oldVector.begin(), oldVector.end(), key));
beginRemoveRows(QModelIndex(), index, index);
if (peerIds_.size() > index) {
peerIds_.remove(index);
} else {
qWarning() << "ConnectionInfoListModel::aggregateData: index out of range";
qWarning() << "index: " << index;
qWarning() << "key: " << key;
}
endRemoveRows();
}
// HACK: loop through all the peerIds_ and update the data for each one.
// This is not efficient, but it works.
Q_FOREACH (const auto& peerId, peerIds_) {
auto index = std::distance(peerIds_.begin(),
std::find(peerIds_.begin(), peerIds_.end(), peerId));
Q_EMIT dataChanged(this->index(index), this->index(index));
}
}
void
ConnectionInfoListModel::resetData()
{
beginResetModel();
peerIds_.clear();
peerData_.clear();
endResetModel();
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "abstractlistmodelbase.h"
#define CONNECTONINFO_ROLES \
X(ConnectionDatas) \
X(ChannelsMap) \
X(PeerName) \
X(PeerId) \
X(DeviceId) \
X(Status) \
X(Channels) \
X(RemoteAddress) \
X(Count) // this is the number of connections (convenience)
namespace ConnectionInfoList {
Q_NAMESPACE
enum Role {
DummyRole = Qt::UserRole + 1,
#define X(role) role,
CONNECTONINFO_ROLES
#undef X
};
Q_ENUM_NS(Role)
} // namespace ConnectionInfoList
class ConnectionInfoListModel : public AbstractListModelBase
{
public:
explicit ConnectionInfoListModel(LRCInstance* instance, QObject* parent = nullptr);
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void update();
private:
using Role = ConnectionInfoList::Role;
VectorMapStringString connectionInfoList_;
QVector<QString> peerIds_;
QMap<QString, QMap<QString, QMap<QString, QVariant>>> peerData_;
void aggregateData();
void resetData();
};

View File

@ -20,6 +20,7 @@
pragma Singleton pragma Singleton
import QtQuick import QtQuick
import net.jami.Adapters 1.1 import net.jami.Adapters 1.1
import net.jami.Enums 1.1
Item { Item {
property string qmlFilePrefix: "file:/" property string qmlFilePrefix: "file:/"
@ -69,4 +70,13 @@ Item {
function clamp(val, min, max) { function clamp(val, min, max) {
return Math.min(Math.max(val, min), max); return Math.min(Math.max(val, min), max);
} }
function isDonationBannerVisible() {
// The banner is visible if the current date is after the date set in the settings and before the end date
// And if the donation toggle is checked
var isDonationVisible = UtilsAdapter.getAppValue(Settings.Key.IsDonationVisible);
var endDonationDate = new Date(Date.parse(UtilsAdapter.getAppValue(Settings.Key.DonationEndDate)));
var donationVisibleDate = new Date(Date.parse(UtilsAdapter.getAppValue(Settings.Key.DonationVisibleDate)));
return new Date() < endDonationDate && new Date() > donationVisibleDate && isDonationVisible && false;
}
} }

View File

@ -47,7 +47,7 @@ Item {
// AboutPopUp // AboutPopUp
property string version: qsTr("Version") + (AppVersionManager.isCurrentVersionBeta() ? " (Beta)" : "") property string version: qsTr("Version") + (AppVersionManager.isCurrentVersionBeta() ? " (Beta)" : "")
property string declarationYear: "© 2015-2023" property string declarationYear: "© 2015-2023"
property string slogan: "Világfa" property string slogan: "Eleutheria"
property string declaration: qsTr("Jami is a free universal communication software that respects the freedom and privacy of its users.") property string declaration: qsTr("Jami is a free universal communication software that respects the freedom and privacy of its users.")
// AccountComboBox // AccountComboBox
@ -83,6 +83,15 @@ Item {
property string selectNewRingtone: qsTr("Select a new ringtone") property string selectNewRingtone: qsTr("Select a new ringtone")
property string certificateFile: qsTr("Certificate File (*.crt)") property string certificateFile: qsTr("Certificate File (*.crt)")
property string audioFile: qsTr("Audio File (*.wav *.ogg *.opus *.mp3 *.aiff *.wma)") property string audioFile: qsTr("Audio File (*.wav *.ogg *.opus *.mp3 *.aiff *.wma)")
property string pushToTalk: qsTr("Push-to-talk")
property string enablePTT: qsTr("Enable push-to-talk")
property string keyboardShortcut: qsTr("Keyboard shortcut")
property string changeKeyboardShortcut: qsTr("Change keyboard shortcut")
// ChangePttKeyPopup
property string changeShortcut: qsTr("Change shortcut")
property string assignmentIndication: qsTr("Press the key to be assigned to push-to-talk shortcut")
property string assign: qsTr("Assign")
// AdvancedChatSettings // AdvancedChatSettings
property string enableReadReceipts: qsTr("Enable read receipts") property string enableReadReceipts: qsTr("Enable read receipts")
@ -436,7 +445,7 @@ Item {
// LinkedDevices // LinkedDevices
property string tipLinkNewDevice: qsTr("Link a new device to this account") property string tipLinkNewDevice: qsTr("Link a new device to this account")
property string linkNewDevice: qsTr("Exporting account…") property string linkDevice: qsTr("Exporting account…")
property string removeDevice: qsTr("Remove Device") property string removeDevice: qsTr("Remove Device")
property string sureToRemoveDevice: qsTr("Are you sure you wish to remove this device?") property string sureToRemoveDevice: qsTr("Are you sure you wish to remove this device?")
property string yourPinIs: qsTr("Your PIN is:") property string yourPinIs: qsTr("Your PIN is:")
@ -513,6 +522,8 @@ Item {
property string updateDownloading: "Downloading" property string updateDownloading: "Downloading"
property string confirmBeta: qsTr("This will uninstall your current Release version and you can always download the latest Release version on our website") property string confirmBeta: qsTr("This will uninstall your current Release version and you can always download the latest Release version on our website")
property string networkDisconnected: qsTr("Network disconnected") property string networkDisconnected: qsTr("Network disconnected")
property string accessError: qsTr("Content access error")
property string contentNotFoundError: qsTr("Content not found")
property string genericError: qsTr("Something went wrong") property string genericError: qsTr("Something went wrong")
//Troubleshoot Settings //Troubleshoot Settings
@ -575,13 +586,20 @@ Item {
// LinkDevicesDialog // LinkDevicesDialog
property string pinTimerInfos: qsTr("The PIN and the account password should be entered in your device within 10 minutes.") property string pinTimerInfos: qsTr("The PIN and the account password should be entered in your device within 10 minutes.")
property string close: qsTr("Close") property string close: qsTr("Close")
property string enterAccountPassword: qsTr("Enter account's password") property string enterAccountPassword: qsTr("Enter account password")
property string enterPasswordPinCode: qsTr("This account is password encrypted, enter the password to generate a PIN code.")
property string addDevice: qsTr("Add Device") property string addDevice: qsTr("Add Device")
property string pinExpired: qsTr("PIN expired")
property string onAnotherDevice: qsTr("On another device")
property string onAnotherDeviceInstruction: qsTr("Install and launch Jami, select \"Import from another device\" and scan the QR code.")
property string linkNewDevice: qsTr("Link new device")
property string linkingInstructions: qsTr("In Jami, scan QR code or manually enter the PIN.")
property string pinValidity: qsTr("The PIN code is valid for: ")
// PasswordDialog // PasswordDialog
property string enterPassword: qsTr("Enter the password") property string enterPassword: qsTr("Enter password")
property string enterCurrentPassword: qsTr("Enter current password") property string enterCurrentPassword: qsTr("Enter current password")
property string confirmRemoval: qsTr("Enter this account's password to confirm the removal of this device") property string confirmRemoval: qsTr("Enter account password to confirm the removal of this device")
property string enterNewPassword: qsTr("Enter new password") property string enterNewPassword: qsTr("Enter new password")
property string confirmNewPassword: qsTr("Confirm new password") property string confirmNewPassword: qsTr("Confirm new password")
property string change: qsTr("Change") property string change: qsTr("Change")
@ -724,6 +742,7 @@ Item {
property string showLess: qsTr("Show less") property string showLess: qsTr("Show less")
property string showPreview: qsTr("Show preview") property string showPreview: qsTr("Show preview")
property string continueEditing: qsTr("Continue editing")
property string bold: qsTr("Bold") property string bold: qsTr("Bold")
property string italic: qsTr("Italic") property string italic: qsTr("Italic")
property string strikethrough: qsTr("Strikethrough") property string strikethrough: qsTr("Strikethrough")
@ -827,4 +846,30 @@ Item {
// Appearence // Appearence
property string theme: qsTr("Theme") property string theme: qsTr("Theme")
property string zoomLevel: qsTr("Text zoom level") property string zoomLevel: qsTr("Text zoom level")
//Donation campaign
property string donationTipBoxText: qsTr("Free and private sharing. <a href=\"https://jami.net/donate/\">Donate</a> to expand it.")
property string donation: qsTr("Donate")
property string donationText: qsTr("If you enjoy using Jami and believe in our mission, would you make a donation?")
property string notNow: qsTr("Not now")
property string enableDonation: qsTr("Enable donation campaign")
//Chat setting page
property string enter: qsTr("Enter")
property string shiftEnter: qsTr("Shift+Enter")
property string textFormattingDescription: qsTr("Enter or Shift+Enter to insert a new line")
property string textFormatting: qsTr("Text formatting")
//Connection monitoring
property string connected: qsTr("Connected")
property string connectingTLS: qsTr("Connecting TLS")
property string connectingICE: qsTr("Connecting ICE")
property string connecting: qsTr("Connecting")
property string waiting: qsTr("Waiting")
property string contact: qsTr("Contact")
property string connection: qsTr("Connection")
property string channels: qsTr("Channels")
property string copyAllData: qsTr("Copy all data")
property string remote: qsTr("Remote: ")
property string view: qsTr("View")
} }

View File

@ -76,7 +76,7 @@ Item {
property color greyBorderColor: "#333" property color greyBorderColor: "#333"
property color selectionBlue: darkTheme ? "#0061a5" : "#109ede" property color selectionBlue: darkTheme ? "#0061a5" : "#109ede"
property color hoverColor: darkTheme ? "#4d4d4d" : "#c7c7c7" property color hoverColor: darkTheme ? "#4d4d4d" : "#DEDEDE"
property color pressColor: darkTheme ? "#777" : "#c0c0c0" property color pressColor: darkTheme ? "#777" : "#c0c0c0"
property color selectedColor: darkTheme ? "#0e81c5" : "#e0e0e0" property color selectedColor: darkTheme ? "#0e81c5" : "#e0e0e0"
property color smartListHoveredColor: darkTheme ? "#4d4d4d" : "#dedede" property color smartListHoveredColor: darkTheme ? "#4d4d4d" : "#dedede"
@ -367,9 +367,9 @@ Item {
property int avatarReadReceiptSize: 18 property int avatarReadReceiptSize: 18
property int menuItemsPreferredWidth: 220 property int menuItemsPreferredWidth: 220
property int menuItemsPreferredHeight: 48 property int menuItemsPreferredHeight: 36
property int menuItemsCommonBorderWidth: 1 property int menuItemsCommonBorderWidth: 1
property int menuBorderPreferredHeight: 8 property int menuBorderPreferredHeight: 5
property real maximumWidthSettingsView: 516 property real maximumWidthSettingsView: 516
property real settingsHeaderpreferredHeight: 64 property real settingsHeaderpreferredHeight: 64
@ -492,6 +492,7 @@ Item {
// MessageBar // MessageBar
property int messageBarMarginSize: 10 property int messageBarMarginSize: 10
property int messageBarMinimumWidth: 438
// InvitationView // InvitationView
property real invitationViewAvatarSize: 112 property real invitationViewAvatarSize: 112
@ -532,6 +533,7 @@ Item {
// WizardView Welcome Page // WizardView Welcome Page
property real welcomeLabelPointSize: 30 property real welcomeLabelPointSize: 30
property var welcomeLogo: darkTheme ? JamiResources.logo_jami_standard_coul_white_svg : JamiResources.logo_jami_standard_coul_svg
property real welcomeLogoWidth: 100 property real welcomeLogoWidth: 100
property real welcomeLogoHeight: 100 property real welcomeLogoHeight: 100
property real wizardButtonWidth: 400 property real wizardButtonWidth: 400
@ -541,9 +543,9 @@ Item {
property real welcomeRectTopMargin: 90 property real welcomeRectTopMargin: 90
property real welcomePageSpacing: 13 property real welcomePageSpacing: 13
property real welcomeGridWidth: 3 * JamiTheme.tipBoxWidth + 2 * JamiTheme.welcomePageSpacing property real welcomeGridWidth: 3 * JamiTheme.tipBoxWidth + 2 * JamiTheme.welcomePageSpacing
property real welcomeHalfGridWidth: (welcomeGridWidth - JamiTheme.welcomePageSpacing) / 2 property real welcomeThirdGridWidth: (welcomeGridWidth - JamiTheme.welcomePageSpacing) / 3
property real welcomeShortGridWidth: 2 * JamiTheme.tipBoxWidth + JamiTheme.welcomePageSpacing property real welcomeShortGridWidth: 2 * JamiTheme.tipBoxWidth + JamiTheme.welcomePageSpacing
readonly property string welcomeBg: darkTheme ? JamiResources.bg_darkmode_id_jami_png : JamiResources.bg_lightmode_id_jami_png readonly property string welcomeBg: darkTheme ? JamiResources.background_don_dark_jpg : JamiResources.background_don_white_jpg
property color welcomeBlockColor: darkTheme ? "#4D000000" : "#4DFFFFFF" property color welcomeBlockColor: darkTheme ? "#4D000000" : "#4DFFFFFF"
// WizardView Advanced Account Settings // WizardView Advanced Account Settings
@ -643,6 +645,9 @@ Item {
property int settingsMenuHeaderButtonHeight: 50 property int settingsMenuHeaderButtonHeight: 50
property int settingsListViewsSpacing: 10 property int settingsListViewsSpacing: 10
// Link Device
property color pinBackgroundColor: "#D6E4EF"
// MaterialRadioButton // MaterialRadioButton
property int radioImageSize: 30 property int radioImageSize: 30
property color radioBackgroundColor: darkTheme ? "#303030" : "#F0EFEF" property color radioBackgroundColor: darkTheme ? "#303030" : "#F0EFEF"
@ -654,7 +659,22 @@ Item {
property color darkThemeCheckedColor: "#03B9E9" property color darkThemeCheckedColor: "#03B9E9"
property color darkThemeBorderColor: "#03B9E9" property color darkThemeBorderColor: "#03B9E9"
// Donation campaign
property color donationButtonTextColor: "#005699"
property color donationBackgroundColor: "#D5E4EF"
property string donationUrl: "https://jami.net/donate/"
//Connection monitoring
property color connectionMonitoringTableColor1: darkTheme ? "#4D4D4D" : "#f0efef"
property color connectionMonitoringTableColor2: darkTheme ? "#333333" : "#f6f5f5"
property color connectionMonitoringHeaderColor: darkTheme ? "#6F6F6F" : "#d1d1d1"
function setTheme(dark) { function setTheme(dark) {
darkTheme = dark; darkTheme = dark;
} }
//Chat setting page
property color chatSettingButtonBackgroundColor: darkTheme ? "#303030" : "#F0EFEF"
property color chatSettingButtonBorderColor: darkTheme ? "#03B9E9" : "#005699"
property color chatSettingButtonTextColor: textColor
} }

View File

@ -21,10 +21,16 @@
#include "contactadapter.h" #include "contactadapter.h"
#include "lrcinstance.h" #include "lrcinstance.h"
#include "qmlregister.h"
ContactAdapter::ContactAdapter(LRCInstance* instance, QObject* parent) ContactAdapter::ContactAdapter(LRCInstance* instance, QObject* parent)
: QmlAdapterBase(instance, parent) : QmlAdapterBase(instance, parent)
, connectionInfoListModel_(new ConnectionInfoListModel(lrcInstance_, this))
{ {
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS,
connectionInfoListModel_.get(),
"ConnectionInfoListModel");
selectableProxyModel_.reset(new SelectableProxyModel(this)); selectableProxyModel_.reset(new SelectableProxyModel(this));
if (lrcInstance_) { if (lrcInstance_) {
connectSignals(); connectSignals();
@ -246,6 +252,12 @@ ContactAdapter::removeContact(const QString& peerUri, bool banContact)
accInfo.contactModel->removeContact(peerUri, banContact); accInfo.contactModel->removeContact(peerUri, banContact);
} }
void
ContactAdapter::updateConnectionInfo()
{
connectionInfoListModel_->update();
}
void void
ContactAdapter::connectSignals() ContactAdapter::connectSignals()
{ {

View File

@ -21,6 +21,7 @@
#include "qmladapterbase.h" #include "qmladapterbase.h"
#include "smartlistmodel.h" #include "smartlistmodel.h"
#include "conversationlistmodel.h" #include "conversationlistmodel.h"
#include "connectioninfolistmodel.h"
#include <QObject> #include <QObject>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
@ -90,6 +91,7 @@ public:
Q_INVOKABLE void setSearchFilter(const QString& filter); Q_INVOKABLE void setSearchFilter(const QString& filter);
Q_INVOKABLE void contactSelected(int index); Q_INVOKABLE void contactSelected(int index);
Q_INVOKABLE void removeContact(const QString& peerUri, bool banContact); Q_INVOKABLE void removeContact(const QString& peerUri, bool banContact);
Q_INVOKABLE void updateConnectionInfo();
void connectSignals(); void connectSignals();
@ -104,6 +106,7 @@ private:
SmartListModel::Type listModeltype_; SmartListModel::Type listModeltype_;
QScopedPointer<SmartListModel> smartListModel_; QScopedPointer<SmartListModel> smartListModel_;
QScopedPointer<SelectableProxyModel> selectableProxyModel_; QScopedPointer<SelectableProxyModel> selectableProxyModel_;
QScopedPointer<ConnectionInfoListModel> connectionInfoListModel_;
QStringList defaultModerators_; QStringList defaultModerators_;

View File

@ -458,3 +458,15 @@ LRCInstance::set_selectedConvUid(QString selectedConvUid)
Q_EMIT selectedConvUidChanged(); Q_EMIT selectedConvUidChanged();
} }
} }
VectorMapStringString
LRCInstance::getConnectionList(const QString& accountId, const QString& uid)
{
return Lrc::getConnectionList(accountId, uid);
}
VectorMapStringString
LRCInstance::getChannelList(const QString& accountId, const QString& uid)
{
return Lrc::getChannelList(accountId, uid);
}

View File

@ -135,6 +135,10 @@ public:
return debugMode_; return debugMode_;
} }
VectorMapStringString getConnectionList(const QString& accountId, const QString& uid = {});
VectorMapStringString getChannelList(const QString& accountId, const QString& uid = {});
Q_SIGNALS: Q_SIGNALS:
void accountListChanged(); void accountListChanged();
void selectedConvUidChanged(); void selectedConvUidChanged();

View File

@ -20,6 +20,7 @@
*/ */
#include "mainapplication.h" #include "mainapplication.h"
#include "pttlistener.h"
#include "qmlregister.h" #include "qmlregister.h"
#include "appsettingsmanager.h" #include "appsettingsmanager.h"
@ -106,6 +107,7 @@ ScreenInfo::onPhysicalDotsPerInchChanged()
MainApplication::MainApplication(int& argc, char** argv) MainApplication::MainApplication(int& argc, char** argv)
: QApplication(argc, argv) : QApplication(argc, argv)
, isCleanupped(false)
{ {
const char* qtVersion = qVersion(); const char* qtVersion = qVersion();
qInfo() << "Using Qt runtime version:" << qtVersion; qInfo() << "Using Qt runtime version:" << qtVersion;
@ -132,6 +134,7 @@ MainApplication::init()
connectivityMonitor_.reset(new ConnectivityMonitor(this)); connectivityMonitor_.reset(new ConnectivityMonitor(this));
settingsManager_.reset(new AppSettingsManager(this)); settingsManager_.reset(new AppSettingsManager(this));
systemTray_.reset(new SystemTray(settingsManager_.get(), this)); systemTray_.reset(new SystemTray(settingsManager_.get(), this));
listener_ = new PTTListener(settingsManager_.get(), this);
QObject::connect(settingsManager_.get(), QObject::connect(settingsManager_.get(),
&AppSettingsManager::retranslate, &AppSettingsManager::retranslate,
@ -195,6 +198,12 @@ MainApplication::init()
engine_.get()->rootContext()->setContextProperty("WITH_WEBENGINE", QVariant(false)); engine_.get()->rootContext()->setContextProperty("WITH_WEBENGINE", QVariant(false));
#endif #endif
#ifdef APPSTORE
engine_.get()->rootContext()->setContextProperty("APPSTORE", QVariant(true));
#else
engine_.get()->rootContext()->setContextProperty("APPSTORE", QVariant(false));
#endif
initQmlLayer(); initQmlLayer();
settingsManager_->setValue(Settings::Key::StartMinimized, settingsManager_->setValue(Settings::Key::StartMinimized,
@ -231,7 +240,6 @@ MainApplication::initLrc(const QString& downloadUrl,
bool debugMode, bool debugMode,
bool muteDaemon) bool muteDaemon)
{ {
lrc::api::Lrc::cacheAvatars.store(false);
/* /*
* Init mainwindow and finish splash when mainwindow shows up. * Init mainwindow and finish splash when mainwindow shows up.
*/ */
@ -351,6 +359,7 @@ MainApplication::initQmlLayer()
auto videoProvider = new VideoProvider(lrcInstance_->avModel(), this); auto videoProvider = new VideoProvider(lrcInstance_->avModel(), this);
engine_->rootContext()->setContextProperty("videoProvider", videoProvider); engine_->rootContext()->setContextProperty("videoProvider", videoProvider);
engine_->rootContext()->setContextProperty("pttListener", listener_);
engine_->load(QUrl(QStringLiteral("qrc:/MainApplicationWindow.qml"))); engine_->load(QUrl(QStringLiteral("qrc:/MainApplicationWindow.qml")));
qWarning().noquote() << "Main window loaded using" << getRenderInterfaceString(); qWarning().noquote() << "Main window loaded using" << getRenderInterfaceString();
@ -402,13 +411,17 @@ MainApplication::initSystray()
void void
MainApplication::cleanup() MainApplication::cleanup()
{ {
QApplication::exit(0); // In Qt 6.5, QApplication::exit(0) will signal aboutToQuit, and aboutToQuit is connected to cleanup
// TODO: delete cleanup.
if (!isCleanupped) {
isCleanupped = true;
QApplication::exit(0);
}
} }
#ifdef Q_OS_MACOS
void void
MainApplication::setEventFilter() MainApplication::setEventFilter()
{ {
installEventFilter(this); installEventFilter(this);
} }
#endif

View File

@ -23,6 +23,7 @@
#include "imagedownloader.h" #include "imagedownloader.h"
#include "lrcinstance.h" #include "lrcinstance.h"
#include "qtutils.h" #include "qtutils.h"
#include "pttlistener.h"
#include <QFile> #include <QFile>
#include <QApplication> #include <QApplication>
@ -82,17 +83,20 @@ public:
return runOptions_[opt]; return runOptions_[opt];
}; };
#ifdef Q_OS_MACOS
Q_INVOKABLE void setEventFilter(); Q_INVOKABLE void setEventFilter();
bool eventFilter(QObject* object, QEvent* event) bool eventFilter(QObject* object, QEvent* event)
{ {
#ifdef Q_OS_MACOS
if (event->type() == QEvent::ApplicationActivate) { if (event->type() == QEvent::ApplicationActivate) {
restoreApp(); restoreApp();
} }
#endif // Q_OS_MACOS
return QApplication::eventFilter(object, event); return QApplication::eventFilter(object, event);
} }
#endif // Q_OS_MACOS
Q_SIGNALS: Q_SIGNALS:
void closeRequested(); void closeRequested();
@ -120,5 +124,9 @@ private:
QScopedPointer<SystemTray> systemTray_; QScopedPointer<SystemTray> systemTray_;
QScopedPointer<ImageDownloader> imageDownloader_; QScopedPointer<ImageDownloader> imageDownloader_;
PTTListener* listener_;
ScreenInfo screenInfo_; ScreenInfo screenInfo_;
bool isCleanupped;
}; };

View File

@ -26,191 +26,169 @@ import "../../commoncomponents"
BaseModalDialog { BaseModalDialog {
id: root id: root
margins: JamiTheme.preferredMarginSize
width: Math.min(parent.width - 2 * JamiTheme.preferredMarginSize, JamiTheme.secondaryDialogDimension)
height: Math.min(parent.height - 2 * JamiTheme.preferredMarginSize, JamiTheme.secondaryDialogDimension)
popupContentMargins: 14
PushButton {
id: btnClose
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: JamiTheme.preferredMarginSize
anchors.rightMargin: JamiTheme.preferredMarginSize
imageColor: "grey"
normalColor: JamiTheme.transparentColor
source: JamiResources.round_close_24dp_svg
onClicked: {
close();
}
}
popupContent: JamiFlickable { popupContent: JamiFlickable {
id: aboutPopUpScrollView id: aboutPopUpScrollView
width: aboutPopUpContentRectColumnLayout.implicitWidth
height: JamiTheme.preferredDialogHeight
width: root.width contentHeight: aboutPopUpContentRectColumnLayout.implicitHeight
contentHeight: aboutPopUpContentRectColumnLayout.implicitHeight
ColumnLayout { ColumnLayout {
id: aboutPopUpContentRectColumnLayout id: aboutPopUpContentRectColumnLayout
anchors.centerIn: parent
width: root.width ResponsiveImage {
id: aboutPopUPJamiLogoImage
ResponsiveImage { Layout.alignment: Qt.AlignCenter
id: aboutPopUPJamiLogoImage Layout.preferredWidth: JamiTheme.aboutLogoPreferredWidth
Layout.preferredHeight: JamiTheme.aboutLogoPreferredHeight
Layout.alignment: Qt.AlignCenter source: JamiTheme.darkTheme ? JamiResources.logo_jami_standard_coul_white_svg : JamiResources.logo_jami_standard_coul_svg
Layout.topMargin: JamiTheme.preferredMarginSize
Layout.preferredWidth: JamiTheme.aboutLogoPreferredWidth
Layout.preferredHeight: JamiTheme.aboutLogoPreferredHeight
source: JamiTheme.darkTheme ? JamiResources.logo_jami_standard_coul_white_svg : JamiResources.logo_jami_standard_coul_svg
}
TextEdit {
id: jamiSlogansText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: aboutPopUpScrollView.width
Layout.topMargin: 26
wrapMode: Text.WordWrap
font.pixelSize: JamiTheme.bigFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: textMetricsjamiSlogansText.text
selectByMouse: true
readOnly: true
color: JamiTheme.tintedBlue
TextMetrics {
id: textMetricsjamiSlogansText
font: jamiSlogansText.font
text: JamiStrings.slogan
}
}
TextEdit {
id: jamiVersionText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: aboutPopUpScrollView.width
font.pixelSize: JamiTheme.tinyCreditsTextSize
padding: 0
text: JamiStrings.version + ": " + UtilsAdapter.getVersionStr()
selectByMouse: true
readOnly: true
color: JamiTheme.textColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
TextEdit {
id: jamiDeclarationText
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: aboutPopUpScrollView.width - JamiTheme.preferredMarginSize * 2
Layout.topMargin: 15
wrapMode: Text.WordWrap
font.pixelSize: JamiTheme.creditsTextSize
color: JamiTheme.textColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
// TextMetrics does not work for multi-line.
text: JamiStrings.declaration
selectByMouse: true
readOnly: true
}
TextEdit {
id: jamiDeclarationHyperText
Layout.alignment: Qt.AlignCenter
// Strangely, hoveredLink works badly when width grows too large
Layout.preferredWidth: 50
Layout.topMargin: 15
color: JamiTheme.textColor
font.pixelSize: JamiTheme.creditsTextSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: textMetricsjamiDeclarationHyperText.text
textFormat: TextEdit.RichText
selectByMouse: true
readOnly: true
onLinkActivated: Qt.openUrlExternally(link)
TextMetrics {
id: textMetricsjamiDeclarationHyperText
font: jamiDeclarationHyperText.font
text: '<a href="https://jami.net" style="color: ' + JamiTheme.blueLinkColor + '">jami.net</a>'
} }
MouseArea { TextEdit {
anchors.fill: parent id: jamiSlogansText
// We don't want to eat clicks on the Text. Layout.alignment: Qt.AlignCenter
acceptedButtons: Qt.NoButton Layout.maximumWidth: JamiTheme.preferredDialogWidth - 2*JamiTheme.preferredMarginSize
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor Layout.topMargin: 26
}
}
TextEdit { wrapMode: Text.WordWrap
id: jamiNoneWarrantyHyperText font.pixelSize: JamiTheme.bigFontSize
Layout.alignment: Qt.AlignCenter horizontalAlignment: Text.AlignHCenter
Layout.preferredWidth: Math.min(390, root.width) verticalAlignment: Text.AlignVCenter
Layout.topMargin: 15
wrapMode: Text.WordWrap
font.pixelSize: JamiTheme.tinyCreditsTextSize
horizontalAlignment: Text.AlignHCenter text: textMetricsjamiSlogansText.text
verticalAlignment: Text.AlignTop selectByMouse: true
color: JamiTheme.textColor readOnly: true
color: JamiTheme.tintedBlue
text: textMetricsjamiNoneWarrantyHyperText.text TextMetrics {
textFormat: TextEdit.RichText id: textMetricsjamiSlogansText
selectByMouse: true font: jamiSlogansText.font
readOnly: true text: JamiStrings.slogan
onLinkActivated: Qt.openUrlExternally(link) }
TextMetrics {
id: textMetricsjamiNoneWarrantyHyperText
font: jamiDeclarationHyperText.font
text: JamiStrings.declarationYear + " " + '<a href="https://savoirfairelinux.com" style="color: ' + JamiTheme.blueLinkColor + '">Savoir-faire Linux Inc.</a><br>' + 'This program comes with absolutely no warranty. See the <a href="http://www.gnu.org/licenses/gpl-3.0.html" style="color: ' + JamiTheme.blueLinkColor + '">GNU General Public License</a>, version 3 or later for details.'
} }
MouseArea { TextEdit {
anchors.fill: parent id: jamiVersionText
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
ProjectCreditsScrollView { Layout.alignment: Qt.AlignCenter
id: projectCreditsScrollView Layout.maximumWidth: JamiTheme.preferredDialogWidth - 2*JamiTheme.preferredMarginSize
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: aboutPopUpScrollView.width - JamiTheme.preferredMarginSize * 2 font.pixelSize: JamiTheme.tinyCreditsTextSize
Layout.preferredHeight: 100
Layout.topMargin: 25 padding: 0
Layout.margins: JamiTheme.preferredMarginSize
} text: JamiStrings.version + ": " + UtilsAdapter.getVersionStr()
selectByMouse: true
readOnly: true
color: JamiTheme.textColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
TextEdit {
id: jamiDeclarationText
Layout.alignment: Qt.AlignCenter
Layout.maximumWidth: JamiTheme.preferredDialogWidth - 2*JamiTheme.preferredMarginSize
Layout.topMargin: 15
wrapMode: Text.WordWrap
font.pixelSize: JamiTheme.creditsTextSize
color: JamiTheme.textColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
// TextMetrics does not work for multi-line.
text: JamiStrings.declaration
selectByMouse: true
readOnly: true
}
TextEdit {
id: jamiDeclarationHyperText
Layout.alignment: Qt.AlignCenter
// Strangely, hoveredLink works badly when width grows too large
Layout.maximumWidth: JamiTheme.preferredDialogWidth - 2*JamiTheme.preferredMarginSize
Layout.topMargin: 15
color: JamiTheme.textColor
font.pixelSize: JamiTheme.creditsTextSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: textMetricsjamiDeclarationHyperText.text
textFormat: TextEdit.RichText
selectByMouse: true
readOnly: true
onLinkActivated: Qt.openUrlExternally(link)
TextMetrics {
id: textMetricsjamiDeclarationHyperText
font: jamiDeclarationHyperText.font
text: '<a href="https://jami.net" style="color: ' + JamiTheme.blueLinkColor + '">jami.net</a>'
}
MouseArea {
anchors.fill: parent
// We don't want to eat clicks on the Text.
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
TextEdit {
id: jamiNoneWarrantyHyperText
Layout.alignment: Qt.AlignCenter
Layout.maximumWidth: JamiTheme.preferredDialogWidth - 2*JamiTheme.preferredMarginSize
Layout.topMargin: 15
wrapMode: Text.WordWrap
font.pixelSize: JamiTheme.tinyCreditsTextSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignTop
color: JamiTheme.textColor
text: textMetricsjamiNoneWarrantyHyperText.text
textFormat: TextEdit.RichText
selectByMouse: true
readOnly: true
onLinkActivated: Qt.openUrlExternally(link)
TextMetrics {
id: textMetricsjamiNoneWarrantyHyperText
font: jamiDeclarationHyperText.font
text: JamiStrings.declarationYear + " " + '<a href="https://savoirfairelinux.com" style="color: ' + JamiTheme.blueLinkColor + '">Savoir-faire Linux Inc.</a><br>' + 'This program comes with absolutely no warranty. See the <a href="http://www.gnu.org/licenses/gpl-3.0.html" style="color: ' + JamiTheme.blueLinkColor + '">GNU General Public License</a>, version 3 or later for details.'
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
ProjectCreditsScrollView {
id: projectCreditsScrollView
Layout.alignment: Qt.AlignCenter
Layout.maximumWidth: JamiTheme.preferredDialogWidth - 2*JamiTheme.preferredMarginSize
Layout.preferredHeight: 100
Layout.topMargin: 25
Layout.margins: JamiTheme.preferredMarginSize
}
} }
} }
} }

View File

@ -203,61 +203,70 @@ ItemDelegate {
anchors.fill: parent anchors.fill: parent
color: menuItem.down ? "#c4aaaaaa" : menuItem.hovered ? "#c4777777" : "transparent" color: menuItem.down ? "#c4aaaaaa" : menuItem.hovered ? "#c4777777" : "transparent"
} }
contentItem: ColumnLayout { // After update to qt 6.4.3 the layout was broken, adding a Rectangle
// as top level in the contentIntem is a workaround which removal can be
// tested with newer qt versions
contentItem: Rectangle {
anchors.fill: parent anchors.fill: parent
spacing: 0 color: "transparent"
RowLayout { ColumnLayout {
Layout.fillWidth: true anchors.fill: parent
Layout.rightMargin: 15 spacing: 0
Layout.leftMargin: 20
Layout.fillHeight: true
Layout.alignment: {
if (menuAction.popupMode !== CallActionBar.ActionPopupMode.LayoutOption || TopMargin && BottomMargin) {
return Qt.AlignLeft | Qt.AlignVCenter;
}
if (TopMargin) {
Layout.bottomMargin = 4;
return Qt.AlignBottom;
}
Layout.topMargin = 4;
return Qt.AlignTop;
}
spacing: 6 RowLayout {
ResponsiveImage {
source: menuAction.popupMode === CallActionBar.ActionPopupMode.ListElement || menuAction.popupMode === CallActionBar.ActionPopupMode.LayoutOption ? IconSource : (menuItem.ListView.isCurrentItem ? JamiResources.check_box_24dp_svg : JamiResources.check_box_outline_blank_24dp_svg)
color: "white"
width: 20
height: 20
}
Text {
id: delegateText
Layout.fillWidth: true Layout.fillWidth: true
horizontalAlignment: Text.AlignLeft Layout.fillHeight: true
verticalAlignment: Text.AlignVCenter Layout.rightMargin: 15
text: menuAction.popupMode === CallActionBar.ActionPopupMode.ListElement || menuAction.popupMode === CallActionBar.ActionPopupMode.LayoutOption ? Name : DeviceName Layout.leftMargin: 20
elide: Text.ElideRight
font.pointSize: JamiTheme.participantFontSize Layout.alignment: {
color: "white" if (menuAction.popupMode !== CallActionBar.ActionPopupMode.LayoutOption || TopMargin && BottomMargin) {
return Qt.AlignLeft | Qt.AlignVCenter;
}
if (TopMargin) {
Layout.bottomMargin = 4;
return Qt.AlignBottom;
}
Layout.topMargin = 4;
return Qt.AlignTop;
}
spacing: 6
ResponsiveImage {
source: menuAction.popupMode === CallActionBar.ActionPopupMode.ListElement || menuAction.popupMode === CallActionBar.ActionPopupMode.LayoutOption ? IconSource : (menuItem.ListView.isCurrentItem ? JamiResources.check_box_24dp_svg : JamiResources.check_box_outline_blank_24dp_svg)
color: "white"
width: 20
height: 20
}
Text {
id: delegateText
Layout.fillWidth: true
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: menuAction.popupMode === CallActionBar.ActionPopupMode.ListElement || menuAction.popupMode === CallActionBar.ActionPopupMode.LayoutOption ? Name : DeviceName
elide: Text.ElideRight
font.pointSize: JamiTheme.participantFontSize
color: "white"
}
ResponsiveImage {
source: JamiResources.check_black_24dp_svg
color: "white"
width: 20
height: 20
visible: menuAction.popupMode === CallActionBar.ActionPopupMode.LayoutOption ? ActiveSetting : false
}
} }
ResponsiveImage { Rectangle {
source: JamiResources.check_black_24dp_svg id: buttonDiv
color: "white" visible: menuAction.popupMode === CallActionBar.ActionPopupMode.LayoutOption ? SectionEnd : false
width: 20 Layout.fillWidth: true
height: 20 height: 1
visible: menuAction.popupMode === CallActionBar.ActionPopupMode.LayoutOption ? ActiveSetting : false opacity: 0.2
border.width: 0
color: JamiTheme.separationLine
Layout.alignment: Qt.AlignBottom
} }
} }
Rectangle {
id: buttonDiv
visible: menuAction.popupMode === CallActionBar.ActionPopupMode.LayoutOption ? SectionEnd : false
Layout.fillWidth: true
height: 1
opacity: 0.2
border.width: 0
color: JamiTheme.separationLine
Layout.alignment: Qt.AlignBottom
}
} }
} }

View File

@ -25,7 +25,6 @@ import "../../commoncomponents"
Item { Item {
id: root id: root
property alias chatViewContainer: ongoingCallPage.chatViewContainer property alias chatViewContainer: ongoingCallPage.chatViewContainer
property alias contentView: callStackMainView property alias contentView: callStackMainView
@ -49,6 +48,16 @@ Item {
} }
} }
Connections {
target: CallOverlayModel
function onPttKeyPressed() {
CallAdapter.muteAudioToggle();
}
function onPttKeyReleased() {
CallAdapter.muteAudioToggle();
}
}
// TODO: this should all be done by listening to // TODO: this should all be done by listening to
// parent visibility change or parent `Component.onDestruction` // parent visibility change or parent `Component.onDestruction`
function needToCloseInCallConversationAndPotentialWindow() { function needToCloseInCallConversationAndPotentialWindow() {

View File

@ -106,13 +106,18 @@ Popup {
height: Top || Bottom ? 10 : 45 height: Top || Bottom ? 10 : 45
background: Rectangle { background: Rectangle {
radius: 5
visible: !Top && !Bottom visible: !Top && !Bottom
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 5
anchors.rightMargin: 5
color: menuItem.down ? "#c4aaaaaa" : menuItem.hovered ? "#c4777777" : "transparent" color: menuItem.down ? "#c4aaaaaa" : menuItem.hovered ? "#c4777777" : "transparent"
} }
RowLayout { RowLayout {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 5
anchors.rightMargin: 5
visible: !Top && !Bottom visible: !Top && !Bottom
ResponsiveImage { ResponsiveImage {
Layout.leftMargin: JamiTheme.preferredMarginSize Layout.leftMargin: JamiTheme.preferredMarginSize

View File

@ -169,12 +169,6 @@ Rectangle {
} }
} }
GenericErrorsRow {
id: genericError
Layout.fillWidth: true
Layout.preferredHeight: JamiTheme.chatViewHeaderPreferredHeight
}
ConversationErrorsRow { ConversationErrorsRow {
id: errorRect id: errorRect
Layout.fillWidth: true Layout.fillWidth: true

View File

@ -130,7 +130,7 @@ Rectangle {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: footerColumnLayout.width Layout.preferredWidth: footerColumnLayout.width
Layout.leftMargin: marginSize Layout.leftMargin: 0
Layout.rightMargin: marginSize Layout.rightMargin: marginSize
Layout.bottomMargin: marginSize Layout.bottomMargin: marginSize
Layout.preferredHeight: height Layout.preferredHeight: height

View File

@ -86,8 +86,7 @@ Rectangle {
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: 8 Layout.leftMargin: 8
preferredSize: 24 //preferredSize: 24
mirror: UtilsAdapter.isRTL mirror: UtilsAdapter.isRTL
source: JamiResources.back_24dp_svg source: JamiResources.back_24dp_svg
@ -155,12 +154,12 @@ Rectangle {
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.preferredHeight: 30 Layout.preferredHeight: 30
Layout.preferredWidth: 40 + (isOpen? JamiTheme.searchbarSize : 0) Layout.preferredWidth: 40 + (isOpen ? JamiTheme.searchbarSize : 0)
colorSearchBar: JamiTheme.backgroundColor colorSearchBar: JamiTheme.backgroundColor
hoverButtonRadius: JamiTheme.chatViewHeaderButtonRadius hoverButtonRadius: JamiTheme.chatViewHeaderButtonRadius
Behavior on Layout.preferredWidth { Behavior on Layout.preferredWidth {
NumberAnimation { NumberAnimation {
duration: 150 duration: 150
} }
@ -168,7 +167,7 @@ Rectangle {
visible: root.swarmDetailsVisibility visible: root.swarmDetailsVisibility
onSearchBarTextChanged: function(text){ onSearchBarTextChanged: function (text) {
MessagesAdapter.searchbarPrompt = text; MessagesAdapter.searchbarPrompt = text;
} }

View File

@ -28,11 +28,6 @@ BaseModalDialog {
property int type: ContactList.CONFERENCE property int type: ContactList.CONFERENCE
width: Math.min(appWindow.width - 2 * JamiTheme.preferredMarginSize, JamiTheme.preferredDialogWidth)
height: Math.min(appWindow.height - 2 * JamiTheme.preferredMarginSize, JamiTheme.preferredDialogHeight)
padding: 0
title: { title: {
switch (type) { switch (type) {
case ContactList.CONFERENCE: case ContactList.CONFERENCE:
@ -48,6 +43,8 @@ BaseModalDialog {
popupContent: ColumnLayout { popupContent: ColumnLayout {
id: contactPickerPopupRectColumnLayout id: contactPickerPopupRectColumnLayout
anchors.centerIn: parent
width: 400
Searchbar { Searchbar {
id: contactPickerContactSearchBar id: contactPickerContactSearchBar
@ -81,8 +78,4 @@ BaseModalDialog {
} }
} }
} }
onAboutToShow: {
contactPickerListView.model = ContactAdapter.getContactSelectableModel(type);
}
} }

View File

@ -104,7 +104,6 @@ ContextMenuAutoLoader {
canTrigger: hasCall canTrigger: hasCall
itemName: JamiStrings.endCall itemName: JamiStrings.endCall
iconSource: JamiResources.ic_call_end_white_24dp_svg iconSource: JamiResources.ic_call_end_white_24dp_svg
addMenuSeparatorAfter: contactType !== Profile.Type.SIP && (contactType === Profile.Type.PENDING || !hasCall)
onClicked: CallAdapter.hangUpACall(responsibleAccountId, responsibleConvUid) onClicked: CallAdapter.hangUpACall(responsibleAccountId, responsibleConvUid)
}, },
GeneralMenuItem { GeneralMenuItem {
@ -129,7 +128,6 @@ ContextMenuAutoLoader {
canTrigger: !hasCall && contactType !== Profile.Type.SIP && !root.isBanned && isCoreDialog && root.idText !== CurrentAccount.uri canTrigger: !hasCall && contactType !== Profile.Type.SIP && !root.isBanned && isCoreDialog && root.idText !== CurrentAccount.uri
itemName: JamiStrings.blockContact itemName: JamiStrings.blockContact
iconSource: JamiResources.block_black_24dp_svg iconSource: JamiResources.block_black_24dp_svg
addMenuSeparatorAfter: canTrigger
onClicked: { onClicked: {
var dlg = viewCoordinator.presentDialog(appWindow, "commoncomponents/ConfirmDialog.qml", { var dlg = viewCoordinator.presentDialog(appWindow, "commoncomponents/ConfirmDialog.qml", {
"title": JamiStrings.confirmAction, "title": JamiStrings.confirmAction,
@ -147,7 +145,6 @@ ContextMenuAutoLoader {
canTrigger: root.isBanned canTrigger: root.isBanned
itemName: JamiStrings.reinstateContact itemName: JamiStrings.reinstateContact
iconSource: JamiResources.round_remove_circle_24dp_svg iconSource: JamiResources.round_remove_circle_24dp_svg
addMenuSeparatorAfter: canTrigger
onClicked: MessagesAdapter.unbanConversation(responsibleConvUid) onClicked: MessagesAdapter.unbanConversation(responsibleConvUid)
}, },
GeneralMenuItem { GeneralMenuItem {

View File

@ -27,44 +27,26 @@ import "../../commoncomponents"
BaseModalDialog { BaseModalDialog {
id: root id: root
width: 488 width: JamiTheme.secondaryDialogDimension
height: 320
popupContent: Rectangle { title: JamiStrings.defaultCallHost
id: rect
color: JamiTheme.transparentColor popupContent: ColumnLayout {
width: root.width
PushButton {
id: btnCancel
imageColor: "grey"
normalColor: "transparent"
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 10
anchors.rightMargin: 10
source: JamiResources.round_close_24dp_svg
onClicked: {
close();
}
}
ColumnLayout {
id: mainLayout id: mainLayout
anchors.fill: parent
anchors.centerIn: parent
anchors.margins: JamiTheme.preferredMarginSize anchors.margins: JamiTheme.preferredMarginSize
spacing: JamiTheme.preferredMarginSize spacing: JamiTheme.preferredMarginSize
Label { Label {
id: informativeLabel id: informativeLabel
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true Layout.topMargin: JamiTheme.preferredMarginSize
Layout.topMargin: 26 Layout.preferredWidth: root.width - 4*JamiTheme.preferredMarginSize
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter wrapMode: Text.Wrap
verticalAlignment: Text.AlignVCenter
text: JamiStrings.chooseHoster text: JamiStrings.chooseHoster
color: JamiTheme.primaryForegroundColor color: JamiTheme.primaryForegroundColor
} }
@ -97,7 +79,7 @@ BaseModalDialog {
property bool isCurrent: DeviceName property bool isCurrent: DeviceName
implicitWidth: devicesListView.width implicitWidth: devicesListView.width
width: devicesListView.width width: root.width - 4*JamiTheme.preferredMarginSize
height: 70 height: 70
highlighted: ListView.isCurrentItem highlighted: ListView.isCurrentItem
@ -136,7 +118,6 @@ BaseModalDialog {
ColumnLayout { ColumnLayout {
id: deviceInfoColumnLayout id: deviceInfoColumnLayout
Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.leftMargin: JamiTheme.preferredMarginSize Layout.leftMargin: JamiTheme.preferredMarginSize
@ -144,7 +125,6 @@ BaseModalDialog {
id: labelDeviceName id: labelDeviceName
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillWidth: true
elide: Text.ElideRight elide: Text.ElideRight
color: JamiTheme.textColor color: JamiTheme.textColor
@ -155,7 +135,7 @@ BaseModalDialog {
id: labelDeviceId id: labelDeviceId
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillWidth: true Layout.preferredWidth: root.width - 200
elide: Text.ElideRight elide: Text.ElideRight
color: JamiTheme.textColor color: JamiTheme.textColor
@ -175,9 +155,10 @@ BaseModalDialog {
} }
} }
RowLayout { ColumnLayout {
id: buttonLayout
spacing: JamiTheme.preferredMarginSize spacing: JamiTheme.preferredMarginSize
Layout.preferredWidth: parent.width Layout.preferredWidth: root.width - 240
MaterialButton { MaterialButton {
id: chooseBtn id: chooseBtn
@ -192,8 +173,8 @@ BaseModalDialog {
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true Layout.fillWidth: true
primary: true primary: true
preferredWidth: chooseBtnTextSize.width + 2 * JamiTheme.buttontextWizzardPadding
enabled: devicesListView.currentItem enabled: devicesListView.currentItem
text: JamiStrings.chooseThisDevice text: JamiStrings.chooseThisDevice
@ -220,7 +201,6 @@ BaseModalDialog {
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true Layout.fillWidth: true
primary: true primary: true
preferredWidth: rmDeviceBtnTextSize.width + 2 * JamiTheme.buttontextWizzardPadding
enabled: devicesListView.currentItem enabled: devicesListView.currentItem
text: JamiStrings.removeCurrentDevice text: JamiStrings.removeCurrentDevice
@ -235,4 +215,4 @@ BaseModalDialog {
} }
} }
} }
}

View File

@ -0,0 +1,149 @@
/*
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
import net.jami.Enums 1.1
import net.jami.Models 1.1
import "../../commoncomponents"
import "../../settingsview/components"
Rectangle {
id: donation
property bool donationVisible: JamiQmlUtils.isDonationBannerVisible()
width: parent.width - 30
height: donationTextRect.height + 45 > donationIcon.height + 20 ? donationTextRect.height + 45 : donationIcon.height + 20
radius: 5
color: JamiTheme.donationBackgroundColor
GridLayout {
id: donationLayout
anchors.fill: parent
columns: 3
rows: 2
rowSpacing: 0
columnSpacing: 10
Rectangle {
id: donationIcon
Layout.row: 0
Layout.column: 0
Layout.rowSpan: 2
Layout.preferredHeight: 70
Layout.preferredWidth: 45
Layout.leftMargin: 10
Layout.topMargin: 10
Layout.bottomMargin: 15
color: JamiTheme.transparentColor
Image {
id: donationImage
height: parent.height
width: 50
anchors.centerIn: parent
source: JamiResources.icon_donate_svg
}
}
Rectangle {
id: donationTextRect
Layout.topMargin: 10
Layout.row: 0
Layout.column: 1
Layout.columnSpan: 2
Layout.preferredHeight: donationText.height
Layout.preferredWidth: parent.width - 74
Layout.bottomMargin: 5
color: JamiTheme.transparentColor
Text {
id: donationText
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
width: parent.width
height: contentHeight
text: JamiStrings.donationText
wrapMode: Text.WordWrap
font.pointSize: JamiTheme.textFontSize
}
}
Rectangle {
id: notNowRect
Layout.row: 1
Layout.column: 1
Layout.preferredHeight: 30
Layout.preferredWidth: (parent.width - 55) / 2
color: JamiTheme.transparentColor
Text {
id: notNowText
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
// When the user clicks on "Not now", we set the donation date to 7 days from now (1 for the test)
UtilsAdapter.setAppValue(Settings.Key.DonationVisibleDate, new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 16).replace("T", " "));
donation.donationVisible = Qt.binding(() => JamiQmlUtils.isDonationBannerVisible());
}
}
text: JamiStrings.notNow
color: JamiTheme.donationButtonTextColor
anchors.top: parent.top
anchors.left: parent.left
font.pointSize: JamiTheme.textFontSize
}
}
Rectangle {
id: donateRect
Layout.row: 1
Layout.column: 2
Layout.preferredHeight: 30
Layout.preferredWidth: (parent.width - 50) / 2
color: JamiTheme.transparentColor
Text {
id: donateText
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
Qt.openUrlExternally(JamiTheme.donationUrl);
}
}
text: JamiStrings.donation
font.pointSize: JamiTheme.textFontSize
color: JamiTheme.donationButtonTextColor
anchors.top: parent.top
anchors.left: parent.left
}
}
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
import "../../commoncomponents"
Item {
id: root
focus: true
width: parent.width
height: backupLayout.height
property real iconSize: 26
property real margin: 5
property real preferredWidth: 170
property real maxHeight: 250
property color textColor: JamiTheme.textColor
property color iconColor: JamiTheme.tintedBlue
ColumnLayout {
id: backupLayout
anchors.top: parent.top
width: parent.width
RowLayout {
id: rowlayout
Layout.leftMargin: 15
Layout.alignment: Qt.AlignLeft
ResponsiveImage {
id: icon
visible: !opened
Layout.alignment: Qt.AlignLeft
Layout.topMargin: root.margin
Layout.preferredWidth: root.iconSize
Layout.preferredHeight: root.iconSize
containerHeight: Layout.preferredHeight
containerWidth: Layout.preferredWidth
color: JamiTheme.tintedBlue
source: JamiResources.favorite_black_24dp_svg
}
Text {
id: title
text: JamiStrings.donation
color: root.textColor
font.weight: Font.Medium
Layout.topMargin: root.margin
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: root.margin
Layout.preferredWidth: root.preferredWidth - 2 * root.margin - root.iconSize
font.pixelSize: JamiTheme.tipBoxTitleFontSize
horizontalAlignment: Text.AlignLeft
elide: Qt.ElideRight
}
}
Text {
id: content
Layout.preferredWidth: root.preferredWidth
focus: true
Layout.leftMargin: 20
Layout.topMargin: 8
Layout.bottomMargin: 8
font.pixelSize: JamiTheme.tipBoxContentFontSize
visible: true
wrapMode: Text.WordWrap
font.weight: Font.Normal
text: JamiStrings.donationTipBoxText
color: root.textColor
horizontalAlignment: Text.AlignLeft
linkColor: JamiTheme.buttonTintedBlue
onLinkActivated: {
Qt.openUrlExternally(JamiTheme.donationUrl);
}
}
}
}

View File

@ -31,7 +31,11 @@ Rectangle {
property alias text: errorLabel.text property alias text: errorLabel.text
color: JamiTheme.filterBadgeColor color: JamiTheme.filterBadgeColor
visible: CurrentAccount.status === Account.Status.UNREGISTERED visible: CurrentAccount.id !== ""
&& CurrentAccount.status !== Account.Status.REGISTERED
&& CurrentAccount.status !== Account.Status.READY
&& CurrentAccount.status !== Account.Status.TRYING
&& CurrentAccount.status !== Account.Status.INITIALIZING
RowLayout { RowLayout {
anchors.fill: parent anchors.fill: parent
@ -41,7 +45,6 @@ Rectangle {
id: errorLabel id: errorLabel
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
text: CurrentAccount.enabled ? JamiStrings.noNetworkConnectivity : JamiStrings.disabledAccount
color: JamiTheme.filterBadgeTextColor color: JamiTheme.filterBadgeTextColor
font.pixelSize: JamiTheme.headerFontSize font.pixelSize: JamiTheme.headerFontSize
elide: Text.ElideRight elide: Text.ElideRight

View File

@ -26,45 +26,21 @@ import "../../commoncomponents"
BaseModalDialog { BaseModalDialog {
id: root id: root
width: 488
height: 256
property bool isAdmin: { property bool isAdmin: {
var role = UtilsAdapter.getParticipantRole(CurrentAccount.id, CurrentConversation.id, CurrentAccount.uri); var role = UtilsAdapter.getParticipantRole(CurrentAccount.id, CurrentConversation.id, CurrentAccount.uri);
return role === Member.Role.ADMIN; return role === Member.Role.ADMIN;
} }
popupContent: Rectangle { popupContent: ColumnLayout {
id: rect
color: JamiTheme.transparentColor
width: root.width
PushButton {
id: btnCancel
imageColor: "grey"
normalColor: "transparent"
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 10
anchors.rightMargin: 10
source: JamiResources.round_close_24dp_svg
onClicked: {
close();
}
}
ColumnLayout {
id: mainLayout id: mainLayout
anchors.fill: parent spacing: JamiTheme.preferredMarginSize
anchors.margins: JamiTheme.preferredMarginSize
Label { Label {
id: informativeLabel id: informativeLabel
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 26 Layout.maximumWidth: root.parent.width - 4*JamiTheme.preferredMarginSize
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
@ -77,7 +53,7 @@ BaseModalDialog {
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.topMargin: 26 Layout.margins: JamiTheme.preferredMarginSize
text: isAdmin ? JamiStrings.becomeHostOneCall : JamiStrings.hostThisCall text: isAdmin ? JamiStrings.becomeHostOneCall : JamiStrings.hostThisCall
onClicked: { onClicked: {
@ -90,6 +66,7 @@ BaseModalDialog {
id: becomeDefaultHostBtn id: becomeDefaultHostBtn
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.margins: JamiTheme.preferredMarginSize
text: JamiStrings.becomeDefaultHost text: JamiStrings.becomeDefaultHost
toolTipText: JamiStrings.becomeDefaultHost toolTipText: JamiStrings.becomeDefaultHost
@ -105,4 +82,4 @@ BaseModalDialog {
} }
} }
} }
} //}

View File

@ -170,7 +170,7 @@ Window {
description: qsTr("Stop camera") description: qsTr("Stop camera")
} }
ListElement { ListElement {
shortcut: "Ctrl" shortcut: "Ctrl + Mouse middle click"
description: qsTr("Take tile screenshot") description: qsTr("Take tile screenshot")
} }
}, },

View File

@ -54,12 +54,14 @@ RowLayout {
height: showTypo || multiLine ? messageBarTextArea.height + 25 + 3 * marginSize + 1 : textAreaObj.height + marginSize + 1 height: showTypo || multiLine ? messageBarTextArea.height + 25 + 3 * marginSize + 1 : textAreaObj.height + marginSize + 1
Rectangle { Rectangle {
Layout.preferredHeight: parent.height Layout.preferredHeight: parent.height
Layout.preferredWidth: childrenRect.width Layout.preferredWidth: childrenRect.width
visible: !CurrentConversation.isSip visible: !CurrentConversation.isSip
color: JamiTheme.transparentColor color: JamiTheme.transparentColor
ComboBox { ComboBox {
id: showMoreButton id: showMoreButton
focus: true
width: JamiTheme.chatViewFooterButtonSize width: JamiTheme.chatViewFooterButtonSize
height: JamiTheme.chatViewFooterButtonSize height: JamiTheme.chatViewFooterButtonSize
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -102,19 +104,20 @@ RowLayout {
toolTipMoreButton.text = sharePopup.opened ? JamiStrings.showLess : JamiStrings.showMore; toolTipMoreButton.text = sharePopup.opened ? JamiStrings.showLess : JamiStrings.showMore;
} }
onPressedChanged: { popup: ShareMenu {
if (sharePopup.enabled)
sharePopup.close();
}
popup: SharePopup {
id: sharePopup id: sharePopup
y: -180 onAudioRecordMessageButtonClicked: {
x: -20 root.audioRecordMessageButtonClicked();
}
menuMoreButton: listViewMoreButton.menuMoreButton onVideoRecordMessageButtonClicked: {
root.videoRecordMessageButtonClicked();
onClosed: messageBar.textAreaObj.forceActiveFocus() }
onShowMapClicked: {
root.showMapClicked();
}
modelList: listViewMoreButton.menuMoreButton
y: showMoreButton.y + 31
x: showMoreButton.x - 3
} }
} }
} }
@ -132,8 +135,6 @@ RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.rightMargin: marginSize
Layout.leftMargin: marginSize
radius: 5 radius: 5
color: JamiTheme.transparentColor color: JamiTheme.transparentColor
@ -142,12 +143,10 @@ RowLayout {
onWidthChanged: { onWidthChanged: {
height = Qt.binding(() => root.height); height = Qt.binding(() => root.height);
if (width < 468) { if (width < JamiTheme.messageBarMinimumWidth) {
showTypoSecond = false; showTypoSecond = false;
} else { } else {
if (width >= 468) { showTypoSecond = true;
showTypoSecond = true;
}
} }
} }
@ -219,32 +218,32 @@ RowLayout {
}, },
"Link": function () { "Link": function () {
if (!showPreview) { if (!showPreview) {
listViewTypoSecond.itemAtIndex(0).action.triggered(); listViewTypoFirst.itemAtIndex(4).action.triggered();
} }
}, },
"Code": function () { "Code": function () {
if (!showPreview) { if (!showPreview) {
listViewTypoSecond.itemAtIndex(1).action.triggered(); listViewTypoFirst.itemAtIndex(5).action.triggered();
} }
}, },
"Quote": function () { "Quote": function () {
if (!showPreview) { if (!showPreview) {
listViewTypoSecond.itemAtIndex(2).action.triggered(); listViewTypoSecond.itemAtIndex(0).action.triggered();
} }
}, },
"Unordered list": function () { "Unordered list": function () {
if (!showPreview) { if (!showPreview) {
listViewTypoSecond.itemAtIndex(3).action.triggered(); listViewTypoSecond.itemAtIndex(1).action.triggered();
} }
}, },
"Ordered list": function () { "Ordered list": function () {
if (!showPreview) { if (!showPreview) {
listViewTypoSecond.itemAtIndex(4).action.triggered(); listViewTypoSecond.itemAtIndex(2).action.triggered();
} }
}, },
"Enter is new line": function () { "Enter is new line": function () {
if (!showPreview) { if (!showPreview) {
listViewTypoSecond.itemAtIndex(5).action.triggered(); listViewTypoSecond.itemAtIndex(3).action.triggered();
} }
} }
} }
@ -308,6 +307,8 @@ RowLayout {
context: Qt.ApplicationShortcut context: Qt.ApplicationShortcut
onActivated: { onActivated: {
showTypo = !showTypo; showTypo = !showTypo;
messageBarTextArea.isShowTypo = showTypo;
UtilsAdapter.setAppValue(Settings.Key.ShowMardownOption, showTypo);
} }
} }
@ -671,11 +672,11 @@ RowLayout {
normalColor: { normalColor: {
if (showPreview) { if (showPreview) {
return JamiTheme.transparentColor; return JamiTheme.primaryBackgroundColor;
} else if (modelData.isStyle) { } else if (modelData.isStyle) {
return JamiTheme.hoveredButtonColor; return JamiTheme.hoveredButtonColor;
} else { } else {
return JamiTheme.transparentColor; return JamiTheme.primaryBackgroundColor;
} }
} }
imageColor: { imageColor: {
@ -698,7 +699,7 @@ RowLayout {
Rectangle { Rectangle {
height: JamiTheme.chatViewFooterButtonSize height: JamiTheme.chatViewFooterButtonSize
color: JamiTheme.transparentColor color: JamiTheme.primaryBackgroundColor
visible: showTypo && showTypoSecond visible: showTypo && showTypoSecond
width: 2 width: 2
@ -713,7 +714,7 @@ RowLayout {
Rectangle { Rectangle {
z: -1 z: -1
radius: 0 radius: 0
color: JamiTheme.transparentColor color: JamiTheme.primaryBackgroundColor
width: JamiTheme.chatViewFooterButtonSize width: JamiTheme.chatViewFooterButtonSize
height: JamiTheme.chatViewFooterButtonSize height: JamiTheme.chatViewFooterButtonSize
@ -762,7 +763,7 @@ RowLayout {
id: markdownPopup id: markdownPopup
y: 1.5 * parent.height y: 1.5 * parent.height
x: -parent.width * 2 x: -parent.width * 2
width: 155 width: 105
height: JamiTheme.chatViewFooterButtonSize height: JamiTheme.chatViewFooterButtonSize
menuTypoActionsSecond: listViewTypoSecond.menuTypoActionsSecond menuTypoActionsSecond: listViewTypoSecond.menuTypoActionsSecond
@ -818,20 +819,6 @@ RowLayout {
onTriggered: function clickAction() { onTriggered: function clickAction() {
listViewTypo.addPrefixStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "", true); listViewTypo.addPrefixStyle(root.text, messageBarTextArea.selectionStart, messageBarTextArea.selectionEnd, "", true);
} }
},
Action {
id: shiftEnterActiom
property var iconSrc: JamiResources.shift_enter_black_24dp_svg
property var shortcutText: chatViewEnterIsNewLine ? JamiStrings.enterNewLine : JamiStrings.shiftEnterNewLine
property var imageColor: chatViewEnterIsNewLine ? JamiTheme.chatViewFooterImgHoverColor : "#7f7f7f"
property var normalColor: chatViewEnterIsNewLine ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor
property var hasShortcut: false
property var shortcutKey: null
property bool isStyle: false
onTriggered: function clickAction() {
root.chatViewEnterIsNewLine = !root.chatViewEnterIsNewLine;
UtilsAdapter.setAppValue(Settings.Key.ChatViewEnterIsNewLine, chatViewEnterIsNewLine);
}
} }
] ]
@ -855,13 +842,13 @@ RowLayout {
normalColor: { normalColor: {
if (showPreview) { if (showPreview) {
return JamiTheme.transparentColor; return JamiTheme.primaryBackgroundColor;
} else if (modelData.normalColor != null) { } else if (modelData.normalColor != null) {
return modelData.normalColor; return modelData.normalColor;
} else if (modelData.isStyle) { } else if (modelData.isStyle) {
return JamiTheme.hoveredButtonColor; return JamiTheme.hoveredButtonColor;
} else { } else {
return JamiTheme.transparentColor; return JamiTheme.primaryBackgroundColor;
} }
} }
imageColor: { imageColor: {
@ -900,24 +887,18 @@ RowLayout {
toolTipText: showTypo ? JamiStrings.hideFormatting : JamiStrings.showFormatting toolTipText: showTypo ? JamiStrings.hideFormatting : JamiStrings.showFormatting
source: JamiResources.text_edit_black_24dp_svg source: JamiResources.text_edit_black_24dp_svg
normalColor: showPreview ? JamiTheme.transparentColor : (showTypo ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor) normalColor: showPreview ? JamiTheme.primaryBackgroundColor : (showTypo ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor)
imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered || showTypo ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered || showTypo ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor)
hoveredColor: JamiTheme.hoveredButtonColor hoveredColor: JamiTheme.hoveredButtonColor
pressedColor: hoveredColor pressedColor: hoveredColor
onClicked: { onClicked: {
showTypo = !showTypo; showTypo = !showTypo;
messageBarTextArea.isShowTypo = showTypo;
if (messageBar.width < messageBarLayoutMaximumWidth + sendMessageButton.width + 2 * JamiTheme.preferredMarginSize) if (messageBar.width < messageBarLayoutMaximumWidth + sendMessageButton.width + 2 * JamiTheme.preferredMarginSize)
showTypoSecond = false; showTypoSecond = false;
if (!showDefault) if (!showDefault)
showDefault = true; showDefault = true;
if (showTypo) {
root.chatViewEnterIsNewLine = true;
UtilsAdapter.setAppValue(Settings.Key.ChatViewEnterIsNewLine, true);
} else {
root.chatViewEnterIsNewLine = false;
UtilsAdapter.setAppValue(Settings.Key.ChatViewEnterIsNewLine, false);
}
UtilsAdapter.setAppValue(Settings.Key.ShowMardownOption, showTypo); UtilsAdapter.setAppValue(Settings.Key.ShowMardownOption, showTypo);
UtilsAdapter.setAppValue(Settings.Key.ShowSendOption, !showDefault); UtilsAdapter.setAppValue(Settings.Key.ShowSendOption, !showDefault);
} }
@ -1022,7 +1003,7 @@ RowLayout {
toolTipText: modelData.toolTip toolTipText: modelData.toolTip
source: modelData.iconSrc source: modelData.iconSrc
normalColor: JamiTheme.transparentColor normalColor: JamiTheme.primaryBackgroundColor
imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor)
hoveredColor: JamiTheme.hoveredButtonColor hoveredColor: JamiTheme.hoveredButtonColor
pressedColor: hoveredColor pressedColor: hoveredColor
@ -1161,11 +1142,11 @@ RowLayout {
imageContainerHeight: 25 imageContainerHeight: 25
radius: 5 radius: 5
source: JamiResources.preview_black_24dp_svg source: JamiResources.preview_black_24dp_svg
normalColor: showPreview ? hoveredColor : JamiTheme.transparentColor normalColor: showPreview ? hoveredColor : JamiTheme.primaryBackgroundColor
imageColor: (hovered || showPreview) ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor imageColor: (hovered || showPreview) ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor
hoveredColor: JamiTheme.hoveredButtonColor hoveredColor: JamiTheme.hoveredButtonColor
pressedColor: hoveredColor pressedColor: hoveredColor
toolTipText: JamiStrings.showPreview toolTipText: showPreview ? JamiStrings.continueEditing : JamiStrings.showPreview
onClicked: { onClicked: {
showPreview = !showPreview; showPreview = !showPreview;

View File

@ -41,6 +41,7 @@ JamiFlickable {
property alias selectionStart: textArea.selectionStart property alias selectionStart: textArea.selectionStart
property alias selectionEnd: textArea.selectionEnd property alias selectionEnd: textArea.selectionEnd
property bool showPreview: false property bool showPreview: false
property bool isShowTypo: UtilsAdapter.getAppValue(Settings.Key.ShowMardownOption)
ScrollBar.vertical.visible: textArea.text ScrollBar.vertical.visible: textArea.text
ScrollBar.horizontal.visible: textArea.text ScrollBar.horizontal.visible: textArea.text
@ -157,7 +158,7 @@ JamiFlickable {
persistentSelection: true persistentSelection: true
height: this.paintedHeight height: textArea.lineCount === 1 ? 35 : textArea.paintedHeight
verticalAlignment: TextEdit.AlignVCenter verticalAlignment: TextEdit.AlignVCenter
@ -206,7 +207,13 @@ JamiFlickable {
const isEnterNewLine = UtilsAdapter.getAppValue(Settings.Key.ChatViewEnterIsNewLine); const isEnterNewLine = UtilsAdapter.getAppValue(Settings.Key.ChatViewEnterIsNewLine);
const isShiftPressed = (keyEvent.modifiers & Qt.ShiftModifier); const isShiftPressed = (keyEvent.modifiers & Qt.ShiftModifier);
const isCtrlPressed = (keyEvent.modifiers & Qt.ControlModifier); const isCtrlPressed = (keyEvent.modifiers & Qt.ControlModifier);
if (!isEnterNewLine && !isShiftPressed || isCtrlPressed) { if (!root.isShowTypo && !isShiftPressed) {
root.sendMessagesRequired();
keyEvent.accepted = true;
} else if (isCtrlPressed) {
root.sendMessagesRequired();
keyEvent.accepted = true;
} else if (!isEnterNewLine && !isShiftPressed) {
root.sendMessagesRequired(); root.sendMessagesRequired();
keyEvent.accepted = true; keyEvent.accepted = true;
} }

View File

@ -75,7 +75,8 @@ Rectangle {
radius: hoverButtonRadius radius: hoverButtonRadius
hoveredColor: JamiTheme.hoveredButtonColor hoveredColor: JamiTheme.hoveredButtonColor
source: JamiResources.ic_baseline_search_24dp_svg source: JamiResources.ic_baseline_search_24dp_svg
normalColor: "transparent" toolTipText: JamiStrings.search
normalColor: JamiTheme.primaryBackgroundColor
imageColor: { imageColor: {
if (reductionEnabled) { if (reductionEnabled) {
if (hovered) { if (hovered) {

View File

@ -16,21 +16,19 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import net.jami.Adapters 1.1 import net.jami.Adapters 1.1
import net.jami.Constants 1.1 import net.jami.Constants 1.1
import net.jami.Enums 1.1 import net.jami.Enums 1.1
import net.jami.Models 1.1 import net.jami.Models 1.1
import "../../commoncomponents" import "../../commoncomponents"
import "../../settingsview/components" import "../../settingsview/components"
SidePanelBase { SidePanelBase {
id: root id: root
objectName: "SidePanel" objectName: "SidePanel"
color: JamiTheme.backgroundColor color: JamiTheme.backgroundColor
@ -39,7 +37,7 @@ SidePanelBase {
target: LRCInstance target: LRCInstance
function onCurrentAccountIdChanged() { function onCurrentAccountIdChanged() {
clearContactSearchBar() clearContactSearchBar();
} }
} }
@ -47,8 +45,8 @@ SidePanelBase {
target: ConversationsAdapter target: ConversationsAdapter
function onConversationReady() { function onConversationReady() {
selectTab(SidePanelTabBar.Conversations) selectTab(SidePanelTabBar.Conversations);
clearContactSearchBar() clearContactSearchBar();
} }
} }
@ -56,46 +54,46 @@ SidePanelBase {
target: ConversationsAdapter target: ConversationsAdapter
function onShowSearchStatus(status) { function onShowSearchStatus(status) {
searchStatusText.text = status searchStatusText.text = status;
} }
function onTextFilterChanged(text) { function onTextFilterChanged(text) {
// In the swarm details, "Go to conversation" can // In the swarm details, "Go to conversation" can
// change the search bar. Be sure to be synced // change the search bar. Be sure to be synced
contactSearchBar.textContent = text contactSearchBar.textContent = text;
} }
} }
function toggleCreateSwarmView() { function toggleCreateSwarmView() {
if (!inNewSwarm) { if (!inNewSwarm) {
viewCoordinator.present("NewSwarmPage") viewCoordinator.present("NewSwarmPage");
const newSwarmPage = viewCoordinator.getView("NewSwarmPage") const newSwarmPage = viewCoordinator.getView("NewSwarmPage");
newSwarmPage.removeMember.connect((convId, member) => { newSwarmPage.removeMember.connect((convId, member) => {
removeMember(convId, member) removeMember(convId, member);
}) });
newSwarmPage.createSwarmClicked.connect((title, description, avatar) => { newSwarmPage.createSwarmClicked.connect((title, description, avatar) => {
var uris = [] var uris = [];
for (var idx in newSwarmPage.members) { for (var idx in newSwarmPage.members) {
var uri = newSwarmPage.members[idx].uri var uri = newSwarmPage.members[idx].uri;
if (uris.indexOf(uri) === -1) { if (uris.indexOf(uri) === -1) {
uris.push(uri) uris.push(uri);
}
} }
} let convuid = ConversationsAdapter.createSwarm(title, description, avatar, uris);
let convuid = ConversationsAdapter.createSwarm(title, description, avatar, uris) viewCoordinator.dismiss("NewSwarmPage");
viewCoordinator.dismiss("NewSwarmPage") LRCInstance.selectConversation(convuid);
LRCInstance.selectConversation(convuid) });
})
} else { } else {
viewCoordinator.dismiss("NewSwarmPage") viewCoordinator.dismiss("NewSwarmPage");
} }
} }
function clearContactSearchBar() { function clearContactSearchBar() {
contactSearchBar.clearText() contactSearchBar.clearText();
} }
function selectTab(tabIndex) { function selectTab(tabIndex) {
sidePanelTabBar.selectTab(tabIndex) sidePanelTabBar.selectTab(tabIndex);
} }
property bool inNewSwarm: viewCoordinator.currentViewName === "NewSwarmPage" property bool inNewSwarm: viewCoordinator.currentViewName === "NewSwarmPage"
@ -104,65 +102,64 @@ SidePanelBase {
property var highlightedMembers: [] property var highlightedMembers: []
onHighlightedMembersChanged: { onHighlightedMembersChanged: {
if (inNewSwarm) { if (inNewSwarm) {
const newSwarmPage = viewCoordinator.getView("NewSwarmPage") const newSwarmPage = viewCoordinator.getView("NewSwarmPage");
newSwarmPage.members = highlightedMembers newSwarmPage.members = highlightedMembers;
} }
} }
function refreshHighlighted(convId, highlightedStatus) { function refreshHighlighted(convId, highlightedStatus) {
var newH = root.highlighted var newH = root.highlighted;
var newHm = root.highlightedMembers var newHm = root.highlightedMembers;
if (highlightedStatus) { if (highlightedStatus) {
var item = ConversationsAdapter.getConvInfoMap(convId) var item = ConversationsAdapter.getConvInfoMap(convId);
var added = false var added = false;
for (var idx in item.uris) { for (var idx in item.uris) {
var uri = item.uris[idx] var uri = item.uris[idx];
if (!Array.from(newHm).find(r => r.uri === uri) && if (!Array.from(newHm).find(r => r.uri === uri) && uri !== CurrentAccount.uri) {
uri !== CurrentAccount.uri) { newHm.push({
newHm.push({"uri": uri, "convId": convId}) "uri": uri,
added = true "convId": convId
});
added = true;
} }
} }
if (!added) if (!added)
return false return false;
} else { } else {
newH = Array.from(newH).filter(r => r !== convId) newH = Array.from(newH).filter(r => r !== convId);
newHm = Array.from(newHm).filter(r => r.convId !== convId) newHm = Array.from(newHm).filter(r => r.convId !== convId);
} }
newH.push(convId);
newH.push(convId) root.highlighted = newH;
root.highlighted = newH root.highlightedMembers = newHm;
root.highlightedMembers = newHm ConversationsAdapter.ignoreFiltering(root.highlighted);
ConversationsAdapter.ignoreFiltering(root.highlighted) return true;
return true
} }
function clearHighlighted() { function clearHighlighted() {
root.highlighted = [] root.highlighted = [];
root.highlightedMembers = [] root.highlightedMembers = [];
} }
function removeMember(convId, member) { function removeMember(convId, member) {
var refreshHighlighted = true var refreshHighlighted = true;
var newHm = [] var newHm = [];
for (var hm in root.highlightedMembers) { for (var hm in root.highlightedMembers) {
var m = root.highlightedMembers[hm] var m = root.highlightedMembers[hm];
if (m.convId === convId && m.uri === member) { if (m.convId === convId && m.uri === member) {
continue; continue;
} else if (m.convId === convId) { } else if (m.convId === convId) {
refreshHighlighted = false refreshHighlighted = false;
} }
newHm.push(m) newHm.push(m);
} }
root.highlightedMembers = newHm root.highlightedMembers = newHm;
if (refreshHighlighted) { if (refreshHighlighted) {
// Remove highlighted status if necessary // Remove highlighted status if necessary
for (var d in swarmCurrentConversationList.contentItem.children) { for (var d in swarmCurrentConversationList.contentItem.children) {
var delegate = swarmCurrentConversationList.contentItem.children[d] var delegate = swarmCurrentConversationList.contentItem.children[d];
if (delegate.convId === convId) if (delegate.convId === convId)
delegate.highlighted = false delegate.highlighted = false;
} }
} }
} }
@ -176,11 +173,16 @@ SidePanelBase {
color: JamiTheme.backgroundColor color: JamiTheme.backgroundColor
} }
header: AccountComboBox {} header: AccountComboBox {
}
Item { Item {
anchors.fill: parent anchors.fill: parent
onVisibleChanged: {
donation.donationVisible = Qt.binding(() => JamiQmlUtils.isDonationBannerVisible());
}
RowLayout { RowLayout {
id: titleBar id: titleBar
@ -240,7 +242,7 @@ SidePanelBase {
sequence: "Ctrl+F" sequence: "Ctrl+F"
context: Qt.ApplicationShortcut context: Qt.ApplicationShortcut
onActivated: { onActivated: {
contactSearchBar.forceActiveFocus() contactSearchBar.forceActiveFocus();
} }
} }
@ -250,20 +252,18 @@ SidePanelBase {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
onSearchBarTextChanged: function(text){ onSearchBarTextChanged: function (text) {
// not calling positionViewAtBeginning will cause // not calling positionViewAtBeginning will cause
// sort animation visual bugs // sort animation visual bugs
conversationListView.positionViewAtBeginning() conversationListView.positionViewAtBeginning();
ConversationsAdapter.ignoreFiltering(root.highlighted) ConversationsAdapter.ignoreFiltering(root.highlighted);
ConversationsAdapter.setFilter(text) ConversationsAdapter.setFilter(text);
} }
onReturnPressedWhileSearching: { onReturnPressedWhileSearching: {
var listView = searchResultsListView.count ? var listView = searchResultsListView.count ? searchResultsListView : conversationListView;
searchResultsListView :
conversationListView
if (listView.count) if (listView.count)
listView.model.select(0) listView.model.select(0);
} }
} }
@ -291,8 +291,7 @@ SidePanelBase {
SidePanelTabBar { SidePanelTabBar {
id: sidePanelTabBar id: sidePanelTabBar
visible: ConversationsAdapter.pendingRequestCount && visible: ConversationsAdapter.pendingRequestCount && !contactSearchBar.textContent && smartListLayout.visible
!contactSearchBar.textContent && smartListLayout.visible
anchors.top: startBar.bottom anchors.top: startBar.bottom
anchors.topMargin: visible ? 10 : 0 anchors.topMargin: visible ? 10 : 0
width: page.width width: page.width
@ -311,7 +310,6 @@ SidePanelBase {
height: visible ? 42 : 0 height: visible ? 42 : 0
color: JamiTheme.backgroundColor color: JamiTheme.backgroundColor
Text { Text {
id: searchStatusText id: searchStatusText
@ -326,13 +324,22 @@ SidePanelBase {
} }
} }
DonationBanner {
id: donation
anchors.horizontalCenter: parent.horizontalCenter
anchors.leftMargin: 15
anchors.rightMargin: 15
anchors.top: sidePanelTabBar.bottom
anchors.topMargin: 10
visible: donation.donationVisible
}
ColumnLayout { ColumnLayout {
id: smartListLayout id: smartListLayout
width: parent.width width: parent.width
anchors.top: searchStatusRect.bottom anchors.top: donation.donationVisible ? donation.bottom : searchStatusRect.bottom
anchors.topMargin: (sidePanelTabBar.visible || anchors.topMargin: (sidePanelTabBar.visible || searchStatusRect.visible) ? 0 : 12
searchStatusRect.visible) ? 0 : 12
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
spacing: 4 spacing: 4
@ -350,14 +357,14 @@ SidePanelBase {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: visible ? contentHeight : 0 Layout.preferredHeight: visible ? contentHeight : 0
Layout.maximumHeight: { Layout.maximumHeight: {
var otherContentHeight = conversationListView.contentHeight + 16 var otherContentHeight = conversationListView.contentHeight + 16;
if (conversationListView.visible) if (conversationListView.visible)
if (otherContentHeight < parent.height / 2) if (otherContentHeight < parent.height / 2)
return parent.height - otherContentHeight return parent.height - otherContentHeight;
else else
return parent.height / 2 return parent.height / 2;
else else
return parent.height return parent.height;
} }
model: SearchResultsListModel model: SearchResultsListModel
@ -385,9 +392,8 @@ SidePanelBase {
visible: inNewSwarm visible: inNewSwarm
width: parent.width width: parent.width
anchors.top: searchStatusRect.bottom anchors.top: donation.donationVisible ? donation.bottom : sidePanelTabBar.bottom
anchors.topMargin: (sidePanelTabBar.visible || anchors.topMargin: (sidePanelTabBar.visible || searchStatusRect.visible) ? 0 : 12
searchStatusRect.visible) ? 0 : 12
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
spacing: 4 spacing: 4
@ -404,8 +410,8 @@ SidePanelBase {
onVisibleChanged: { onVisibleChanged: {
if (!swarmCurrentConversationList.visible) { if (!swarmCurrentConversationList.visible) {
highlighted = false highlighted = false;
root.clearHighlighted() root.clearHighlighted();
} }
} }
@ -414,26 +420,26 @@ SidePanelBase {
// destroyed from the memory. So, re-add the highlighted // destroyed from the memory. So, re-add the highlighted
// status if necessary // status if necessary
if (Array.from(root.highlighted).find(r => r === UID)) { if (Array.from(root.highlighted).find(r => r === UID)) {
highlighted = true highlighted = true;
} }
} }
onHighlightedChanged: function onHighlightedChanged() { onHighlightedChanged: function onHighlightedChanged() {
if (highlighted && Array.from(root.highlighted).find(r => r === UID)) { if (highlighted && Array.from(root.highlighted).find(r => r === UID)) {
// Due to scrolling destruction/reconstruction // Due to scrolling destruction/reconstruction
return return;
} }
var currentHighlighted = root.highlighted var currentHighlighted = root.highlighted;
if (!root.refreshHighlighted(UID, highlighted)) { if (!root.refreshHighlighted(UID, highlighted)) {
highlighted = false highlighted = false;
return return;
} }
if (highlighted) { if (highlighted) {
root.highlighted.push(UID) root.highlighted.push(UID);
} else { } else {
root.highlighted = Array.from(root.highlighted).filter(r => r !== UID) root.highlighted = Array.from(root.highlighted).filter(r => r !== UID);
} }
root.clearContactSearchBar() root.clearContactSearchBar();
} }
} }
currentIndex: model.currentFilteredRow currentIndex: model.currentFilteredRow
@ -448,7 +454,9 @@ SidePanelBase {
interval: 750 interval: 750
running: isSharingPosition || isReceivingPosition running: isSharingPosition || isReceivingPosition
repeat: true repeat: true
onTriggered: {showIconArrow = !showIconArrow} onTriggered: {
showIconArrow = !showIconArrow;
}
} }
} }
} }

View File

@ -37,7 +37,6 @@ FocusScope {
property color textColor: JamiTheme.textColor property color textColor: JamiTheme.textColor
property color iconColor: JamiTheme.tintedBlue property color iconColor: JamiTheme.tintedBlue
property string customizeTip: "CustomizeTipBox {}" property string customizeTip: "CustomizeTipBox {}"
property string backupTip: "BackupTipBox {" + " onIgnore: {" + " root.ignoreClicked()" + " }" + "}" property string backupTip: "BackupTipBox {" + " onIgnore: {" + " root.ignoreClicked()" + " }" + "}"
@ -56,7 +55,6 @@ FocusScope {
focus: true focus: true
activeFocusOnTab: true activeFocusOnTab: true
Rectangle { Rectangle {
id: rect id: rect
anchors.fill: parent anchors.fill: parent
@ -73,6 +71,18 @@ FocusScope {
width: parent.width width: parent.width
anchors.topMargin: 10 anchors.topMargin: 10
Loader {
id: loader_donationTip
active: type === "donation"
focus: true
sourceComponent: DonationTipBox {
maxHeight: root.maximumHeight
textColor: root.textColor
iconColor: root.iconColor
}
width: parent.width
}
Loader { Loader {
id: loader_backupTip id: loader_backupTip
active: type === "backup" active: type === "backup"
@ -95,7 +105,6 @@ FocusScope {
} }
width: parent.width width: parent.width
focus: true focus: true
} }
Loader { Loader {
id: loader_infoTip id: loader_infoTip
@ -106,7 +115,6 @@ FocusScope {
iconColor: root.iconColor iconColor: root.iconColor
} }
width: parent.width width: parent.width
} }
} }
} }
@ -119,6 +127,7 @@ FocusScope {
TapHandler { TapHandler {
target: rect target: rect
enabled: type !== "donation"
onTapped: { onTapped: {
return opened ? focus = false : root.forceActiveFocus(); return opened ? focus = false : root.forceActiveFocus();
} }

View File

@ -24,9 +24,6 @@ import "../../commoncomponents"
BaseModalDialog { BaseModalDialog {
id: root id: root
width: Math.min(appWindow.width - 2 * JamiTheme.preferredMarginSize, JamiTheme.secondaryDialogDimension)
height: Math.min(appWindow.height - 2 * JamiTheme.preferredMarginSize, JamiTheme.secondaryDialogDimension)
property string convId property string convId
property string aliasText property string aliasText
property string registeredNameText property string registeredNameText
@ -34,19 +31,11 @@ BaseModalDialog {
property int preferredImgSize: 80 property int preferredImgSize: 80
popupContent: Rectangle { popupContent: GridLayout {
id: userProfileContentRect
color: JamiTheme.backgroundColor
radius: JamiTheme.modalPopupRadius
anchors.fill: parent
GridLayout {
id: userProfileDialogLayout id: userProfileDialogLayout
anchors.centerIn: parent
anchors.fill: parent
anchors.margins: JamiTheme.preferredMarginSize anchors.margins: JamiTheme.preferredMarginSize
width: JamiTheme.secondaryDialogDimension
columns: 2 columns: 2
rows: 6 rows: 6
@ -77,6 +66,7 @@ BaseModalDialog {
visible: aliasText ? (aliasText === idText ? false : true) : false visible: aliasText ? (aliasText === idText ? false : true) : false
selectByMouse: true selectByMouse: true
readOnly: true
wrapMode: Text.NoWrap wrapMode: Text.NoWrap
text: textMetricsContactAliasText.elidedText text: textMetricsContactAliasText.elidedText
@ -88,7 +78,7 @@ BaseModalDialog {
id: textMetricsContactAliasText id: textMetricsContactAliasText
font: contactAlias.font font: contactAlias.font
text: aliasText text: aliasText
elideWidth: userProfileContentRect.width - 200 elideWidth: root.width - 200
elide: Qt.ElideMiddle elide: Qt.ElideMiddle
} }
} }
@ -141,12 +131,13 @@ BaseModalDialog {
id: textMetricsContactDisplayNameText id: textMetricsContactDisplayNameText
font: contactDisplayName.font font: contactDisplayName.font
text: registeredNameText text: registeredNameText
elideWidth: userProfileContentRect.width - 200 elideWidth: root.width - 200
elide: Qt.ElideMiddle elide: Qt.ElideMiddle
} }
} }
Text { Text {
id: identifierText
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
font.pointSize: JamiTheme.textFontSize font.pointSize: JamiTheme.textFontSize
text: JamiStrings.identifier text: JamiStrings.identifier
@ -157,8 +148,8 @@ BaseModalDialog {
id: contactId id: contactId
Layout.alignment: Qt.AlignLeft Layout.alignment: Qt.AlignLeft
Layout.preferredWidth: userProfileContentRect.width - 200 Layout.preferredWidth: root.width - 250
Layout.rightMargin: JamiTheme.preferredMarginSize
font.pointSize: JamiTheme.textFontSize font.pointSize: JamiTheme.textFontSize
font.kerning: true font.kerning: true
color: JamiTheme.textColor color: JamiTheme.textColor
@ -166,7 +157,7 @@ BaseModalDialog {
readOnly: true readOnly: true
selectByMouse: true selectByMouse: true
wrapMode: TextEdit.WrapAnywhere wrapMode: Text.Wrap
text: idText text: idText
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
@ -193,25 +184,6 @@ BaseModalDialog {
source: convId !== "" ? "image://qrImage/contact_" + convId : "image://qrImage/contact_" + idText source: convId !== "" ? "image://qrImage/contact_" + convId : "image://qrImage/contact_" + idText
} }
MaterialButton {
id: btnClose
Layout.columnSpan: 2
Layout.alignment: Qt.AlignHCenter
preferredWidth: JamiTheme.preferredFieldWidth / 2
buttontextHeightMargin: JamiTheme.buttontextHeightMargin
color: JamiTheme.buttonTintedBlack
hoveredColor: JamiTheme.buttonTintedBlackHovered
pressedColor: JamiTheme.buttonTintedBlackPressed
secondary: true
text: JamiStrings.close
onClicked: close()
}
} }
} }
}

View File

@ -31,7 +31,7 @@ Item {
property color textColor: JamiTheme.textColor property color textColor: JamiTheme.textColor
property color idColor: JamiTheme.welcomeBlockColor property color idColor: JamiTheme.welcomeBlockColor
property color contentIdColor: JamiTheme.tintedBlue property color contentIdColor: JamiTheme.tintedBlue
property bool hasTitle: true property bool hasTitle: false
property bool hasDescription: true property bool hasDescription: true
property string title: JamiStrings.welcomeToJami property string title: JamiStrings.welcomeToJami
@ -39,8 +39,6 @@ Item {
property real contentWidth: welcomeInfo.width - 2 * JamiTheme.mainViewMargin property real contentWidth: welcomeInfo.width - 2 * JamiTheme.mainViewMargin
function getHeight() { function getHeight() {
return bgRect.height; return bgRect.height;
} }
@ -70,7 +68,6 @@ Item {
Loader { Loader {
id: loader_identifierDescription id: loader_identifierDescription
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: contentWidth
Layout.preferredHeight: item ? item.contentHeight : 0 Layout.preferredHeight: item ? item.contentHeight : 0
Layout.bottomMargin: loader_bottomIdentifier.item ? JamiTheme.mainViewMargin - 10 : 0 Layout.bottomMargin: loader_bottomIdentifier.item ? JamiTheme.mainViewMargin - 10 : 0
sourceComponent: { sourceComponent: {
@ -93,7 +90,6 @@ Item {
sourceComponent: JamiIdentifier { sourceComponent: JamiIdentifier {
backgroundColor: welcomeInfo.idColor backgroundColor: welcomeInfo.idColor
contentColor: contentIdColor contentColor: contentIdColor
} }
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: active ? item.getHeight() : 0 Layout.preferredHeight: active ? item.getHeight() : 0
@ -133,7 +129,7 @@ Item {
width: welcomeInfo.contentWidth width: welcomeInfo.contentWidth
height: contentHeight height: contentHeight
font.pixelSize: JamiTheme.headerFontSize font.pixelSize: JamiTheme.tipBoxContentFontSize
wrapMode: Text.WordWrap wrapMode: Text.WordWrap

View File

@ -36,18 +36,18 @@ Item {
width: getWidth() width: getWidth()
function getWidth() { function getWidth() {
return JamiTheme.welcomeHalfGridWidth; return JamiTheme.welcomeThirdGridWidth;
} }
function getHeight() { function getHeight() {
return 120; return 80;
} }
CachedImage { CachedImage {
id: cachedImgLogo id: cachedImgLogo
objectName: "cachedImgLogo" objectName: "cachedImgLogo"
downloadUrl: logoUrl downloadUrl: logoUrl
defaultImage: JamiResources.jami_logo_icon_svg defaultImage: JamiTheme.welcomeLogo
visible: welcomeLogo.visible visible: welcomeLogo.visible
height: parent.height * logoSize height: parent.height * logoSize
width: parent.width * logoSize width: parent.width * logoSize

View File

@ -49,7 +49,7 @@ ListSelectionView {
property bool hasCustomUi: false property bool hasCustomUi: false
property bool hasTitle: true property bool hasTitle: false
property bool hasDescription: true property bool hasDescription: true
property bool hasCustomTitle: false property bool hasCustomTitle: false
@ -95,7 +95,7 @@ ListSelectionView {
function updateUiFlags() { function updateUiFlags() {
hasCustomUi = Object.keys(uiCustomization).length > 0; hasCustomUi = Object.keys(uiCustomization).length > 0;
hasTitle = hasCustomUi ? uiCustomization.title !== "" : true; hasTitle = hasCustomUi ? uiCustomization.title !== "" : false;
hasDescription = hasCustomUi ? uiCustomization.description !== "" : true; hasDescription = hasCustomUi ? uiCustomization.description !== "" : true;
title = hasCustomUi && uiCustomization.title !== undefined ? uiCustomization.title : JamiStrings.welcomeToJami; title = hasCustomUi && uiCustomization.title !== undefined ? uiCustomization.title : JamiStrings.welcomeToJami;
description = hasCustomUi && uiCustomization.description !== undefined ? uiCustomization.description : JamiStrings.hereIsIdentifier; description = hasCustomUi && uiCustomization.description !== undefined ? uiCustomization.description : JamiStrings.hereIsIdentifier;
@ -261,16 +261,14 @@ ListSelectionView {
TextMetrics { TextMetrics {
id: textSize id: textSize
font.weight: Font.Bold font.weight: Font.Bold
font.pixelSize: 20
font.capitalization: Font.AllUppercase font.capitalization: Font.AllUppercase
text: aboutJami.text text: aboutJami.text
} }
tertiary: true tertiary: true
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
preferredWidth: textSize.width preferredWidth: text.width
text: JamiStrings.aboutJami text: JamiStrings.aboutJami
fontSize: 12
onClicked: viewCoordinator.presentDialog(appWindow, "mainview/components/AboutPopUp.qml") onClicked: viewCoordinator.presentDialog(appWindow, "mainview/components/AboutPopUp.qml")
} }

View File

@ -18,26 +18,26 @@
import QtQuick import QtQuick
import net.jami.Adapters 1.1 import net.jami.Adapters 1.1
import net.jami.Constants 1.1 import net.jami.Constants 1.1
import QtQuick.Layouts
import "../../commoncomponents" import "../../commoncomponents"
BaseModalDialog { BaseModalDialog {
id: root id: root
//Content height + margin. topLayoutVisible: false
property int size: JamiTheme.qrCodeImageSize + 30
width: size
height: size
backgroundColor: JamiTheme.whiteColor backgroundColor: JamiTheme.whiteColor
popupContentPreferredHeight: JamiTheme.qrCodeImageSize
popupContentPreferredWidth: JamiTheme.qrCodeImageSize
popupContent: Image { popupContent: Image {
id: userQrImage id: userQrImage
property int size: JamiTheme.qrCodeImageSize
width: size
height: size
anchors.centerIn: parent
smooth: false smooth: false
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
source: "image://qrImage/account_" + CurrentAccount.id source: "image://qrImage/account_" + CurrentAccount.id
} }
} }

View File

@ -25,6 +25,28 @@
#include <QtNetwork> #include <QtNetwork>
#include <QScopedPointer> #include <QScopedPointer>
namespace {
NetworkManager::GetError
translateErrorCode(QNetworkReply::NetworkError error)
{
// From qnetworkreply.h:
// network layer errors (1-99): / proxy errors (101-199):
// content errors (201-299): ContentAccessDenied = 201,
// protocol errors / Server side errors (401-499)
static auto inRange = [](int value, int min, int max) -> bool {
return (value >= min && value <= max);
};
if (inRange(error, 1, 199))
return NetworkManager::NETWORK_ERROR;
if (inRange(error, 201, 201))
return NetworkManager::ACCESS_DENIED;
if (inRange(error, 202, 299))
return NetworkManager::CONTENT_NOT_FOUND;
return NetworkManager::NETWORK_ERROR;
}
} // namespace
NetworkManager::NetworkManager(ConnectivityMonitor* cm, QObject* parent) NetworkManager::NetworkManager(ConnectivityMonitor* cm, QObject* parent)
: QObject(parent) : QObject(parent)
, manager_(new QNetworkAccessManager(this)) , manager_(new QNetworkAccessManager(this))
@ -45,7 +67,7 @@ NetworkManager::NetworkManager(ConnectivityMonitor* cm, QObject* parent)
}); });
#endif #endif
connect(connectivityMonitor_, &ConnectivityMonitor::connectivityChanged, this, [this] { connect(connectivityMonitor_, &ConnectivityMonitor::connectivityChanged, this, [this] {
auto connected = connectivityMonitor_->isOnline(); const auto connected = connectivityMonitor_->isOnline();
if (connected && !lastConnectionState_) { if (connected && !lastConnectionState_) {
manager_->deleteLater(); manager_->deleteLater();
manager_ = new QNetworkAccessManager(this); manager_ = new QNetworkAccessManager(this);
@ -59,7 +81,7 @@ void
NetworkManager::sendGetRequest(const QUrl& url, NetworkManager::sendGetRequest(const QUrl& url,
std::function<void(const QByteArray&)>&& onDoneCallback) std::function<void(const QByteArray&)>&& onDoneCallback)
{ {
QNetworkRequest request = QNetworkRequest(url); const QNetworkRequest request = QNetworkRequest(url);
sendGetRequest(request, std::move(onDoneCallback)); sendGetRequest(request, std::move(onDoneCallback));
} }
@ -98,9 +120,8 @@ NetworkManager::downloadFile(const QUrl& url,
const QString& filePath, const QString& filePath,
const QString& extension) const QString& extension)
{ {
// If there is already a download in progress, return. // Don't replace the download if there is already a download in progress for this id.
if ((downloadReplies_.value(replyId) != NULL || !(replyId == 0)) if (downloadReplies_.contains(replyId) && downloadReplies_.value(replyId)->isRunning()) {
&& downloadReplies_[replyId]->isRunning()) {
qWarning() << Q_FUNC_INFO << "Download already in progress"; qWarning() << Q_FUNC_INFO << "Download already in progress";
return replyId; return replyId;
} }
@ -121,6 +142,7 @@ NetworkManager::downloadFile(const QUrl& url,
} }
// set the id for the request // set the id for the request
// NOLINTNEXTLINE(misc-const-correctness)
std::uniform_int_distribution<int> dist(1, std::numeric_limits<int>::max()); std::uniform_int_distribution<int> dist(1, std::numeric_limits<int>::max());
auto uuid = dist(rng_); auto uuid = dist(rng_);
@ -133,7 +155,7 @@ NetworkManager::downloadFile(const QUrl& url,
const QFileInfo fileInfo(url.path()); const QFileInfo fileInfo(url.path());
const QString fileName = fileInfo.fileName(); const QString fileName = fileInfo.fileName();
auto& file = files_[uuid]; auto& file = files_[uuid];
file = new QFile(filePath + fileName + extension); file = new QFile(filePath + QDir::separator() + fileName + extension);
if (!file->open(QIODevice::WriteOnly)) { if (!file->open(QIODevice::WriteOnly)) {
Q_EMIT errorOccurred(GetError::ACCESS_DENIED); Q_EMIT errorOccurred(GetError::ACCESS_DENIED);
files_.remove(uuid); files_.remove(uuid);
@ -167,7 +189,7 @@ NetworkManager::downloadFile(const QUrl& url,
resetDownload(uuid); resetDownload(uuid);
qWarning() << Q_FUNC_INFO qWarning() << Q_FUNC_INFO
<< QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(error); << QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(error);
Q_EMIT errorOccurred(GetError::NETWORK_ERROR); Q_EMIT errorOccurred(translateErrorCode(error));
}); });
connect(reply, &QNetworkReply::finished, this, [this, uuid, onDoneCallback, reply, file]() { connect(reply, &QNetworkReply::finished, this, [this, uuid, onDoneCallback, reply, file]() {

Some files were not shown because too many files have changed in this diff Show More