Compare commits

..

209 Commits

Author SHA1 Message Date
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
b77012baae misc: bump daemon
Change-Id: Ibf34d81f97f5d601e7357096279e07833a940a33
2023-09-14 13:35:43 -04:00
bc34abc8f4 misc: add tooltip for show preview button
Change-Id: I8b292bdb157c0fed6f873263dc97c4f7f2fa1f02
GitLab: #1337
2023-09-14 13:35:02 -04:00
69b59ad2dd misc: bump daemon
Change-Id: Ie3c7b8665c87e0b7e1b051816f72ec223e559c92
2023-09-14 10:44:33 -04:00
1f2401bc7e PluginDescription: handle language to send request to the plugin store
Change-Id: Id96578cf238246ebe69a6f9b77b0ed1d1f465f38
2023-09-14 10:44:19 -04:00
06b0f1d39c plugins: use pluginId for getIconUrl
Change-Id: I560429fa6604a595c945ffca73fed3c43b152e40
2023-09-14 10:18:01 -04:00
d5b36e7a6d Icon local Path: change identifier plugin name to plugin id
Change-Id: I5091b6f4d5a8d42c73b574d4f889d5795b7ec0db
2023-09-13 15:22:25 -04:00
4e2ae6cde0 misc: bump daemon
Change-Id: I5b014d9c1bf5541fef6dc0af0eda57357c149e9c
2023-09-13 15:28:34 -03:00
0895a9f183 TextEditor: patch height binding after tap big message
Change-Id: I91111ff3b4d54dda85e649e62eef91ad9b935bb8
2023-09-13 11:06:22 -04:00
e8075a412e misc: bump daemon
Change-Id: Ie3c9570dd55e442a6b1e996801e0bb1a7f92b77c
2023-09-12 11:34:20 -04:00
4d55a1430d misc: remove ubuntu 22.10 (EOL)
Change-Id: I9a7bbd77a91b885666519e726530df2ebd7097ca
2023-09-12 11:26:27 -04:00
8de099e38d MessageOptionsPopup: add option to locally delete file
This button offers an option to remove sent/downloaded files
from the device.

Change-Id: Ida1b135681243fd6055034d8a2d699d11bf040e5
GitLab: #1287
2023-09-12 10:59:23 -04:00
306c428019 misc: fix log warning
Change-Id: I943bf58612dc7e6f95fab064c3cd18afda60d9f2
2023-09-12 10:36:46 -04:00
c0a5ced044 misc: fix message bar buttons background color
Change-Id: Ie934835952180803473645bd041bbbba06f02d4f
2023-09-12 10:36:46 -04:00
9f570a3cee Plugin Queries: resolve architecture to be able to handle dynamically all platform
Change-Id: I35ea5be7dc87dcf2e15b5803f9819887c946b91a
2023-09-12 07:32:34 -04:00
2371f0c09f conv-avatar: show a placeholder avatar when base64 data won't load
This does not fix the issue, it's a workaround in case the image data can't load. This may be related to loading large PNGs directly from base 64 strings.

Gitlab: #1329
Change-Id: I45729d10a33b8c8ad0adffb339dbcae40c4b18f9
2023-09-11 15:06:14 -04:00
f605cfce81 white-labeling: fix local file paths
Fixes white-labeling not working on Windows

- use portable local file URI prefixes
- emit download failed when the file can't be created locally
- light refactor

Change-Id: Id6c4c07a9b0edcc18d0d5f5c8852308aaf1e8b44
2023-09-11 10:17:38 -04:00
2aa3212b8f misc: bump daemon
Change-Id: I78e305b020902010dfc9a1c3b1c82d09f0ed2870
2023-09-08 10:59:40 -04:00
031d4348bc build.py: Provide the TARBALLS hint for all distributions.
There's nothing particular about Guix in the handling of TARBALLS, so
display the hint for all distributions.

Change-Id: Icc5f224f08dd0d57f53ee7bed46b11048bff303b
2023-09-07 07:52:00 -04:00
e7436dbc05 accessibility: make the shortcuts focusable
Gitlab: #1211
Change-Id: Idf6a9971ceb06d1f9d42a907f948f402623fccd2
2023-09-06 15:16:37 -04:00
b291728472 tips: center tips when only one or two are left
GitLab: #1184

Change-Id: I9791565e371ca1a5693e85417c9b253802e0b2b3
2023-09-05 09:33:48 -04:00
5820052a53 i18n: automatic bump
Change-Id: I5b0ece4c53706cb698ac904b57fece4c120c1cb2
2023-09-04 16:42:37 -04:00
65cc7a36ed messageBar: hide the popup when you click on show less
GitLab: #1322
Change-Id: I87d4b94a53a4720da5fdf2940ad23f6e17c8fd48
2023-09-01 10:16:43 -04:00
46e2354274 messageBar: display "showLess" when needed
GitLab: #1309
GitLab: #1125
Change-Id: I2b443750731170bebe3532338517e5e0e0ed594b
2023-09-01 10:16:41 -04:00
1bbd8e31af cmake: fix check for minimum major/minor version
The current check only fails if the major and minor version are less than the minimum.
This simplifies the check even removing the major version check which is a find requirement already.

Gitlab: #1330
Change-Id: Id066953c50ef4a925713dbd9203ebe7a3a36f4a1
2023-08-30 14:04:15 -04:00
0bd24bf8c5 misc: bump daemon
Change-Id: I9ccaed3f275b0573e98628c66ebc605fe5764c14
2023-08-25 18:19:29 -03:00
a028696e57 Plugin: change remote plugin margin
Change-Id: Id2289e5f22f23f0a1295dc63d00b6e36133e27b7
2023-08-25 16:40:55 -04:00
c8b371e77a Conversation : remove zero member conversation
(Note: this is a work around, need investigation)

Change-Id: I43d3c26352a068d29486da38b3e25487f10cd9fa
2023-08-25 15:27:17 -04:00
b26259dac8 misc: fix error log in emojipicker
Change-Id: I2dc5ac7743de921469f0b14e12de46b8827184a7
2023-08-24 09:38:18 -03:00
423290a09a emojiPicker: automatic keyboard focus
GitLab: #1220
Change-Id: I848b5352b8214c2112dddc8e69b7bc96d0e372e7
2023-08-24 08:02:41 -04:00
3195fa9b22 sendFile: sending with Enter and automatic focus on the text area
GitLab: #1275
Change-Id: I70036b158cfede3a6c6a7de9bb63a049c8fec39a
2023-08-24 08:02:01 -04:00
4619f04f7b emojireaction: fix maxMsgWidth is not defined error
Change-Id: Id6229ff59c5b896ffe72068e91fc70e334c11aad
2023-08-23 15:46:25 -04:00
ae2380c71b misc: removed unecessary log
Change-Id: I768f32e3bbc2780becc83fe92d6f6f8c9215cec2
2023-08-23 15:55:34 -03:00
2bdf8e088c fix: missing pluginId value
Change-Id: Id1b30c2b35affc3beb3dc2a5646e45c855196a82
2023-08-23 15:17:35 -03:00
9947021394 PluginId: add handler for the plugin id
Change-Id: I377d5856491d38f127fe422e84a6c93839295447
2023-08-23 11:50:14 -04:00
80fe376e3c i18n: automatic bump
Change-Id: Ie2b458e17eb1ecbf7a517c2588e7b87ef36b5752
2023-08-23 09:09:48 -04:00
d1eb1f5885 macOS: fix crash on force quit
This patch ensures that views are destroyed when the user quits
the application.

Change-Id: I173643136d277fe604838bdf19a6c292b066ee8d
2023-08-22 09:07:35 -04:00
b1ca6cf861 PluginView: refactor the ui to a better view
Gitlab: #1306

Change-Id: Ic3d952408c352715f2cd611dad63cf92cfb81ff0
2023-08-21 10:54:35 -04:00
8c728374a7 emojiReactions: change the emojis layout
Gitlab: #1230
Co-authored-by: Charles <charles-francis.damedey@savoirfairelinux.com>
Co-authored-by: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
Change-Id: I5bff3a811caa9bec8ee9b80733165aaaaae5db24
2023-08-18 17:15:33 -04:00
3a693536e4 MessageBar: Fixed issue where sending a message would break the layout.
Change-Id: Iacdea26427e48b00f9edd9aacf57f88860717e0c
2023-08-18 16:42:36 -04:00
ffcd3e59a4 incomingcall: use callstatechanged signal
To be able to show calls that are transfered, we must catch new calls
from callstatechanged signal. Move all logic from newincomingcall to
callstatechanged.

Change-Id: Ibd3ff5f8b4009895b3165348fd1638956f5f66d9
2023-08-08 10:48:50 -04:00
77935de893 welcomepage: fix title translation
Change-Id: Ied989089c59293802b16cf252a538f56d1fbc147
2023-08-08 10:20:37 -03:00
386ef224d1 jamistrings: cleanup
Change-Id: I10c7aa2c77a752c508821d018b7d54dfeb64d7df
2023-08-08 10:15:49 -03:00
d62c2ff98e misc: update title label
Change-Id: I2baa2915398803550fcc161aa7e1ce7cb59ca300
GitLab: #1293
2023-08-07 13:24:46 -04:00
3b00b42213 RTL: fix sparse side panel options
+ fix splitview width resize
+ fix tips row in the WelcomePage

GitLab: #1290
Change-Id: I458e6a96e496b35b7659c5a061949f135511a2e4
2023-08-04 15:06:22 -03:00
21f3479a96 messagebar: fix rtl layout
GitLab: #1279

Change-Id: I746fd86a4cf32cbb369ba2c5d57182800d7da0d0
2023-08-02 12:40:37 -03:00
8307089900 jamiid: change look of jami id to be more compact
Change-Id: I5f39b5f28d4447cdd5b10f37ad2d8780260d5ed8
2023-08-02 10:38:38 -04:00
2916b4c523 swarmdetailpanel: fix avatar position
Change-Id: I9a94c11056be4e176cb01400b2023021a98b6a51
GitLab: #1288
2023-08-02 09:01:37 -03:00
5530649f07 PluginStore: add view for plugin store
Gitlab: #1163
Change-Id: If9d9a27a296c5810b9f99126bed6453cc6ab6852
2023-08-01 13:42:49 -04:00
7581f9397a updateManager: create a plugin store and a plugin manager
Change-Id: I57ebec72c1cb6e2f245af011def82f880bc9573f
2023-08-01 13:42:49 -04:00
7f2c98a594 shortcuttable: update strings
Change-Id: I9428df58376a6cf84c9736d40b07db88089230d1
GitLab: #1282
2023-08-01 10:00:17 -04:00
6341f32618 updatemanager: refactor windows update and macos update manager
To be able to use an update manager for the plugins store, a refactor of windows update manager is done. The windows and macos update manager is used for updating jami. The plugins store update manager is to update plugins to the newest version.

Gitlab: #1229
Change-Id: I0541b6191401f2aa2c6d6034722796455e9c18d2
2023-07-31 15:46:16 -04:00
a652a3d20f messagelistview: fix isFirst/isLast with isEmojiOnly
Change-Id: I4f9a8b037c14e48f12f42f73f0b44b9a78945567
GitLab: #1198
2023-07-31 13:20:06 -04:00
46da989a59 settings: move link device button
Change-Id: Ibafb7afb3eb4fa373a02120ae3575254c645a5c8
GitLab: #1253
2023-07-31 12:56:56 -04:00
1a463ec662 misc: bump daemon
Change-Id: Ib2ad7deed9e27855c1dd6e7c75930a3d4f7f880c
2023-07-31 11:08:30 -04:00
aee632c967 misc: fix warning
Change-Id: I7fd957e621f5af1cc76b94c47fffc2523009fa52
2023-07-31 08:41:50 -04:00
e3a73ac932 TextEditor: General upgrade
Popup take text size according to languagePopup takes size of the text in fonction
Edition button are now colored when actif

GitLab: #1096
Change-Id: I4ddfe8de267a0e0582dde602aa2ad42f5cf535e8
2023-07-31 08:41:37 -04:00
416417d15a contactmessagedelegate: fix placement on resize
Change-Id: Icd84dcc248ee0097546a23eed03f4b1379337d0e
GitLab: #1268
2023-07-31 08:28:38 -04:00
36a36dadcf contextmenu: remove "Block contact" on self
https://git.jami.net/savoirfairelinux/jami-project/-/issues/1586

Change-Id: I9b86781869d80eda347659f0c009b8dfe09bdfd0
2023-07-31 08:28:24 -04:00
38735b052a whitelabeling: fix bug on custom color for background
Change-Id: I91544414664008b26397d041998da5c895b48d7a
2023-07-28 12:53:12 -04:00
5b984396cf whitelabeling: change color of text and icons to contrast with custom colors
Change-Id: Ie990bdf7e3ce5253eb55317d2d57a43dd7f543d7
2023-07-28 12:52:51 -04:00
22cd3d4d4e whitelabeling: fix problem when no custom logo in custom Ui
Change-Id: I3a90a20e1963277e72c3980bf5002c16a9a4f213
2023-07-28 12:52:36 -04:00
53811f93b2 misc: remove weird hovered animation on push buttons
Change-Id: Ibad1dd9a6ab8c780123a0342bd4cc138b04663c5
2023-07-28 09:47:16 -04:00
5e874f4f4b contextmenu: remove incorrect block contact
Change-Id: Ia3c72757c903e022f2cbf6d74fc0e0916cd83a94
GitLab: #1270
2023-07-28 09:47:16 -04:00
a5bf258476 swarmdetailspanel: always open on first tab option
Change-Id: If04bdf1b1398c04cdd980d28e0ee594b225ebc3d
GitLab: #1231
2023-07-28 08:20:34 -04:00
3b85425aa3 smartlist: don't reposition the view at the current index
Gitlab: #1273
Change-Id: I4a8cac7caef3c5935b65dacb35b4fc235525ca48
2023-07-27 11:37:38 -04:00
e8e9fd30c9 avatars: fix missing avatars
Strip whitespace for avatars pulled from conversation info.

Gitlab: #1246
Change-Id: I767a53ee3e492507f9cb80b802a9eaaaa66d3d50
2023-07-27 10:47:06 -04:00
e914f795bc i18n: automatic bump
Change-Id: Ia5ee4d6887d4680918ccd5d247dbfdf2197ee7f5
2023-07-27 10:07:14 -04:00
007b0c1132 i18n: fix configuration
+ Only look for translations in valid files.

Change-Id: I350478d050118c8b5d6bd127aaeed6c3965fe05f
GitLab: #1266
2023-07-27 09:59:43 -04:00
11f67c73c8 customizeprofilepage: fix double placeholder
Change-Id: I6628fe83c9818698cc6a2357ab283c97fc94ca31
2023-07-26 13:58:31 -04:00
01cbcbbb2c chatview: update image uri for contact avatar
Gitlab: #1267
Change-Id: I651232cbbf68997f8111c9374486bde4bd8ceeef
2023-07-26 12:50:38 -04:00
76fcd5f910 jamiidentifier: remove useless mask
Change-Id: Ie7e1ae5e5be9b710f53e21cf51385ae8addb54f6
2023-07-26 07:31:15 -04:00
38a3da38c5 i18n: automatic bump
Change-Id: I133ca9ec80aa8ff6a967dd1a4eaf22330fa89279
2023-07-24 16:42:32 -04:00
f0b78036e3 ModalTextEdit: add required placeHolder
Change-Id: I7e450a3f68176bd67801700b621ff6f076531193
2023-07-24 10:44:57 -04:00
2f7acbd31b whitelabeling: change welcomePage to take into account ui customization
GitLab: #1097
Change-Id: I8967146c3ca04daee96b4a4fb10bcb6811c1c7a4
2023-07-19 16:46:32 -04:00
8c1b214619 replytorow: fix message size
Change-Id: I5fd6054a1ac2e409a3ddecef82ec656ad5639e98
2023-07-19 13:00:04 -04:00
e3e4de0fe7 misc: remove unused method
Change-Id: Ib58dabb342a293a1e4e699fcb75b1b04e5541bc4
2023-07-19 11:02:12 -04:00
452d49a439 settings: remove RTP fallback
As not present in other clients and if SDES is enabled, all calls
must be in SRTP. Else UX would be unclear.

Change-Id: If756f8738ef08109aa7fbf8cbcade3b4f4792093
GitLab: #1263
2023-07-19 10:54:35 -04:00
f53c2be978 MediaSettings: pass arguments to method
Change-Id: I9c751dbc1e9557b95c8d34e80e1e43cbe26d57d4
2023-07-18 14:53:17 -04:00
36e5bdb839 i18n: automatic bump
Change-Id: I3050e54142fd9bd9a59e2a5c18adbe3fcf82d8d5
2023-07-18 14:16:45 -04:00
b54cb31d75 misc: fix typo on formatting
Change-Id: I35a0791ba0c8cc906ac441c7afb588e40b1be5c5
2023-07-18 11:16:17 -04:00
5134160539 misc: bump daemon submodule
Change-Id: Idc2990e82ef0f87b07f79a576390c4b1d99051ed
2023-07-17 15:03:27 -04:00
a9ad7d0bde Plugins: fix unavailable view
Plugins settings view is unavailable due to missing QML_REGISTERTYPE
removed at ec0feef74d.

Change-Id: I07d7fef42e9c25d6ee867f7c682286ea3c52a863
2023-07-17 14:47:53 -03:00
6a1a9b60aa MessageBar: do not show sendFile/Location for a SIP account
Change-Id: I4f2fc87c2ec1083605f8a287eecac67ff950c821
2023-07-17 07:48:25 -04:00
61126cfa64 messageparser: replace regexes with tidy API
Depend on tidy API for attribute extraction rather than regexes.

1. htmlparser methods return nodes instead of pre-parsed strings
2. htmlparser provides some methods to extract text/attr from nodes

Gitlab: #1248
Change-Id: I367d703680938fb0b7c5055ac41e079c1322da30
2023-07-14 13:32:20 -04:00
ec0feef74d CachedImage: add icon downloader for pluginstore and welcome page
Gitlab: #1228
Gitlab: #1166

Change-Id: I0117cecdb8a77ded8f3da3c2f25028012002a285
2023-07-14 07:57:45 -04:00
eff76eddc7 buttons: remove bold effect
Change-Id: Ie483a9af270990622b876ca44a975d915e458783
GitLab: #1236
2023-07-13 15:44:07 -04:00
83039abc1b TextEditor: General upgrade
Implement new design
Add multiline button
Use correct color and implement dark theme

GitLab: #1096
Change-Id: I5699c81fbc41e50300ca8b32b93ee47cd17ceee1
2023-07-13 13:48:00 -04:00
bbdd68fb1d misc: fix isRTL function
Uses the system locale name when the preference is set to "SYSTEM".
Adds some extra ISO 639-1 RTL languages.

Change-Id: Ia28ae1bc15992ce26f88ab11bc447d76054f0581
2023-07-13 11:11:59 -04:00
afc0423bf6 swarmdetailspanel: avoid bugguy column layout
Since Qt 6.4, some layout are bugguy causing bad positioning.
(Even some examples in Qt's doc are incorrect)
So, use anchors instead.

Change-Id: Id0f0175208312b6e4b9fe503d8713c7ff037024a
GitLab: #1217
2023-07-13 09:39:24 -04:00
0b18f3d145 swarmdetailspanel: fix identifier row
also separate debug and muteDaemon options so that "jami -dq" shows
debug informations from the client.

Change-Id: Ic69c5cf8b6a8ef4aa1fff607d01a541dab3e6da2
2023-07-13 09:39:19 -04:00
593ecc9910 whitelabeling: add uicustom info in account property
GitLab: #1097

Change-Id: I1f7db2b14c437d033264ff58457d8067e4ff6c05
2023-07-11 14:34:31 -04:00
8fd7c70d1f wizardview: manage through MainView
Change-Id: I083d293784e07f4fcc099e60ada84e433a1b2fa0
GitLab: #1216
2023-07-11 08:05:56 -04:00
e71c1d1729 i18n: automatic bump
Change-Id: I9af964c0078f96730c42ee525ce23e1a83850579
2023-07-10 16:42:30 -04:00
207872244b moderatorlistmodel: fix refresh on account change
Change-Id: Ib689e97d903a42fc241f505e3fb5f37c155c65f9
GitLab: #1122
2023-07-10 07:41:54 -04:00
03b3530d3d conversationmodel: specify "you" for self-user in title
Change-Id: I01d2cd868c7f1c513290792b5f8bff0f6a110f0e
GitLab: #1250
2023-07-07 13:29:28 -04:00
a7bd860e2b Doc: Clarification of install.md instructions
GitLab: #1168

Change-Id: I478b7db6fd6438ed3a35defcc9a7b3e5e7176f32
2023-07-07 13:02:52 -04:00
df9c4b0653 materialradiobutton: update radius
Change-Id: I00feb393feeb1c7e17dccfd75209b00de6e75e4f
GitLab: #1241
2023-07-07 11:12:30 -04:00
d2eed3af64 chatview timestamp: update colors
+ update scroll to bottom button radius
GitLab: #1244

Change-Id: I76ef89123a9a1dfc521aff2983bd46288abab698
2023-07-07 10:54:14 -03:00
f0eb826b64 contactmessagebase: update design
Also move all spacing in TimeStampInfo, so sequences doesn't have
weird spacing and can better be controlled.

GitLab: #1243
Change-Id: Ica7235856c3a7ed38ed3e390c4bf14decede25b0
2023-07-07 08:35:01 -04:00
2ed89fec3c materialbutton: group hoverEnabled and enabled
The hover animation was shown on disabled buttons

Change-Id: I2d8579a1d712e785b8edc82472df6ac798f1b523
GitLab: #1247
2023-07-07 07:53:34 -04:00
281516823e chatviewheader: keep button selected when linked tab is opened
Change-Id: I5b4df32352bc1e6e5281a18e16c8da902242bc4f
GitLab: #1233
2023-07-07 07:43:33 -04:00
a2d110740d swarmdetailspanel: avoid bugguy column layout
Since Qt 6.4, some layout are bugguy causing bad positioning.
(Even some examples in Qt's doc are incorrect)
So, use anchors instead.

Change-Id: Iebb47b8c7e694049ba297609a12bcf43db7dddd3
GitLab: #1217
2023-07-07 07:32:16 -04:00
ad14302ac5 macOS: remove unnecessary permission for photo library access
This commit removes a permission that is not needed, as the photo
library is not accessed in the code.

Change-Id: I47a3af739252733e3e8a2379b417396b2b67578c
2023-07-06 14:48:25 -04:00
f903c635a7 EmojiPicker: close popup when repress the button
Fixing issues where clicking a second time on
the emoji button open a second popup instead
of closing the first one

GitLab: #1249
Change-Id: I76f0094c4024ae27f260e6aeba93522d3709feef
2023-07-06 11:30:49 -04:00
5582d39a3f settings: update selected colors
Change-Id: I18191ef1a4e5e3a62d509e3871ea33550951e690
GitLab: #1237
2023-07-06 11:30:12 -04:00
4f1e04a9b9 HoveredButton: homogenise effects on hovering
Creating a JamiPushButton in oder to regroup definition
Color correction
Homogenization of the other button (Layout QR Code, Settings, and Hide conversation)

GitLab: #1209
Change-Id: If9f891dba1c1d4e83aaebc16a2202dc2a3b719f2
2023-07-05 11:43:05 -04:00
7514d75242 conversationmodel: ignore notifications from muted conversations
This use case has been observed when taking a look at the system tray
icon, which uses conversation model's notificationsCount() to define
whether or not to show a red dot. As we don't want this for muted
conversations these are ignored.

Change-Id: Ic185de9170dfcbfbd8ffc3513676dd90471f3baa
2023-07-04 16:23:35 -04:00
fe2f3258b2 Popup : Close all popups by pressing escape
Using a key OnPressed instead of Shortcut
Making all popups closable with escape (focus true and a close policy)

GitLab: #1234
Change-Id: I1a612834c439aea94a59e91cb915b18b4ef5cf84
2023-07-04 14:30:23 -04:00
c8ec980a3b misc: invert horizontal and vertical view labels
Change-Id: Ic00b2f5073ee3c3b866c8042be3c19993d446699
GitLab: #1142
2023-07-04 08:39:55 -04:00
cb0e45c3fa swarmdetailspanel: reorder tabbar options
Change-Id: Idf6e9c41148b29b3d3a31ecc3b3ae55c551433bf
GitLab: #1231
2023-07-04 08:21:35 -04:00
532bf6c4ad i18n: automatic bump
Change-Id: I8be71ba4848f90f034f9bc81318cba739c9865f2
2023-07-03 16:42:32 -04:00
d7200cc8a3 ChatViewFooter : use Escape for closing box
Closing emoji box, record box and location box by pressing Esc Key
Using opened that already exists instead of creating isOpen

GitLab: #1197
Change-Id: I8461a7f2e8acaffe4ab66647d3e98701c608f270
2023-06-29 08:08:11 -04:00
3383f43688 chatview: update font sizes and margin
Change-Id: I8186083bbe0854dfa6e1d48b61b14b4aef6d135b
GitLab: #1213
2023-06-28 11:42:44 -04:00
26212b21b2 i18n: automatic bump
Change-Id: I874ad3f1ad9181105cb538349862535a2a9f0677
2023-06-28 08:48:46 -04:00
136f365fe2 fix: avoid crash when deleting account
GitLab: #1173
Change-Id: Id30f259ce286ea8fb76af5aee59ed49edb99011a
2023-06-28 01:30:00 -04:00
2145ee6229 callsettings: correctly get isSIP property
Change-Id: I3512cc9890207f2322d7d843e2137dc09d77ebe5
GitLab: #1207
2023-06-27 15:44:13 -04:00
0f66152d72 build.py: allow initialization without installing pre-commit hook
Gitlab: #1219
Change-Id: I5a2e2099d6ad1b551e2d744ffbf800b79c36a821
2023-06-27 14:59:52 -04:00
24a0a384ff contactmodel: no need to call both addContact/acceptConversationRequest
only acceptConversationRequest is enough to accept a request

Change-Id: I4720ea70def6cd35153167ef9577b1c7528e7140
2023-06-27 13:54:19 -04:00
97297eacf7 jamitheme: update color bubble
Change-Id: Ib7bf909811675dc50c3f964feee93191f8d43338
GitLab: #1212
2023-06-27 13:54:19 -04:00
5a70c7e7e8 misc: fix some overlap issues
+ Fix the password entry for linking a new device with password
+ Fix the linked devices page with a lot of devices
+ Fix the add default moderators popup

Change-Id: I1bac4bd8f55dd91825278399fe39f3503e153edb
GitLab: #886
2023-06-27 13:45:07 -04:00
7931d66b81 calloverlay: don't load call action item models when not visible
Gitlab: #1173
Change-Id: I912cb7a16eb22de188350a741efeaa7e23d99d9b
2023-06-27 11:46:59 -04:00
9fd48580bb i18n: automatic bump
Change-Id: I9df6e8bcd1e599e65508e04d183c558c0d9c9978
2023-06-26 10:25:58 -04:00
1789402949 currentconversation: untick mute conversation setting if unset
Change-Id: I3c0586d17cbb72b0a71886f40409e97d8a37502a
GitLab: #1218
2023-06-22 14:32:23 -04:00
2546b69343 networkmanager: changed handle error in sendGetRequest
Change-Id: I3f3b963b7443a5319799e6f6430f9ddd22414d5f
2023-06-22 14:18:52 -04:00
fb420b2ff7 addmemberpanel: simplify and avoid extra model resets
Change-Id: I3989f386127c55c224311afc0aa0b89303579dec
2023-06-22 09:04:39 -04:00
8a7547aaba smartList: update underlying model
This patch ensures the underlying model is updated whenever
a new conversation is added or removed. This will prevent a
possible crash when the model gets invalidated.

GitLab: #1210
Change-Id: I2bd6f396a6ea09ddd357a567456a057ac1805734
2023-06-21 17:10:47 -04:00
9fe34c5282 i18n: automatic bump
Change-Id: Ib40a6b0eb8fb1d96eb6326f2fbfc8059ea434ac7
2023-06-19 13:30:00 -04:00
b948646cbd misc: bump libjami version
Change-Id: I0cc0e0b798f8f79aa6c8686716848a10c167b2b7
2023-06-19 11:40:22 -04:00
21c4afa564 makefile: remove fedora_36
Change-Id: I006e3d940066510dd2831371d9940360a6149276
2023-06-19 10:29:49 -04:00
41b9e541bb JamiIdentifier: reset edit status on account changes
Change-Id: Ifc2c5380b035c10ec188e2b643d87cca9478cd51
GitLab: #1180
2023-06-19 07:55:34 -04:00
e867b578bf positionmanager: fix signature
Change-Id: I68b830eeb775ed043c617db838a5160213152720
GitLab: #1194
2023-06-19 07:55:14 -04:00
944a20b2f3 swarmdetailspanel: remove incorrect margins on members list
Change-Id: Iffc1ee897507aa11ff845686123a14a94c39ba80
GitLab: #1175
2023-06-19 07:54:44 -04:00
7f4e3c4739 JamiIdentifier: fix reduction overflow
GitLab: #1146
Change-Id: Icafcded965e4517ffd01301ad6f11fbc9d404911
2023-06-15 15:50:22 -04:00
2ef5dcae71 packaging: deprecate fedora 36 (eol) - add debian 12
Change-Id: Ibc7d68a651b5f0ba488d6f45e910ddbe339568a2
2023-06-15 09:26:41 -04:00
ad4d7aecc3 ManageAccountPage: no bug on view when resize the view
Gitlab: #886

Change-Id: Ib3d260271d951a16b63db1ac4a0c3c29a4d87f52
2023-06-15 09:11:56 -04:00
388ad92d96 message panel: update location button visibility
Disable the location sharing button when building without
WebEngine.

Change-Id: I62494147a26035a507742e5e80a85e3c044bc3ff
2023-06-14 15:54:58 -04:00
c37ec740e2 misc: fix click on remove conversation
https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/855
Change-Id: I2c0caa3db05c663c5ee23367774c987aeca3324f
2023-06-14 15:41:38 -04:00
cb31ea3575 messagesadapter: fix click on reply header
The signature was incorrect

Change-Id: I35454bd96cea2d2eb959a80605375e1eb962a0da
2023-06-14 15:41:38 -04:00
a27c344cb7 misc: clarify log
Change-Id: I66b2b8cb1c289575b5568cc40f7402282bede314
2023-06-14 15:41:38 -04:00
a65c4f28e1 snap: add libsystem-dev
Change-Id: I2d337149bf2ef8c7807bbb2562e35cc05e3dbbba
2023-06-14 08:07:05 -04:00
ecd291c1be misc: bump daemon
Change-Id: I4827bd4cc4fb8e853c42f7c6bea6126b30e37968
2023-06-13 08:28:15 -04:00
498dfed98b misc: only check for app updates on windows
Change-Id: I508300446e5c8891bb018af0b0c42de4309685c6
2023-06-12 14:34:48 -04:00
da7366f23d Revert "misc: bump libjami version"
This reverts commit 7743c14598.

Reason for revert: Current version of libjami is causing duplicate conversations for some. The offending commits are unknown.

Change-Id: Ica81e8212117bcba30a1c34776fd6dda44c6705d
2023-06-12 09:29:09 -04:00
8990162f99 Doc: fix package name and clarify instruction
Change-Id: I833f62eac5ffba820d1fdd95f9979c250f56fcf2
2023-06-08 12:58:23 -04:00
1f0e2e92ad build: Add dependencies.
Add libsystemd-dev to APT_DEPENDENCIES
    Add systemd-devel to ZYPPER_DEPENDENCIES
    Add systemd-libs to PACMAN_DEPENDENCIES

Change-Id: Ie997202acd85b04b7c4376cf936b98e04dcb23b6
2023-06-08 12:58:02 -04:00
7743c14598 misc: bump libjami version
Change-Id: I684c5c5888f1e2a0c53b2335a19f06a03ce1b96a
2023-06-08 12:56:01 -04:00
c47cfe446d notifications: gnu/linux: do a lookup for incoming trust requests
Attempt a name directory lookup for trust requests before popping a notification. Fall back to the display name, then peer URI if needed.

Gitlab: #1141
Change-Id: Ie91c3fdf518cb8f27d8f0d6a74f015e9c4034d42
2023-06-08 10:25:32 -04:00
948e2cc837 callactionbar: avoid multiple resets
GitLab: #1073

Change-Id: I7dc2ab632170a959b8d29979deacd3fb03ff6671
2023-06-08 08:44:14 -04:00
b611685653 settingsmaterialtextedit: fix focus changes
Change-Id: I289b610e43317470d061e7ecd6338bfa805c5ce7
GitLab: #1171
2023-06-07 16:10:46 -04:00
26d16c38b8 conversationextrapanel: close details on request/sync
Change-Id: Iec52dc4400bc92283b8a0f7eb5643c758902dc19
GitLab: #1149
2023-06-06 17:17:13 -04:00
5508f28c63 packaging: windows: fix Beta deployment script
Change-Id: I8facd465cd0c8eb0509b66b6f87008c6a86e89bd
2023-06-06 11:56:56 -04:00
c59ac1dd7f misc: bump libjami
Change-Id: I1479573ab66a6c32f0e470bfb918bfaec4c4bbde
2023-06-05 16:33:57 -04:00
51cfef2fdc updatemanager: use msiexec to launch update installer
Change-Id: I605cc425b600b08dac809f0d38d366279140895d
2023-06-05 16:28:11 -04:00
7611cb6147 jenkinsfile: update device label
Change-Id: I5d9eebbe924e642de27ff6f9910f978daf00dd07
2023-06-05 15:07:49 -04:00
e04e3db69f build: windows: use string literal instead of bytes for exe path
Change-Id: If641a2cf5a2a47bfa70e8232769ef916c64af35b
2023-06-05 13:59:32 -04:00
6e7278c87a chatview: remove excess spacing between chat contents and footer
Gitlab: #1172
Change-Id: I615caf484ab37b4a783eadc751642eeb7a5553ac
2023-06-05 09:54:46 -04:00
30e8bf56fb videoprovider: fix copy-paste error
Change-Id: I76706abb2208267c9111903df9cfd92c3c03c2dd
2023-06-02 15:17:17 -04:00
d94c30833f chatview: fix emoji responses under Qt v 6.4.x and up
Qt.bindings are not supported for properties within when calling createObject anymore. Instead, we can pass component references, or generate bindings post-creation.

Note: in this case, the popup closes and observation is not really needed here.

Gitlab: #1169
Change-Id: I21c1d95f4ca725c86fcf276834830145587458cc
2023-06-02 14:57:54 -04:00
ed6e76aa0a settings: audio: start level meter on component loaded
Adds a value animation also.

Gitlab: #1124
Change-Id: I4c012188033dcbb58797d5b071a1c154c7231c2b
2023-06-02 10:33:17 -04:00
1bf4d232b4 settingssidepanel: fix button width
Change-Id: Ib879e352e9f5d4f494469f987cdaedc3f65b74f7
GitLab: #1129
2023-06-02 09:43:57 -04:00
886074dc1e qt: openfile portal: do not use O_PATH fds
This allow to use xdg-open inside a snap

Change-Id: I5ad7e067228b260174abf5c78d0a0e7c2cf8c31d
2023-06-01 14:58:04 -04:00
316750ad93 systemtray: remove option to minimize in systray if tray not visible
Change-Id: I56ad4a55bda8a26931d81d6dbe903c41c65ba345
GitLab: #391
2023-06-01 14:57:32 -04:00
f7bc95d47e logsview: fix ugly theme
Change-Id: Ic38b7c322f0ffe9690a11294683d2d605d7f128e
GitLab: #1153
2023-06-01 14:56:39 -04:00
dc53aa887d misc: change library name "jami" -> "libjami"
Bumps the daemon and adjusts the build to use the appropriate library name.

Change-Id: I4208f161c3522bb58dfc1dc55cb10910ade24eed
2023-06-01 12:32:07 -04:00
a179a9ae2d settings: fix item item visibility
Gitlab: #1127

Change-Id: I447adb4b9d62eae4d21b6d886dba86f05dbc3fde
2023-06-01 10:24:54 -04:00
193b125c48 video: shm: cleanup lock in shmrenderer
Adds an atomic bool used to exit the render in case frameSize is reset by the daemon.

Change-Id: I8c2ae01a3de79704f83930507ee147a34c1628b8
2023-06-01 10:24:42 -04:00
6d8adc9453 avmodel: avoid write-locking the mutex when deleting the renderer
During a resize event the the addRenderer function will regenerate a Renderer of the new size. The Renderer destructor will eventually trigger a write-lock in VideoProvider which may deadlock with frame updates to other renderers.

Gitlab: #1161
Change-Id: I3f3b99f6f78ac94218213130d42efcf0884b38fa
2023-06-01 10:24:42 -04:00
e8b6914517 videoprovider: expose the renderer's active value QML
Simplifies the property `activeRenderers`.

Gitlab: #1161
Change-Id: I4d39aaf3b96bba774c2492551f0426ea42446690
2023-06-01 10:24:42 -04:00
da5d041227 videoprovider: do not remove the FrameObject when unsubscribing
The end of the lifetime of the FrameObject should be determined by the underlying renderer.

Change-Id: I91026764a20a8451d6e71ffa98ee8cbea55272c4
2023-06-01 10:24:42 -04:00
5a48bccd25 swarmdetailspanel: some ui fixes
Change-Id: I6c00b128284e5b86de7905aca9cb548523dfc3b0
GitLab: #1072
2023-06-01 09:55:37 -04:00
d4b3048e8e usernametextedit: create account page should use default nameserver
Change-Id: I11a25c6121171eb4fb99b492cc18c32b085b4aaa
GitLab: #1159
2023-05-31 09:49:26 -04:00
087135cccf rtl: fix system settings page layout
Change-Id: I98bcd5b691cb8642900d1812cfcbcb6da3927c38
GitLab: #1133
2023-05-31 09:49:02 -04:00
8520ddaa83 WelcomePage: add responsive width to About button
Gitlab: #886

Change-Id: I949651c9fb2aee81b2c5183b56a416c2f681aace
2023-05-30 14:34:11 -04:00
7d856899c3 EmojiPicker: Left align to match the emoji button
Gitlab: #1150
Change-Id: I21edc4e1dec474d2fef8a3104edff2e79cdce30f
2023-05-30 14:16:18 -04:00
63687acc71 install: bumped Qt 6.2 to 6.4
Change-Id: I39262a1945ab48f43efbb958ebe323f52f5d1a8d
2023-05-30 14:14:14 -04:00
860f59893b SettingsSidePanel: implement deselect function
Gitlab: #1130

Change-Id: I166d41f495278a8d8a7c918e1d6d818108acae4e
2023-05-30 14:13:38 -04:00
39264e59c2 build: fix packaging with sdbus-c++
Change-Id: Ie7ab5f35d0f215cd32932f277dd7cc178e0dd2cc
2023-05-30 11:26:30 -04:00
370 changed files with 320747 additions and 313292 deletions

3
.gitignore vendored
View File

@ -30,6 +30,9 @@ install/
*.log
*.pid
# tests
Testing/
# auto-gen files
src/app/resources.qrc
src/app/qml.qrc

View File

@ -3,6 +3,5 @@ host = https://www.transifex.com
[o:savoirfairelinux:p:jami:r:jami_client_qt]
file_filter = translations/jami_client_qt_<lang>.ts
source_file = translations/jami_client_qt.ts
source_lang = en
source_file = translations/jami_client_qt_en.ts
type = TS

View File

@ -74,16 +74,19 @@ set(TESTS_DIR ${PROJECT_SOURCE_DIR}/tests)
# Here we let find_package(<PackageName>...) try to find Qt 6,
# If it is found, find_package will succeed, and the CMake variable
# QT_VERSION_MAJOR will be defined 6.
set(QT6_MINVER_MINOR 4)
if(QT6_VER AND QT6_PATH)
find_package(QT NAMES Qt6 REQUIRED
PATHS ${QT6_PATH} NO_DEFAULT_PATH)
else()
message(STATUS "Looking for Qt 6" ${CMAKE_PREFIX_PATH})
find_package(QT NAMES Qt6 REQUIRED)
endif()
if (${QT_VERSION_MAJOR} STRLESS 6)
if (${QT_VERSION_MINOR} STRLESS 2)
message(FATAL_ERROR "Qt 6.2 or higher is required.")
endif()
if (${QT_VERSION_MINOR} GREATER_EQUAL ${QT6_MINVER_MINOR})
# Qt version is 6.4 or higher
message(STATUS "Found a suitable Qt version ${QT_VERSION}")
else()
message(FATAL_ERROR "Qt 6.4 or higher is required. Found ${QT_VERSION}")
endif()
if(MSVC)
@ -206,6 +209,7 @@ set(COMMON_SOURCES
${APP_SRC_DIR}/pluginadapter.cpp
${APP_SRC_DIR}/deviceitemlistmodel.cpp
${APP_SRC_DIR}/pluginlistmodel.cpp
${APP_SRC_DIR}/pluginstorelistmodel.cpp
${APP_SRC_DIR}/pluginhandlerlistmodel.cpp
${APP_SRC_DIR}/preferenceitemlistmodel.cpp
${APP_SRC_DIR}/mediacodeclistmodel.cpp
@ -238,13 +242,15 @@ set(COMMON_SOURCES
${APP_SRC_DIR}/positioning.cpp
${APP_SRC_DIR}/currentcall.cpp
${APP_SRC_DIR}/messageparser.cpp
${APP_SRC_DIR}/previewengine.cpp)
${APP_SRC_DIR}/previewengine.cpp
${APP_SRC_DIR}/imagedownloader.cpp
${APP_SRC_DIR}/pluginversionmanager.cpp)
set(COMMON_HEADERS
${APP_SRC_DIR}/avatarimageprovider.h
${APP_SRC_DIR}/networkmanager.h
${APP_SRC_DIR}/smartlistmodel.h
${APP_SRC_DIR}/updatemanager.h
${APP_SRC_DIR}/appversionmanager.h
${APP_SRC_DIR}/utils.h
${APP_SRC_DIR}/bannedlistmodel.h
${APP_SRC_DIR}/version.h
@ -266,6 +272,7 @@ set(COMMON_HEADERS
${APP_SRC_DIR}/pluginadapter.h
${APP_SRC_DIR}/deviceitemlistmodel.h
${APP_SRC_DIR}/pluginlistmodel.h
${APP_SRC_DIR}/pluginstorelistmodel.h
${APP_SRC_DIR}/pluginhandlerlistmodel.h
${APP_SRC_DIR}/preferenceitemlistmodel.h
${APP_SRC_DIR}/mediacodeclistmodel.h
@ -301,7 +308,10 @@ set(COMMON_HEADERS
${APP_SRC_DIR}/positioning.h
${APP_SRC_DIR}/currentcall.h
${APP_SRC_DIR}/messageparser.h
${APP_SRC_DIR}/htmlparser.h)
${APP_SRC_DIR}/htmlparser.h
${APP_SRC_DIR}/imagedownloader.h
${APP_SRC_DIR}/pluginversionmanager.h)
# For libavutil/avframe.
set(LIBJAMI_CONTRIB_DIR "${DAEMON_DIR}/contrib")
@ -333,7 +343,7 @@ if(MSVC)
list(APPEND COMMON_SOURCES
${APP_SRC_DIR}/connectivitymonitor.cpp
${APP_SRC_DIR}/updatemanager.cpp)
${APP_SRC_DIR}/appversionmanager.cpp)
# preprocessor defines
add_definitions(-DUNICODE -DQT_NO_DEBUG -DNDEBUG)
@ -363,7 +373,7 @@ if(MSVC)
# daemon
set(JAMID_SRC_PATH ${DAEMON_DIR}/contrib/msvc/include)
set(JAMID_LIB ${DAEMON_DIR}/build/x64/ReleaseLib_win32/bin/jami.lib)
set(JAMID_LIB ${DAEMON_DIR}/build/x64/ReleaseLib_win32/bin/libjami.lib)
set(GNUTLS_LIB ${DAEMON_DIR}/contrib/msvc/lib/x64/libgnutls.lib)
# Beta config
@ -385,7 +395,7 @@ elseif (NOT APPLE)
${APP_SRC_DIR}/xrectsel.c
${APP_SRC_DIR}/connectivitymonitor.cpp
${APP_SRC_DIR}/dbuserrorhandler.cpp
${APP_SRC_DIR}/updatemanager.cpp)
${APP_SRC_DIR}/appversionmanager.cpp)
list(APPEND COMMON_HEADERS
${APP_SRC_DIR}/xrectsel.h
${APP_SRC_DIR}/dbuserrorhandler.h)
@ -437,7 +447,7 @@ elseif (NOT APPLE)
find_library(X11 X11)
else() # APPLE
list(APPEND COMMON_SOURCES
${APP_SRC_DIR}/os/macos/updatemanager.mm
${APP_SRC_DIR}/os/macos/appversionmanager.mm
${APP_SRC_DIR}/os/macos/connectivitymonitor.mm
${APP_SRC_DIR}/os/macos/macutils.mm)
list(APPEND COMMON_HEADERS

View File

@ -7,49 +7,55 @@ There are essentially two ways to build `client-qt`:
## Disclaimer
Because the client-qt is multi-platforms and supporting macOS, we need a recent version of Qt to do rendering with Metal. So, Qt 6.2 is necessary.
Because the client-qt is multi-platforms and supporting macOS, we need a recent version of Qt to do rendering with Metal. So, Qt 6.4 is necessary.
This version is generally not packaged on a lot of platforms, and to control available plugins and such, we have our own Qt packaged (available on https://jami.net on the distributions we support).
So, you will need to get Qt 6.2 first. For this, there is 3 methods:
So, you will need to get Qt 6.4 first. For this, there is 3 methods:
### Qt from https://jami.net (recommended)
### Qt from our repo (recommended)
If your distribution is supported, we provide a Qt package (libqt-jami) on our repo.
The files will be installed in `/usr/lib/libqt-jami`.
#### Install libqt-jami, Debian based
```
sudo apt install gnupg dirmngr ca-certificates curl --no-install-recommends
curl -s https://dl.jami.net/public-key.gpg | sudo tee /usr/share/keyrings/jami-archive-keyring.gpg > /dev/null
sudo sh -c "echo 'deb [signed-by=/usr/share/keyrings/jami-archive-keyring.gpg] https://dl.jami.net/nightly/debian_<VERSION>/ jami main' > /etc/apt/sources.list.d/jami.list"
sudo apt-get update && sudo apt-get install jami
```
#### Install libqt-jami, Ubuntu based
```
To install libqt-jami on Ubuntu, execute these commands replacing `ubuntu_<VERSION>` by your distribution version. For example "ubuntu_22.04"
```bash
sudo apt install gnupg dirmngr ca-certificates curl --no-install-recommends
curl -s https://dl.jami.net/public-key.gpg | sudo tee /usr/share/keyrings/jami-archive-keyring.gpg > /dev/null
sudo sh -c "echo 'deb [signed-by=/usr/share/keyrings/jami-archive-keyring.gpg] https://dl.jami.net/nightly/ubuntu_<VERSION>/ jami main' > /etc/apt/sources.list.d/jami.list"
sudo apt-get update && sudo apt-get install libqt-jami
```
#### Install libqt-jami, Debian based
To install libqt-jami on Debian, execute these commands replacing `debian_<VERSION>` by your distribution version. For example "debian_11"
```bash
sudo apt install gnupg dirmngr ca-certificates curl --no-install-recommends
curl -s https://dl.jami.net/public-key.gpg | sudo tee /usr/share/keyrings/jami-archive-keyring.gpg > /dev/null
sudo sh -c "echo 'deb [signed-by=/usr/share/keyrings/jami-archive-keyring.gpg] https://dl.jami.net/nightly/debian_<VERSION>/ jami main' > /etc/apt/sources.list.d/jami.list"
sudo apt-get update && sudo apt-get install jami
```
#### Install jami-libqt, Fedora based
```
To install libqt-jami on Fedora, execute these commands replacing `fedora_<VERSION>` by your distribution version. For example "fedora_38"
```bash
sudo dnf config-manager --add-repo https://dl.jami.net/nightly/fedora_<VERSION>/jami-nightly.repo
sudo dnf update && sudo dnf install jami-libqt
```
### Qt from your distribution
If Qt 6.2 is available, you can use the packages from your distribution:
If Qt 6.4 is available, you can use the packages from your distribution:
It should be (For now qt5 only is packaged by distributions, so names can change).
#### Dependencies, Debian based
```
```bash
sudo apt-get install cmake make doxygen g++ gettext libnotify-dev pandoc nasm libqrencode-dev \
libnotify-dev libnm-dev \
qt6-base-dev \
@ -66,7 +72,7 @@ sudo apt-get install cmake make doxygen g++ gettext libnotify-dev pandoc nasm li
#### Dependencies, Fedora based
```
```bash
sudo dnf install qt6-qtsvg-devel qt6-qtwebengine-devel qt6-qtmultimedia-devel qt6-qtdeclarative-devel qt6-qtquickcontrols2-devel qt6-qtquickcontrols qrencode-devel NetworkManager-libnm-devel
```
@ -87,6 +93,11 @@ for getting the latest development versions; otherwise, you can use
`git submodule update --init` then checkout specific commits for each
submodule).
If you're a developer you need to install clang-format separately before initializing with the command
```bash
sudo apt install clang-format
```
```bash
./build.py --init [--qt=<path/to/qt> (this is required for qmlformatting to work)]
```
@ -96,7 +107,7 @@ Then you will need to install dependencies:
- For GNU/Linux
```bash
./build.py --dependencies # needs sudo
sudo ./build.py --dependencies
```
Then, you can build daemon and the client using:
@ -107,9 +118,9 @@ Then, you can build daemon and the client using:
If you use a Qt version that is not system-wide installed, you need to
specify its path using the `--qt` flag, e.g.
`./build.py --install --qt=/home/<username>/Qt/6.2.1/gcc_64`.
`./build.py --install --qt=/home/<username>/Qt/6.4.1/gcc_64`.
Now you will have the daemon in `daemon/bin/jamid` and the client in
Now you will have the daemon in `daemon/bin/dbus/jamid` and the client in
`build/jami`. You can now run Jami using:
```bash
@ -123,7 +134,7 @@ Notes:
## Build only the client
In order to use the Qt Client it is necessary to have the Qt version 6.2 or higher. If your system does not have it you can install it [from sources or download the binary installer](https://www.qt.io/download).
In order to use the Qt Client it is necessary to have the Qt version 6.4 or higher. If your system does not have it you can install it [from sources or download the binary installer](https://www.qt.io/download).
## Build only this repository
@ -173,7 +184,7 @@ Only 64-bit MSVC build can be compiled.
- Download [Qt (Open Source)](https://www.qt.io/download-open-source?hsCtaTracking=9f6a2170-a938-42df-a8e2-a9f0b1d6cdce%7C6cb0de4f-9bb5-4778-ab02-bfb62735f3e5)
- Using the online installer, install the following Qt 6.2.3 components:
- Using the online installer, install the following Qt 6.4.3 components:
- Git 2.10.2
- MSVC 2019 64-bit
@ -196,7 +207,7 @@ Only 64-bit MSVC build can be compiled.
| | Qt Version |
| -------------------- | ---------- |
| Minimum requirement: | 6.2.3 |
| Minimum requirement: | 6.4.3 |
- Install [Python3](https://www.python.org/downloads/) for Windows
@ -222,7 +233,7 @@ Only 64-bit MSVC build can be compiled.
- Using a new **Non-Elevated Command Prompt**
```bash
python build.py --install --qt <path-to-qt-bin-folder> (e.g. C:/Qt/6.2.3/msvc2019_64)
python build.py --install --qt <path-to-qt-bin-folder> (e.g. C:/Qt/6.4.3/msvc2019_64)
```
> **SDK** Note:
@ -265,7 +276,7 @@ Once the build has finished, you should then be able to use the Visual Studio So
```
python extras\scripts\build-windows.py --init
python extras\scripts\build-windows.py --qt <path-to-qt-bin-folder> (e.g. C:/Qt/6.2.3/msvc2019_64)
python extras\scripts\build-windows.py --qt <path-to-qt-bin-folder> (e.g. C:/Qt/6.4.3/msvc2019_64)
```
## Building On MacOS
@ -275,9 +286,9 @@ Once the build has finished, you should then be able to use the Visual Studio So
- macOS minimum version 10.15
- install python3
- download xcode
- install Qt 6.2
- install Qt 6.4
Qt 6.2 can be installed via brew
Qt 6.4 can be installed via brew
```bash
brew install qt

View File

@ -92,7 +92,7 @@ ZYPPER_INSTALL_SCRIPT = [
ZYPPER_DEPENDENCIES = [
# build system
'autoconf', 'autoconf-archive', 'automake', 'cmake', 'make', 'patch', 'gcc-c++',
'libtool', 'which', 'pandoc', 'nasm', 'doxygen', 'graphviz',
'libtool', 'which', 'pandoc', 'nasm', 'doxygen', 'graphviz', 'systemd-devel',
# contrib dependencies
'curl', 'gzip', 'bzip2',
# daemon
@ -152,7 +152,7 @@ APT_DEPENDENCIES = [
'libspeex-dev', 'libspeexdsp-dev', 'libswscale-dev', 'libtool',
'libudev-dev', 'libyaml-cpp-dev', 'sip-tester', 'swig',
'uuid-dev', 'yasm', 'libjsoncpp-dev', 'libva-dev', 'libvdpau-dev', 'libmsgpack-dev',
'pandoc', 'nasm', 'dpkg-dev'
'pandoc', 'nasm', 'dpkg-dev', 'libsystemd-dev'
]
APT_CLIENT_DEPENDENCIES = [
@ -181,7 +181,7 @@ PACMAN_DEPENDENCIES = [
'gcc', 'ffmpeg', 'boost', 'cppunit', 'libdbus', 'dbus-c++', 'libe-book', 'expat',
'jack', 'opus', 'pcre', 'libpulse', 'speex', 'speexdsp', 'libtool', 'yaml-cpp',
'swig', 'yasm', 'make', 'patch', 'pkg-config',
'automake', 'libva', 'libvdpau', 'openssl', 'pandoc', 'nasm'
'automake', 'libva', 'libvdpau', 'openssl', 'pandoc', 'nasm', 'systemd-libs'
]
PACMAN_CLIENT_DEPENDENCIES = [
@ -329,7 +329,7 @@ def run_init(args):
# The client submodule has QML files, so we need to run qmlformat on it,
# and thus need to supply the Qt path.
execute_script([f'{format_script} --install {client_hooks_dir}'
f' --qt {args.qt}' if args.qt else ''],
f' --qt {args.qt}'],
{"path": client_hooks_dir})
# The daemon submodule has no QML files, so we don't need to run
@ -416,6 +416,11 @@ def run_install(args):
command = ['extras/scripts/install.sh'] + install_args
if 'TARBALLS' not in os.environ:
print('info: consider setting the TARBALLS environment variable '
'to a stable writable location to avoid loosing '
'cached tarballs')
if args.distribution == 'guix':
if args.global_install:
print('error: global install is not supported when using Guix.')
@ -425,10 +430,6 @@ def run_install(args):
if 'TARBALLS' in os.environ:
share_tarballs_args = ['--preserve=TARBALLS',
f'--share={os.environ["TARBALLS"]}']
else:
print('info: consider setting the TARBALLS environment variable '
'to a stable writable location to avoid loosing '
'cached tarballs')
command = ['guix', 'shell', f'--manifest={GUIX_MANIFEST}',
'--symlink=/usr/bin/env=bin/env',
'--symlink=/etc/ssl/certs=etc/ssl/certs',

2
daemon

Submodule daemon updated: 2eea2ce34d...ac9fdd465f

View File

@ -53,6 +53,11 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES_orig ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib;.so;.dll")
# Add the lib prefix for Windows checks.
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(CMAKE_FIND_LIBRARY_PREFIXES "lib;")
endif()
if(WITH_DAEMON_SUBMODULE)
find_library(LIBJAMI_LIB NAMES jami ring
PATHS ${DAEMON_DIR}/src/.libs

View File

@ -22,7 +22,7 @@ RUN apt-get install -y -o Acquire::Retries=10 \
cmake \
libtool \
libdbus-1-dev \
libdbus-c++-dev \
libsystemd-dev \
libargon2-0-dev \
libcanberra-gtk3-dev \
libclutter-gtk-1.0-dev \
@ -66,4 +66,4 @@ RUN apt-get install -y -o Acquire::Retries=10 \
libssl-dev
RUN apt-get install -y pandoc \
googletest \
libgtest-dev
libgtest-dev

View File

@ -215,7 +215,7 @@ make -f ${PACKAGING_DIR}/Makefile portable-release-tarball .tarball-version
}
stage('Sign & deploy packages') {
agent {
label 'ring-buildmachine-02.mtl.sfl'
label 'jami-buildmachine-02.mtl.sfl'
}
when {

View File

@ -49,7 +49,7 @@ QT_MAJOR := 6
QT_MINOR := 4
QT_PATCH := 3
QT_TARBALL_CHECKSUM := 29a7eebdbba0ea57978dea6083709c93593a60f0f3133a3de08b9571ee8eaab4
DEBIAN_QT_VERSION := $(QT_MAJOR).$(QT_MINOR).$(QT_PATCH)-1
DEBIAN_QT_VERSION := $(QT_MAJOR).$(QT_MINOR).$(QT_PATCH)-2
DEBIAN_QT_DSC_FILENAME := libqt-jami_$(DEBIAN_QT_VERSION).dsc
QT_JAMI_PREFIX := /usr/lib/libqt-jami
@ -161,13 +161,12 @@ endif
#
DISTRIBUTIONS := \
debian_11 \
debian_12 \
debian_testing \
debian_unstable \
ubuntu_20.04 \
ubuntu_22.04 \
ubuntu_22.10 \
ubuntu_23.04 \
fedora_36 \
fedora_37 \
fedora_38 \
opensuse-leap_15.4 \

View File

@ -1,4 +1,4 @@
FROM ubuntu:22.10
FROM debian:bookworm
ENV DEBIAN_FRONTEND=noninteractive

View File

@ -9,7 +9,6 @@ RUN apt-get update && \
equivs \
python-is-python3 \
libdbus-1-dev \
libdbus-c++-dev \
wget
ADD extras/packaging/gnu-linux/scripts/prebuild-package-debian.sh /opt/prebuild-package-debian.sh

View File

@ -1,106 +0,0 @@
FROM fedora:36
RUN dnf clean all
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 \
dbus-c++-devel \
dbus-devel \
libXext-devel \
libXfixes-devel \
yasm \
python2.7 \
python3-html5lib \
speex-devel \
gsm-devel \
chrpath \
check \
astyle \
uuid-c++-devel \
gettext-devel \
gcc-c++ \
which \
alsa-lib-devel \
systemd-devel \
libuuid-devel \
uuid-devel \
gnutls-devel \
nettle-devel \
opus-devel \
patch \
jsoncpp-devel \
libnatpmp-devel \
webkitgtk4-devel \
cryptopp-devel \
libva-devel \
libvdpau-devel \
msgpack-devel \
NetworkManager-libnm-devel \
openssl-devel \
clutter-devel \
clutter-gtk-devel \
libappindicator-gtk3-devel \
libnotify-devel \
libupnp-devel \
qrencode-devel \
libargon2-devel \
libsndfile-devel \
libdrm \
gperf \
bison \
clang \
clang-devel \
llvm-devel \
nodejs \
flex \
gstreamer1 gstreamer1-devel \
gstreamer1-plugins-base-devel \
gstreamer1-plugins-good \
gstreamer1-plugins-bad-free-devel \
nss-devel \
libxcb* \
libxkb* \
libX11-devel \
vulkan-devel \
libXrender-devel \
xcb-util-* \
xz \
xkeyboard-config \
libnotify \
wget \
libstdc++-static \
sqlite-devel \
perl-generators \
perl-English \
libxshmfence-devel \
ninja-build \
clang \
cmake \
fmt-devel \
cups-devel #Chromium for Qt
ADD extras/packaging/gnu-linux/scripts/build-package-rpm.sh /opt/build-package-rpm.sh
CMD ["/opt/build-package-rpm.sh"]

View File

@ -27,8 +27,6 @@ RUN dnf install -y \
expat-devel \
pcre-devel \
yaml-cpp-devel \
dbus-c++-devel \
dbus-devel \
libXext-devel \
libXfixes-devel \
yasm \

View File

@ -27,8 +27,6 @@ RUN dnf install -y \
expat-devel \
pcre-devel \
yaml-cpp-devel \
dbus-c++-devel \
dbus-devel \
libXext-devel \
libXfixes-devel \
yasm \

View File

@ -23,7 +23,6 @@ RUN zypper --non-interactive install -y \
libtool \
pcre-devel \
yaml-cpp-devel \
libdbus-c++-devel \
libXext-devel \
libXfixes-devel \
yasm \
@ -51,7 +50,6 @@ RUN zypper --non-interactive install -y \
clutter-gtk-devel \
libnma-devel \
libcryptopp-devel \
libdbus-c++-devel \
libexpat-devel \
gnome-icon-theme-symbolic \
libgsm-devel \

View File

@ -0,0 +1,52 @@
From f4410fcbb093f259eaff4a20fc4266a535479235 Mon Sep 17 00:00:00 2001
From: Sebastien Blin <sebastien.blin@savoirfairelinux.com>
Date: Mon, 29 May 2023 13:09:53 -0400
Subject: [PATCH] OpenFile portal: do not use O_PATH fds
Using O_PATH requires correctly specifying whether the fd is writable or
not. Stating that the fd is writable without it actually being writable
results into rejection on xdg-desktop-portal side. Other implementations
like xdg-open or gtk have also moved away from O_PATH fds so this will
make a matching implementation and avoid possible rejections from xdp.
Fixes: QTBUG-113143
Original: https://codereview.qt-project.org/c/qt/qtbase/+/475425
---
qtbase/src/gui/platform/unix/qgenericunixservices.cpp | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/qtbase/src/gui/platform/unix/qgenericunixservices.cpp b/qtbase/src/gui/platform/unix/qgenericunixservices.cpp
index a0e5466c58..fe0fdaa625 100644
--- a/qtbase/src/gui/platform/unix/qgenericunixservices.cpp
+++ b/qtbase/src/gui/platform/unix/qgenericunixservices.cpp
@@ -163,8 +163,7 @@ static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url)
// handle_token (s) - A string that will be used as the last element of the @handle.
// writable (b) - Whether to allow the chosen application to write to the file.
-#ifdef O_PATH
- const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_PATH);
+ const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_RDONLY);
if (fd != -1) {
QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
"/org/freedesktop/portal/desktop"_L1,
@@ -174,16 +173,13 @@ static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url)
QDBusUnixFileDescriptor descriptor;
descriptor.giveFileDescriptor(fd);
- const QVariantMap options = {{"writable"_L1, true}};
+ const QVariantMap options = {};
// FIXME parent_window_id
message << QString() << QVariant::fromValue(descriptor) << options;
return QDBusConnection::sessionBus().call(message);
}
-#else
- Q_UNUSED(url);
-#endif
return QDBusMessage::createError(QDBusError::InternalError, qt_error_string());
}
--
2.40.1

View File

@ -1 +1,2 @@
0001-fix-gcc13.patch
0001-fix-gcc13.patch
0002-OpenFile-portal-do-not-use-O_PATH-fds.patch

View File

@ -16,7 +16,7 @@ Build-Depends: debhelper (>= 9),
libayatana-appindicator3-dev | libappindicator3-dev,
# daemon
libdbus-1-dev,
libdbus-c++-dev,
libsystemd-dev,
libupnp-dev,
libgnutls28-dev,
libpulse-dev,
@ -68,7 +68,7 @@ Depends: gnupg,
Replaces: jami,
jami-libclient,
jami-daemon,
libqt-jami (>= 6.2.3),
libqt-jami (>= 6.4.3),
Conflicts: jami,
jami-libclient,
jami-libclient-gnome,
@ -84,7 +84,7 @@ Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
jami-daemon (=${binary:Version}),
libqt-jami (>= 6.2.3)
libqt-jami (>= 6.4.3)
Provides: jami-qt
Replaces: jami-all,
jami-libclient (<= 20220516.0214.9b42ad3~dfsg1-1)

View File

@ -93,12 +93,12 @@ if [ -f /etc/os-release ]; then
# Set-up Jami repository end tag
if [ "${VERSION_CODENAME}" = "bullseye" ] || [ "${ID}_${VERSION_ID}" = "debian_11" ]; then
ENDTAG="debian_11"
elif [ "${VERSION_CODENAME}" = "bookworm" ] || [ "${ID}_${VERSION_ID}" = "debian_12" ]; then
ENDTAG="debian_12"
elif [ "${UBUNTU_CODENAME}" = "focal" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_20.04" ]; then
ENDTAG="ubuntu_20.04"
elif [ "${UBUNTU_CODENAME}" = "jammy" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_22.04" ]; then
ENDTAG="ubuntu_22.04"
elif [ "${UBUNTU_CODENAME}" = "kinetic" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_22.10" ]; then
ENDTAG="ubuntu_22.10"
elif [ "${UBUNTU_CODENAME}" = "lunar" ] || [ "${ID}_${VERSION_ID}" = "ubuntu_23.04" ]; then
ENDTAG="ubuntu_23.04"
elif [ "${ID}" = "debian" ] && \

View File

@ -35,7 +35,7 @@ BuildRequires: opus-devel
BuildRequires: pulseaudio-libs-devel
%endif
%if %{defined suse_version}
BuildRequires: libdbus-c++-devel
BuildRequires: systemd-devel
BuildRequires: libexpat-devel
BuildRequires: libopus-devel
BuildRequires: libpulse-devel

View File

@ -27,6 +27,7 @@ Vendor: Savoir-faire Linux Inc.
URL: https://jami.net/
Source: jami-libqt-%{version}.tar.xz
Patch0: 0001-fix-gcc13.patch
Patch1: 0002-OpenFile-portal-do-not-use-O_PATH-fds.patch
%global gst 0.10
%if 0%{?fedora} || 0%{?rhel} > 7
@ -62,10 +63,11 @@ This package contains Qt libraries for Jami.
%prep
%setup -n qt-everywhere-src-%{version}
%patch0 -p1
%patch1 -p1
%build
echo "Building Qt using %{job_count} parallel jobs"
# Qt 6.2 (https://wiki.linuxfromscratch.org/blfs/ticket/14729)
# Qt 6.4 (https://wiki.linuxfromscratch.org/blfs/ticket/14729)
sed -i 's,default=False,default=True,g' qtwebengine/src/3rdparty/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents.py
# Gcc 13
sed -i 's,std::uint32_t,uint32_t,g' qt3d/src/3rdparty/assimp/src/code/AssetLib/FBX/FBXBinaryTokenizer.cpp

View File

@ -0,0 +1,52 @@
From f4410fcbb093f259eaff4a20fc4266a535479235 Mon Sep 17 00:00:00 2001
From: Sebastien Blin <sebastien.blin@savoirfairelinux.com>
Date: Mon, 29 May 2023 13:09:53 -0400
Subject: [PATCH] OpenFile portal: do not use O_PATH fds
Using O_PATH requires correctly specifying whether the fd is writable or
not. Stating that the fd is writable without it actually being writable
results into rejection on xdg-desktop-portal side. Other implementations
like xdg-open or gtk have also moved away from O_PATH fds so this will
make a matching implementation and avoid possible rejections from xdp.
Fixes: QTBUG-113143
Original: https://codereview.qt-project.org/c/qt/qtbase/+/475425
---
qtbase/src/gui/platform/unix/qgenericunixservices.cpp | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/qtbase/src/gui/platform/unix/qgenericunixservices.cpp b/qtbase/src/gui/platform/unix/qgenericunixservices.cpp
index a0e5466c58..fe0fdaa625 100644
--- a/qtbase/src/gui/platform/unix/qgenericunixservices.cpp
+++ b/qtbase/src/gui/platform/unix/qgenericunixservices.cpp
@@ -163,8 +163,7 @@ static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url)
// handle_token (s) - A string that will be used as the last element of the @handle.
// writable (b) - Whether to allow the chosen application to write to the file.
-#ifdef O_PATH
- const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_PATH);
+ const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_RDONLY);
if (fd != -1) {
QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
"/org/freedesktop/portal/desktop"_L1,
@@ -174,16 +173,13 @@ static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url)
QDBusUnixFileDescriptor descriptor;
descriptor.giveFileDescriptor(fd);
- const QVariantMap options = {{"writable"_L1, true}};
+ const QVariantMap options = {};
// FIXME parent_window_id
message << QString() << QVariant::fromValue(descriptor) << options;
return QDBusConnection::sessionBus().call(message);
}
-#else
- Q_UNUSED(url);
-#endif
return QDBusMessage::createError(QDBusError::InternalError, qt_error_string());
}
--
2.40.1

View File

@ -308,8 +308,7 @@ parts:
- libexpat1-dev
- libjsoncpp-dev
- libnm-dev # connectivityChanged()
- libdbus-1-dev # dbus
- libdbus-c++-dev
- libsystemd-dev # sdbus-cpp
- libpulse-dev # pulse
- libudev-dev
- libopus-dev # Avoid to build opus from contrib

View File

@ -46,7 +46,7 @@ CMAKE_PREFIX_PATH="${QT_JAMI_PREFIX}/lib/cmake:${CMAKE_PREFIX_PATH}"
QT_MAJOR=6
QT_MINOR=4
QT_PATCH=3
QT_RELEASE_PATCH=1
QT_RELEASE_PATCH=2
QT_MAJOR_MINOR=${QT_MAJOR}.${QT_MINOR}
QT_MAJOR_MINOR_PATCH=${QT_MAJOR}.${QT_MINOR}.${QT_PATCH}

View File

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

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
"""
Build, test, and package the project.
@ -27,7 +28,7 @@ mutually exclusive required arguments:
-z, --zip Build portable archive
examples:
1. build.py --qt=C:/Qt/6.2.3/msvc2019_64 # Build the app using a specific Qt
1. build.py --qt=C:/Qt/6.4.3/msvc2019_64 # Build the app using a specific Qt
2. build.py --init pack --msi # Build the app and an MSI installer
3. build.py --init --tests # Build the app and run tests
build.py pack --zip --skip-build # Generate a 7z archive of the app
@ -293,11 +294,11 @@ def build(config_str, qt_dir, tests):
sys.exit(1)
def deploy_runtimes(qt_dir):
def deploy_runtimes(config_str, qt_dir):
"""Deploy the dependencies to the runtime directory."""
print("Deploying runtime dependencies")
runtime_dir = os.path.join(repo_root_dir, "x64", "Release")
runtime_dir = os.path.join(repo_root_dir, "x64", config_str)
stamp_file = os.path.join(runtime_dir, ".deploy.stamp")
if os.path.exists(stamp_file):
return
@ -340,8 +341,12 @@ def deploy_runtimes(qt_dir):
print("Running windeployqt (this may take a while)...")
win_deploy_qt = os.path.join(qt_dir, "bin", "windeployqt.exe")
qml_src_dir = os.path.join(repo_root_dir, "src", "app")
os.environ["VCINSTALLDIR"] = os.path.join(
get_vs_prop("installationPath"), "VC")
installation_dir = get_vs_prop("installationPath")
if not installation_dir:
print("Visual Studio not found. Please install Visual Studio 2017 or "
"later.")
sys.exit(1)
os.environ["VCINSTALLDIR"] = os.path.join(installation_dir, "VC")
executable = os.path.join(runtime_dir, "Jami.exe")
execute_cmd([win_deploy_qt, "--verbose", "1", "--no-compiler-runtime",
"--qmldir", qml_src_dir, "--release", executable],
@ -371,11 +376,19 @@ def run_tests(config_str, qt_dir):
qt_dir, 'bin', 'QtWebEngineProcess.exe')
os.environ["QML2_IMPORT_PATH"] = os.path.join(qt_dir, "qml")
cmd = ["ctest", "-V", "-C", config_str]
# On Windows, when running on a jenkins slave, the QML tests don't output
# anything to stdout/stderr. Workaround by outputting to a file and then
# printing the contents of the file.
if os.environ.get("JENKINS_URL"):
cmd += ["--output-log", "test.log", "--quiet"]
tests_dir = os.path.join(build_dir, "tests")
if execute_cmd(["ctest", "-V", "-C", config_str],
False, None, tests_dir):
print("Tests failed.")
sys.exit(1)
exit_code = execute_cmd(cmd, False, None, tests_dir)
# Print the contents of the log file.
if os.environ.get("JENKINS_URL"):
with open(os.path.join(tests_dir, "test.log"), "r") as file:
print(file.read())
sys.exit(exit_code)
def generate_msi(version):
@ -483,7 +496,11 @@ def main():
print("These scripts will only run on a 64-bit system for now.")
sys.exit(1)
if sys.platform == "win32":
vs_version = get_vs_prop("installationVersion").split(".")[0]
vs_version = get_vs_prop("installationVersion")
if vs_version is None:
print("Visual Studio version not found.")
sys.exit(1)
vs_version = vs_version.split(".")[0]
if vs_version is None or int(vs_version) < 15:
print("Visual Studio 2017 or later is required.")
sys.exit(1)
@ -516,7 +533,7 @@ def main():
if not parsed_args.skip_build:
build(config_str, parsed_args.qt, do_tests)
if not parsed_args.skip_deploy:
deploy_runtimes(parsed_args.qt)
deploy_runtimes(config_str, parsed_args.qt)
if parsed_args.subcommand == "pack":
do_build(False)

View File

@ -52,7 +52,7 @@ for ARCH in "${ARCHS[@]}"; do
# force to build every contrib
for dir in "$DAEMON"/contrib/src/*/; do
PKG=$(basename -- "$dir")
if [ "$PKG" != "dbus-cpp" ] && [ "$PKG" != "natpmp" ] &&
if [ "$PKG" != "sdbus-cpp" ] && [ "$PKG" != "natpmp" ] &&
[ "$PKG" != "portaudio" ] && [ "$PKG" != "pthreads" ] &&
[ "$PKG" != "lttng-ust" ] && [ "$PKG" != "openssl" ] &&
[ "$PKG" != "media-sdk" ] && [ "$PKG" != "jack" ] &&

View File

@ -22,7 +22,7 @@ import shutil
from platform import uname
CFVERSION = "9"
CLANGFORMAT = ""
CLANGFORMAT = None
QMLFORMAT = None
@ -138,27 +138,29 @@ def main():
args = parser.parse_args()
if args.type in ["cpp", "both"]:
if not command_exists("clang-format-" + CFVERSION):
if not command_exists("clang-format"):
print("Required version of clang-format not found")
sys.exit(1)
else:
CLANGFORMAT = "clang-format"
else:
CLANGFORMAT = "clang-format-" + CFVERSION
if command_exists("clang-format-" + CFVERSION):
CLANGFORMAT = "clang-format-" + CFVERSION
elif command_exists("clang-format"):
CLANGFORMAT = "clang-format"
if CLANGFORMAT is not None:
print("Using source formatter: " + CLANGFORMAT)
else:
print("clang-format not found. can't format source files")
if args.qt is not None and args.type in ["qml", "both"]:
global QMLFORMAT # pylint: disable=global-statement
QMLFORMAT = find_qmlformat(args.qt)
if QMLFORMAT is not None:
print("Using qmlformatter: " + QMLFORMAT)
else:
print("No qmlformat found, can't format QML files")
if QMLFORMAT is not None:
print("Using qmlformatter: " + QMLFORMAT)
else:
print("qmlformat not found, can't format QML files")
if args.install:
install_hook(args.install, args.qt)
if CLANGFORMAT is not None or QMLFORMAT is not None:
install_hook(args.install, args.qt)
else:
print("No formatters found, skipping hook install")
sys.exit(0)
src_files = get_files([".cpp", ".cxx", ".cc", ".h", ".hpp"],

View File

@ -33,7 +33,7 @@ export OSTYPE
set -ex
# Qt_MIN_VER required for client-qt
QT_MIN_VER="6.2"
QT_MIN_VER="6.4"
debug=
global=false
@ -125,6 +125,8 @@ else
if [[ "$OSTYPE" != "darwin"* ]]; then
CONFIGURE_FLAGS+=" --disable-shared"
fi
else
CONFIGURE_FLAGS+="--without-dbus"
fi
BUILD_TYPE="Release"

View File

@ -10,4 +10,4 @@ if (-not(Test-Path -Path $QtDir)) {
$lupdate = "$QtDir\bin\lupdate.exe"
$tsFileNames = Get-ChildItem -Path "$clientDir\translations" -Recurse -Include *.ts
Invoke-Expression("$lupdate $clientDir\src -ts $tsFileNames -no-obsolete")
Invoke-Expression("$lupdate -extensions cpp,h,qml $clientDir\src -ts $tsFileNames -no-obsolete")

View File

@ -34,8 +34,6 @@
<string>Jami requires to access your camera to make calls and record video</string>
<key>NSMicrophoneUsageDescription</key>
<string>Jami requires to access your microphone to make calls and record audio</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Jami requires to access your photo library to show image on profile and send via chat</string>
<key>ITSAppUsesNonExemptEncryption</key>
<true/>
</dict>

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,14 @@
<?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-overview-4287788" transform="translate(-112.49 -112.51)">
<path id="Path_272" d="M134.5,133.4l-3.5-3.5c3.3-3.9,2.8-9.8-1.1-13.2c-3.9-3.3-9.8-2.8-13.2,1.1c-3.3,3.9-2.8,9.8,1.1,13.2
c3.5,2.9,8.6,2.9,12.1,0l3.5,3.5L134.5,133.4z M123.8,131.6c-4.3,0-7.8-3.5-7.8-7.8s3.5-7.8,7.8-7.8c4.3,0,7.8,3.5,7.8,7.8l0,0
C131.6,128.2,128.1,131.6,123.8,131.6L123.8,131.6z"/>
<path id="Path_273" d="M123.8,119.7c-3.5,0-6.2,1.8-6.2,4.1s2.7,4.1,6.2,4.1c3.5,0,6.2-1.8,6.2-4.1S127.3,119.7,123.8,119.7z
M123.8,126.6c-2.6,0-4.8-1.3-4.8-2.8s2.2-2.8,4.8-2.8c2.6,0,4.8,1.3,4.8,2.8S126.5,126.6,123.8,126.6z"/>
<path id="Path_274" d="M126.1,123.9c0,1.3-1,2.3-2.3,2.3c-1.3,0-2.3-1-2.3-2.3c0-1.3,1-2.3,2.3-2.3
C125.1,121.6,126.1,122.6,126.1,123.9L126.1,123.9"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<path d="M5.8,4.7h12.5c0.7,0,1.2,0.6,1.2,1.2v7.5c0,0.7-0.6,1.2-1.2,1.2h-12l2.9-2.9l-1.8-1.8l-5,5c-0.1,0.1-0.2,0.3-0.3,0.4
c-0.2,0.5-0.1,1,0.3,1.4l5,5L9.1,20l-2.9-2.9h12c2.1,0,3.7-1.7,3.7-3.7V5.9c0-2.1-1.7-3.7-3.7-3.7H5.8V4.7z"/>
</svg>

After

Width:  |  Height:  |  Size: 582 B

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<path d="M20.9,4.6H15V4.2C15,3,14,2,12.8,2h-1.6C10,2,9,3,9,4.2v0.3H3.1c-0.4,0-0.7,0.3-0.7,0.7s0.3,0.7,0.7,0.7h1.4l0.7,13.8
C5.2,21,6.3,22,7.6,22h8.9c1.3,0,2.4-1,2.4-2.3l0.7-13.8h1.4c0.4,0,0.7-0.3,0.7-0.7S21.3,4.6,20.9,4.6z M10.3,4.6V4.2
c0-0.5,0.4-0.8,0.8-0.8h1.6c0.5,0,0.8,0.4,0.8,0.8v0.3H10.3z M18.1,5.9l-0.7,13.7c0,0.6-0.5,1-1,1H7.6c-0.6,0-1-0.4-1-1L5.8,5.9
H18.1z"/>
</svg>

After

Width:  |  Height:  |  Size: 726 B

View File

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="26.503" height="26.5" viewBox="0 0 26.503 26.5">
<g id="noun-backup-2912773" transform="translate(-51.27 -51.32)">
<path id="Path_259" data-name="Path 259" d="M76.04,60.533H53a1.483,1.483,0,0,1-1.482-1.482v-6A1.483,1.483,0,0,1,53,51.57H76.04a1.483,1.483,0,0,1,1.482,1.482v6A1.483,1.483,0,0,1,76.04,60.533ZM53,52.014a1.038,1.038,0,0,0-1.037,1.037v6A1.038,1.038,0,0,0,53,60.089H76.04a1.038,1.038,0,0,0,1.037-1.037v-6a1.038,1.038,0,0,0-1.037-1.037Z" fill="#005699" stroke="#005699" stroke-width="0.5"/>
<path id="Path_260" data-name="Path 260" d="M72.468,779.243H53.042a1.483,1.483,0,0,1-1.482-1.482v-6a1.483,1.483,0,0,1,1.482-1.482h16.2a.222.222,0,1,1,0,.444h-16.2A1.038,1.038,0,0,0,52,771.762v6a1.038,1.038,0,0,0,1.037,1.037H72.468a.222.222,0,1,1,0,.444Z" transform="translate(-0.039 -701.673)" fill="#005699" stroke="#005699" stroke-width="0.5"/>
<path id="Path_261" data-name="Path 261" d="M723.843,728.9a5.093,5.093,0,1,1,5.093-5.093,5.1,5.1,0,0,1-5.093,5.093Zm0-9.741a4.649,4.649,0,1,0,3.079,1.166A4.642,4.642,0,0,0,723.843,719.156Z" transform="translate(-651.414 -651.328)" fill="#005699" stroke="#005699" stroke-width="0.5"/>
<path id="Path_262" data-name="Path 262" d="M77.382,423.416a.222.222,0,0,1-.222-.222V412.138a.76.76,0,0,0-.759-.759H52.807a.76.76,0,0,0-.759.759v6.556a.76.76,0,0,0,.759.759H69.285a.222.222,0,1,1,0,.444H52.807a1.205,1.205,0,0,1-1.2-1.2v-6.556a1.205,1.205,0,0,1,1.2-1.2H76.4a1.205,1.205,0,0,1,1.2,1.2v11.056A.222.222,0,0,1,77.382,423.416Z" transform="translate(-0.081 -350.845)" fill="#005699" stroke="#005699" stroke-width="0.5"/>
<path id="Path_263" data-name="Path 263" d="M168.967,149.643a.222.222,0,0,1-.222-.222v-3.889a.222.222,0,1,1,.444,0v3.889A.222.222,0,0,1,168.967,149.643Z" transform="translate(-114.446 -91.518)" fill="#005699" stroke="#005699" stroke-width="0.5"/>
<path id="Path_264" data-name="Path 264" d="M168.967,524.643a.222.222,0,0,1-.222-.222v-3.889a.222.222,0,1,1,.444,0v3.889A.222.222,0,0,1,168.967,524.643Z" transform="translate(-114.446 -457.629)" fill="#005699" stroke="#005699" stroke-width="0.5"/>
<path id="Path_265" data-name="Path 265" d="M168.967,899.623a.222.222,0,0,1-.222-.222v-3.889a.222.222,0,1,1,.444,0V899.4A.222.222,0,0,1,168.967,899.623Z" transform="translate(-114.446 -823.72)" fill="#005699" stroke="#005699" stroke-width="0.5"/>
<path id="Path_266" data-name="Path 266" d="M498.2,171.417a1.333,1.333,0,1,1,1.333-1.333A1.335,1.335,0,0,1,498.2,171.417Zm0-2.222a.889.889,0,1,0,.889.889A.89.89,0,0,0,498.2,169.194Z" transform="translate(-434.793 -114.402)" fill="#005699" stroke="#005699" stroke-width="0.5"/>
<path id="Path_267" data-name="Path 267" d="M709.143,171.417a1.333,1.333,0,1,1,1.333-1.333A1.335,1.335,0,0,1,709.143,171.417Zm0-2.222a.889.889,0,1,0,.889.889A.89.89,0,0,0,709.143,169.194Z" transform="translate(-640.733 -114.402)" fill="#005699" stroke="#005699" stroke-width="0.5"/>
<path id="Path_268" data-name="Path 268" d="M920.083,171.417a1.333,1.333,0,1,1,1.333-1.333A1.335,1.335,0,0,1,920.083,171.417Zm0-2.222a.889.889,0,1,0,.889.889A.89.89,0,0,0,920.083,169.194Z" transform="translate(-846.673 -114.402)" fill="#005699" stroke="#005699" stroke-width="0.5"/>
<path id="Path_269" data-name="Path 269" d="M826.331,853.344h-.015a.222.222,0,0,1-.17-.1l-1.111-1.667a.222.222,0,1,1,.37-.247l.95,1.425,3.7-4.226a.222.222,0,0,1,.335.293l-3.889,4.445a.223.223,0,0,1-.167.076Z" transform="translate(-755.142 -777.995)" fill="#005699" stroke="#005699" stroke-width="0.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,358 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 116.3 116.3" style="enable-background:new 0 0 116.3 116.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_2_);}
.st2{fill:url(#SVGID_3_);}
.st3{fill:url(#SVGID_4_);}
.st4{fill:url(#SVGID_5_);}
.st5{fill:url(#SVGID_6_);}
.st6{opacity:0.4;fill:url(#SVGID_7_);enable-background:new ;}
.st7{fill:url(#SVGID_8_);}
.st8{fill:url(#SVGID_9_);}
.st9{fill:url(#SVGID_10_);}
.st10{fill:url(#SVGID_11_);}
.st11{fill:url(#SVGID_12_);}
.st12{fill:url(#SVGID_13_);}
.st13{fill:url(#SVGID_14_);}
.st14{fill:url(#SVGID_15_);}
.st15{fill:url(#SVGID_16_);}
.st16{opacity:0.2;fill:url(#SVGID_17_);enable-background:new ;}
.st17{fill:url(#SVGID_18_);}
.st18{fill:url(#SVGID_19_);}
.st19{opacity:0.25;fill:url(#SVGID_20_);enable-background:new ;}
.st20{fill:url(#SVGID_21_);}
.st21{fill:url(#SVGID_22_);}
.st22{opacity:0.2;fill:url(#SVGID_23_);enable-background:new ;}
.st23{fill:url(#SVGID_24_);}
</style>
<g>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="69.0328" y1="454.9245" x2="64.4435" y2="449.5703" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2B3B6A"/>
<stop offset="1" style="stop-color:#2B3B6A"/>
</linearGradient>
<polygon class="st0" points="54.9,55.8 62,55.6 58.4,62.2 "/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="108.534" y1="457.2333" x2="108.534" y2="494.0327" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2B3B6A"/>
<stop offset="7.040000e-02" style="stop-color:#2D4576"/>
<stop offset="0.2165" style="stop-color:#2E5589"/>
<stop offset="0.3608" style="stop-color:#2B5E97"/>
<stop offset="0.5" style="stop-color:#29629C"/>
<stop offset="0.6392" style="stop-color:#2B5E97"/>
<stop offset="0.7835" style="stop-color:#2E5589"/>
<stop offset="0.9296" style="stop-color:#2D4576"/>
<stop offset="1" style="stop-color:#2B3B6A"/>
</linearGradient>
<path class="st1" d="M85.5,57.5c26.1,4.2,29.8,10.7,29.8,10.7c0,0.4,0,0.8,0,1.2c0,0.2-0.1,0.4-0.2,0.7c-0.1,0.3-2.7,5.7-19.6,9.3
L85.5,57.5z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="26.7686" y1="496.8278" x2="38.7091" y2="475.5678" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#252B59"/>
<stop offset="8.590000e-02" style="stop-color:#2B3A69"/>
<stop offset="0.2267" style="stop-color:#2E4A7C"/>
<stop offset="0.3658" style="stop-color:#2E5487"/>
<stop offset="0.5" style="stop-color:#2D578C"/>
<stop offset="0.6342" style="stop-color:#2E5487"/>
<stop offset="0.7733" style="stop-color:#2E4A7C"/>
<stop offset="0.9141" style="stop-color:#2B3A69"/>
<stop offset="1" style="stop-color:#252B59"/>
</linearGradient>
<path class="st2" d="M19.8,78.5c-5.9,15.7-2.9,20.6-2.7,21c0.1,0.2,0.2,0.4,0.4,0.5c0.4,0,0.8-0.1,1.2-0.2c0,0,10.7-0.5,23.2-18.3
L19.8,78.5z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="60.8512" y1="424.6486" x2="41.0872" y2="401.5905" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#181844"/>
<stop offset="2.840000e-02" style="stop-color:#1E1E4C"/>
<stop offset="0.1353" style="stop-color:#283261"/>
<stop offset="0.2468" style="stop-color:#2D4172"/>
<stop offset="0.3647" style="stop-color:#2E4A7C"/>
<stop offset="0.5" style="stop-color:#2E4D7F"/>
<stop offset="0.6177" style="stop-color:#2D4576"/>
<stop offset="0.8125" style="stop-color:#273160"/>
<stop offset="1" style="stop-color:#181844"/>
</linearGradient>
<path class="st3" d="M58.8,18.6C44.5,2.9,37.5,3.8,37.1,3.9c-0.2,0-0.5,0.1-0.7,0.2c-0.5,0.2-1,1.8-1,1.8s-3,8.7,9.1,31.9
L58.8,18.6z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="99.9721" y1="499.3526" x2="84.7036" y2="450.1664" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#181844"/>
<stop offset="2.840000e-02" style="stop-color:#1E1E4C"/>
<stop offset="0.1353" style="stop-color:#283261"/>
<stop offset="0.2468" style="stop-color:#2D4172"/>
<stop offset="0.3647" style="stop-color:#2E4A7C"/>
<stop offset="0.5" style="stop-color:#2E4D7F"/>
<stop offset="0.6177" style="stop-color:#2D4576"/>
<stop offset="0.8125" style="stop-color:#273160"/>
<stop offset="1" style="stop-color:#181844"/>
</linearGradient>
<path class="st4" d="M71.2,78.8C90.6,101,97.4,99.8,97.4,99.8c0.4,0.1,0.9,0.2,1.3,0.2c0.2-0.1,0.3-0.3,0.4-0.5
c0.3-0.4,5.8-9.4-12.8-41.8L71.2,78.8z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="31.6447" y1="457.2331" x2="31.6447" y2="494.0317" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2B3B6A"/>
<stop offset="7.040000e-02" style="stop-color:#2D4576"/>
<stop offset="0.2165" style="stop-color:#2E5589"/>
<stop offset="0.3608" style="stop-color:#2B5E97"/>
<stop offset="0.5" style="stop-color:#29629C"/>
<stop offset="0.6392" style="stop-color:#2B5E97"/>
<stop offset="0.7835" style="stop-color:#2E5589"/>
<stop offset="0.9296" style="stop-color:#2D4576"/>
<stop offset="1" style="stop-color:#2B3B6A"/>
</linearGradient>
<path class="st5" d="M46.1,82.2c-40-1.7-44.8-11.6-45-12.1C1.1,69.9,1,69.7,1,69.5c0.1-0.7,1.5-2,1.5-2s10.6-6.5,28.3-10
L46.1,82.2z"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="51.8906" y1="421.1236" x2="66.337" y2="421.1236" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2B3B6A"/>
<stop offset="1" style="stop-color:#2B3B6A"/>
</linearGradient>
<path class="st6" d="M57.6,17.4c-5,5.4-9.6,11.2-13.8,17.2h1c3.1-3.9,10.8-13.7,13.4-16.5L57.6,17.4z"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="70.9709" y1="436.4003" x2="70.9709" y2="401.6908" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#252B59"/>
<stop offset="0.5" style="stop-color:#2D578C"/>
<stop offset="0.6934" style="stop-color:#2D5588"/>
<stop offset="0.8038" style="stop-color:#2E4F80"/>
<stop offset="0.8932" style="stop-color:#2D4474"/>
<stop offset="0.971" style="stop-color:#283463"/>
<stop offset="1" style="stop-color:#252B59"/>
</linearGradient>
<path class="st7" d="M73.8,35.4C84.2,10.7,80.2,5,80.2,5c-0.1-0.3-0.2-0.7-0.3-1c-0.2-0.1-0.4-0.1-0.7-0.2
c-0.5-0.1-11.4-1.5-34.4,30.7L73.8,35.4z"/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="39.2669" y1="503.7654" x2="102.6764" y2="407.9172" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2867A2"/>
<stop offset="8.239999e-02" style="stop-color:#177EBC"/>
<stop offset="0.1675" style="stop-color:#0E91D1"/>
<stop offset="0.2527" style="stop-color:#10A2E1"/>
<stop offset="0.337" style="stop-color:#18ACEA"/>
<stop offset="0.42" style="stop-color:#24B1ED"/>
<stop offset="0.5" style="stop-color:#28B1ED"/>
<stop offset="0.58" style="stop-color:#24B1ED"/>
<stop offset="0.663" style="stop-color:#18ACEA"/>
<stop offset="0.7473" style="stop-color:#10A2E1"/>
<stop offset="0.8325" style="stop-color:#0E91D1"/>
<stop offset="0.9176" style="stop-color:#177EBC"/>
<stop offset="1" style="stop-color:#2867A2"/>
</linearGradient>
<path class="st8" d="M58,97.4c-14.2,15.4-21,14.5-21.4,14.5c-0.6-0.2-1.2-0.5-1.7-0.8l-17.3-11c7.3-1.6,16.3-10.2,25.7-21.3
L58,97.4z"/>
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="33.568" y1="505.6873" x2="58.683" y2="483.2007" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2C5D95"/>
<stop offset="8.220001e-02" style="stop-color:#246EAB"/>
<stop offset="0.1808" style="stop-color:#1B79B9"/>
<stop offset="0.3007" style="stop-color:#1080C2"/>
<stop offset="0.5" style="stop-color:#0E81C5"/>
<stop offset="0.6993" style="stop-color:#1080C2"/>
<stop offset="0.8192" style="stop-color:#1B79B9"/>
<stop offset="0.9178" style="stop-color:#246EAB"/>
<stop offset="1" style="stop-color:#2C5D95"/>
</linearGradient>
<path class="st9" d="M58.6,98c-14.2,15.4-21,14.5-21.4,14.5c-0.6-0.2-1.2-0.5-1.7-0.8L17.6,100c7.3-1.6,16.9-9.6,26.3-20.7
L58.6,98z"/>
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="31.3212" y1="407.2591" x2="89.6399" y2="504.4568" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2C5D95"/>
<stop offset="1.760000e-02" style="stop-color:#2A6199"/>
<stop offset="0.1407" style="stop-color:#1C79B7"/>
<stop offset="0.2631" style="stop-color:#0A8CCA"/>
<stop offset="0.3837" style="stop-color:#0B97D4"/>
<stop offset="0.5" style="stop-color:#0E9AD8"/>
<stop offset="0.6163" style="stop-color:#0B97D4"/>
<stop offset="0.7369" style="stop-color:#0A8CCA"/>
<stop offset="0.8593" style="stop-color:#1C79B7"/>
<stop offset="0.9824" style="stop-color:#2A6199"/>
<stop offset="1" style="stop-color:#2C5D95"/>
</linearGradient>
<path class="st10" d="M20.7,38c-6.3-16.2-3.2-21.3-3-21.6c0.4-0.5,0.9-0.9,1.4-1.2l17.3-11c-1.5,7.1,2.3,18,8.2,30.7L20.7,38z"/>
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="94.4028" y1="503.8655" x2="56.9038" y2="456.6339" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2C5D95"/>
<stop offset="2.570000e-02" style="stop-color:#2A6199"/>
<stop offset="0.2053" style="stop-color:#1C79B7"/>
<stop offset="0.384" style="stop-color:#0A8CCA"/>
<stop offset="0.5599" style="stop-color:#0B97D4"/>
<stop offset="0.7296" style="stop-color:#0E9AD8"/>
<stop offset="0.7925" style="stop-color:#0B97D4"/>
<stop offset="0.8577" style="stop-color:#0A8CCA"/>
<stop offset="0.9239" style="stop-color:#1C79B7"/>
<stop offset="0.9905" style="stop-color:#2A6199"/>
<stop offset="1" style="stop-color:#2C5D95"/>
</linearGradient>
<path class="st11" d="M57.2,57.2c-8.7,0-17.4,0.7-26,1.9c0.3,0.5,4.3,7.2,7.2,11.7c27.8,42.8,40.8,41.1,41.4,41
c0.6-0.2,1.2-0.5,1.7-0.8l17.3-11C87,97.5,70.6,78.2,57.2,57.2z"/>
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="40.2175" y1="431.0724" x2="32.9164" y2="404.7886" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2C5D95"/>
<stop offset="8.220001e-02" style="stop-color:#246EAB"/>
<stop offset="0.1808" style="stop-color:#1B79B9"/>
<stop offset="0.3007" style="stop-color:#1080C2"/>
<stop offset="0.5" style="stop-color:#0E81C5"/>
<stop offset="0.6993" style="stop-color:#1080C2"/>
<stop offset="0.8192" style="stop-color:#1B79B9"/>
<stop offset="0.9178" style="stop-color:#246EAB"/>
<stop offset="1" style="stop-color:#2C5D95"/>
</linearGradient>
<path class="st12" d="M20.1,38.5c-6.3-16.2-3.2-21.3-3-21.6c0.4-0.5,0.9-0.9,1.4-1.2L36.5,4.1c-1.5,7.1,1.7,18.6,7.6,31.2
L20.1,38.5z"/>
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="122.9025" y1="448.7971" x2="9.1479" y2="448.7971" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2867A2"/>
<stop offset="1.280000e-02" style="stop-color:#256BA7"/>
<stop offset="0.1121" style="stop-color:#0B83C3"/>
<stop offset="0.2115" style="stop-color:#1797D8"/>
<stop offset="0.3099" style="stop-color:#25A3E2"/>
<stop offset="0.4066" style="stop-color:#27ABE7"/>
<stop offset="0.5" style="stop-color:#2AAEEA"/>
<stop offset="0.5934" style="stop-color:#27ABE7"/>
<stop offset="0.6901" style="stop-color:#25A3E2"/>
<stop offset="0.7885" style="stop-color:#1797D8"/>
<stop offset="0.8879" style="stop-color:#0B83C3"/>
<stop offset="0.9872" style="stop-color:#256BA7"/>
<stop offset="1" style="stop-color:#2867A2"/>
</linearGradient>
<path class="st13" d="M85.5,59.6c13.5,1.9,24.7,4.7,29.8,9.8V48.9c0-0.6-0.1-1.3-0.2-1.9c-0.1-0.3-2.7-5.6-19-9.1L85.5,59.6z"/>
<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="90.2941" y1="447.1362" x2="122.8074" y2="448.8884" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2E5284"/>
<stop offset="6.100000e-03" style="stop-color:#2E5486"/>
<stop offset="9.120000e-02" style="stop-color:#29649D"/>
<stop offset="0.1876" style="stop-color:#236FAD"/>
<stop offset="0.3049" style="stop-color:#1D77B6"/>
<stop offset="0.5" style="stop-color:#1C78B9"/>
<stop offset="0.6951" style="stop-color:#1D77B6"/>
<stop offset="0.8124" style="stop-color:#236FAD"/>
<stop offset="0.9088" style="stop-color:#29649D"/>
<stop offset="0.9939" style="stop-color:#2E5486"/>
<stop offset="1" style="stop-color:#2E5284"/>
</linearGradient>
<path class="st14" d="M85.5,58.8c13.5,1.9,24.7,5.5,29.8,10.6V48.1c0-0.6-0.1-1.3-0.2-1.9c-0.1-0.3-2.7-5.6-19-9.1L85.5,58.8z"/>
<linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="9.0577" y1="447.1912" x2="67.7186" y2="447.1912" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2867A2"/>
<stop offset="2.250000e-02" style="stop-color:#256BA7"/>
<stop offset="0.1971" style="stop-color:#0B83C3"/>
<stop offset="0.3718" style="stop-color:#1797D8"/>
<stop offset="0.5447" style="stop-color:#25A3E2"/>
<stop offset="0.7147" style="stop-color:#27ABE7"/>
<stop offset="0.8788" style="stop-color:#2AAEEA"/>
<stop offset="0.9015" style="stop-color:#27ABE7"/>
<stop offset="0.9249" style="stop-color:#25A3E2"/>
<stop offset="0.9487" style="stop-color:#1797D8"/>
<stop offset="0.9728" style="stop-color:#0B83C3"/>
<stop offset="0.9969" style="stop-color:#256BA7"/>
<stop offset="1" style="stop-color:#2867A2"/>
</linearGradient>
<path class="st15" d="M73.2,35.1c-3-0.1-9.5-0.4-15.1-0.4C7.1,34.7,1.4,46.5,1.2,47C1,47.6,1,48.3,1,48.9v20.6
c5-5,15.9-7.7,29.2-9.7c8.6-1.2,17.2-1.9,25.9-2c1.6,0,3.2,0,4.8,0C60.8,57.8,76.3,35.2,73.2,35.1z"/>
<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="50.3126" y1="432.0108" x2="28.2664" y2="428.9106" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2B3B6A"/>
<stop offset="1" style="stop-color:#2B3B6A"/>
</linearGradient>
<path class="st16" d="M44.1,33.5c-10.7,0.5-18.4,1.3-24.8,3.1l0.3,0.8c0.6-0.1,1.3-0.3,1.9-0.4c7.7-1.2,15.4-2,23.1-2.3L44.1,33.5
z"/>
<linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="72.7451" y1="450.8669" x2="10.4435" y2="442.1056" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2867A2"/>
<stop offset="3.820000e-02" style="stop-color:#2174B1"/>
<stop offset="0.1177" style="stop-color:#0B86C4"/>
<stop offset="0.2081" style="stop-color:#0A94D2"/>
<stop offset="0.3177" style="stop-color:#0C9BDB"/>
<stop offset="0.5" style="stop-color:#109EDE"/>
<stop offset="0.6823" style="stop-color:#0C9BDB"/>
<stop offset="0.7919" style="stop-color:#0A94D2"/>
<stop offset="0.8823" style="stop-color:#0B86C4"/>
<stop offset="0.9618" style="stop-color:#2174B1"/>
<stop offset="1" style="stop-color:#2867A2"/>
</linearGradient>
<path class="st17" d="M73.2,34.3c-3-0.1-9.5-0.4-15.1-0.4c-51.1,0-56.7,11.8-57,12.4C1,46.8,1,47.5,1,48.1v21.4
c5-5,15.9-8.5,29.2-10.5c8.6-1.2,17.2-1.9,25.9-2c1.6,0,3.2,0,4.8,0C63.2,57.1,76.3,34.4,73.2,34.3z"/>
<linearGradient id="SVGID_19_" gradientUnits="userSpaceOnUse" x1="101.6202" y1="407.733" x2="71.9933" y2="458.7571" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2867A2"/>
<stop offset="0.1238" style="stop-color:#177EBC"/>
<stop offset="0.2516" style="stop-color:#0E91D1"/>
<stop offset="0.3797" style="stop-color:#10A2E1"/>
<stop offset="0.5064" style="stop-color:#18ACEA"/>
<stop offset="0.631" style="stop-color:#24B1ED"/>
<stop offset="0.7513" style="stop-color:#28B1ED"/>
<stop offset="0.7911" style="stop-color:#24B1ED"/>
<stop offset="0.8324" style="stop-color:#18ACEA"/>
<stop offset="0.8743" style="stop-color:#10A2E1"/>
<stop offset="0.9167" style="stop-color:#0E91D1"/>
<stop offset="0.959" style="stop-color:#177EBC"/>
<stop offset="1" style="stop-color:#2867A2"/>
</linearGradient>
<path class="st18" d="M58.2,58.8C72.1,37.9,82.4,16,79.8,4.1l17.3,11c0.5,0.3,1,0.7,1.4,1.2c0.3,0.5,7.1,11.7-20.7,54.5
c-2,3.2-3.9,6.9-4.6,7.2c-4.1-4-12.6-15.6-14.7-18.5C58.3,59.1,58.2,58.8,58.2,58.8z"/>
<linearGradient id="SVGID_20_" gradientUnits="userSpaceOnUse" x1="105.3445" y1="433.3988" x2="94.5575" y2="453.6416" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2B3B6A"/>
<stop offset="1" style="stop-color:#2B3B6A"/>
</linearGradient>
<path class="st19" d="M96.6,37.2c-3.1,7.8-6.8,15.3-11.1,22.4l1.3,0.2c5.5-9.5,8.7-16.5,10.9-22.4L96.6,37.2z"/>
<linearGradient id="SVGID_21_" gradientUnits="userSpaceOnUse" x1="100.6479" y1="408.8533" x2="70.927" y2="464.6275" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2867A2"/>
<stop offset="3.820000e-02" style="stop-color:#2174B1"/>
<stop offset="0.1177" style="stop-color:#0B86C4"/>
<stop offset="0.2081" style="stop-color:#0A94D2"/>
<stop offset="0.3177" style="stop-color:#0C9BDB"/>
<stop offset="0.5" style="stop-color:#109EDE"/>
<stop offset="0.6823" style="stop-color:#0C9BDB"/>
<stop offset="0.7919" style="stop-color:#0A94D2"/>
<stop offset="0.8823" style="stop-color:#0B86C4"/>
<stop offset="0.9618" style="stop-color:#2174B1"/>
<stop offset="1" style="stop-color:#2867A2"/>
</linearGradient>
<path class="st20" d="M78.5,71.4c27.8-42.8,21-54,20.7-54.5c-0.4-0.5-0.9-0.9-1.4-1.2L79.8,4.1c2.5,11.8-7.4,34.6-21.2,55.5
c4.6,7.1,9.4,14,14.5,19.9C74.1,78.3,76.7,74.3,78.5,71.4z"/>
<linearGradient id="SVGID_22_" gradientUnits="userSpaceOnUse" x1="102.9539" y1="410.1097" x2="72.9714" y2="466.375" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2867A2"/>
<stop offset="3.820000e-02" style="stop-color:#2174B1"/>
<stop offset="0.1177" style="stop-color:#0B86C4"/>
<stop offset="0.2081" style="stop-color:#0A94D2"/>
<stop offset="0.3177" style="stop-color:#0C9BDB"/>
<stop offset="0.5" style="stop-color:#109EDE"/>
<stop offset="0.6823" style="stop-color:#0C9BDB"/>
<stop offset="0.7919" style="stop-color:#0A94D2"/>
<stop offset="0.8823" style="stop-color:#0B86C4"/>
<stop offset="0.9618" style="stop-color:#2174B1"/>
<stop offset="1" style="stop-color:#2867A2"/>
</linearGradient>
<path class="st21" d="M72.6,80.2c0.1-0.1,0.2-0.1,0.2-0.2c-5.3-6.2-10.2-12.8-14.7-19.7c-0.1,0.1-0.2,0.2-0.2,0.4
C57.9,60.6,67.6,75.9,72.6,80.2z"/>
<linearGradient id="SVGID_23_" gradientUnits="userSpaceOnUse" x1="54.5637" y1="474.0854" x2="62.254" y2="494.9197" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2B3B6A"/>
<stop offset="1" style="stop-color:#2B3B6A"/>
</linearGradient>
<path class="st22" d="M58.2,98.4C57.9,98.1,47.7,86.1,43.1,79l-0.8,0.9C46.9,86.6,52,93,57.6,99L58.2,98.4z"/>
<linearGradient id="SVGID_24_" gradientUnits="userSpaceOnUse" x1="69.1674" y1="452.6575" x2="78.2209" y2="509.0225" gradientTransform="matrix(1 0 0 1 -8.0854 -395.1333)">
<stop offset="0" style="stop-color:#2E5284"/>
<stop offset="2.440000e-02" style="stop-color:#2C5C92"/>
<stop offset="8.880000e-02" style="stop-color:#2075B1"/>
<stop offset="0.1599" style="stop-color:#0B86C4"/>
<stop offset="0.2403" style="stop-color:#0A94D2"/>
<stop offset="0.3378" style="stop-color:#0E9CDA"/>
<stop offset="0.5" style="stop-color:#109EDE"/>
<stop offset="0.6718" style="stop-color:#0C9BDB"/>
<stop offset="0.7751" style="stop-color:#0A94D2"/>
<stop offset="0.8603" style="stop-color:#0B86C4"/>
<stop offset="0.9351" style="stop-color:#2174B1"/>
<stop offset="1" style="stop-color:#2C5D95"/>
</linearGradient>
<path class="st23" d="M72.9,79.9c-5.3-6.2-10.2-12.8-14.7-19.7c-0.5-0.8-1.1-1.6-1.6-2.4c-8.7,0-17.4,0.7-26,1.9
c0.3,0.5,4.3,7.2,7.2,11.7c27.8,42.8,40.8,41.1,41.4,41c0.6-0.2,1.2-0.5,1.7-0.8L98.8,100C91.4,98.4,82.1,90.6,72.9,79.9z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="24" viewBox="0 0 30 24"><defs><style>.a{fill:#005699;}.b,.d{fill:none;}.b{stroke:#005699;stroke-width:1.5px;}.c{stroke:none;}</style></defs><g transform="translate(7.328 6.159)"><g transform="translate(0 0)"><path class="a" d="M-2124.191-3452.351h.007a1.335,1.335,0,0,0,.972-.341,1.106,1.106,0,0,0,.351-.847.958.958,0,0,0-.34-.76,1.407,1.407,0,0,0-.983-.337h-.012a1.365,1.365,0,0,0-.977.342,1.1,1.1,0,0,0-.053,1.549l.055.056a1.364,1.364,0,0,0,.973.341Z" transform="translate(2125.521 3454.638)"/></g><g transform="translate(0.358 0.062)"><path class="a" d="M-2123.846-3442.183h9.042a8,8,0,0,0,3.567-.767,5.651,5.651,0,0,0,2.353-2.118,6.555,6.555,0,0,0,0-6.4,5.651,5.651,0,0,0-2.351-2.114,7.975,7.975,0,0,0-3.562-.766h-3.427v8.653h2.057v-7.142h1.216a4.586,4.586,0,0,1,4.953,4.187,4.586,4.586,0,0,1-4.187,4.954,4.585,4.585,0,0,1-.772,0h-6.942v-6.035h-1.946v6.035h0Z" transform="translate(2123.846 3454.35)"/></g></g><g class="b"><path class="c" d="M5,0H25a5,5,0,0,1,5,5V24a0,0,0,0,1,0,0H5a5,5,0,0,1-5-5V5A5,5,0,0,1,5,0Z"/><path class="d" d="M5,.75H25A4.25,4.25,0,0,1,29.25,5V22.5a.75.75,0,0,1-.75.75H5A4.25,4.25,0,0,1,.75,19V5A4.25,4.25,0,0,1,5,.75Z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,13 @@
<?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-add-929469" transform="translate(-102.6 -102.6)">
<path id="Path_270" d="M107.5,107.5c-3.9,3.9-3.9,10.2,0,14.1c3.9,3.9,10.2,3.9,14.1,0c3.9-3.9,3.9-10.2,0-14.1
C117.8,103.6,111.4,103.6,107.5,107.5C107.5,107.5,107.5,107.5,107.5,107.5z M120.5,120.5c-3.3,3.3-8.5,3.3-11.8,0
c-3.3-3.3-3.3-8.5,0-11.8c3.3-3.3,8.5-3.3,11.8,0C123.7,112,123.7,117.2,120.5,120.5z"/>
<path id="Path_271" d="M114.6,109.8c-0.4,0-0.8,0.4-0.8,0.8c0,0,0,0,0,0v3.1h-3.1c-0.5,0-0.8,0.4-0.8,0.8c0,0.5,0.4,0.8,0.8,0.8
h3.1v3.1c0,0.4,0.4,0.8,0.8,0.8c0,0,0,0,0,0c0.5,0,0.8-0.4,0.8-0.8v-3.1h3.1c0.5,0,0.8-0.4,0.8-0.8c0-0.4-0.4-0.8-0.8-0.8
c0,0,0,0,0,0h-3.1v-3.1C115.4,110.2,115.1,109.8,114.6,109.8C114.6,109.8,114.6,109.8,114.6,109.8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,41 @@
<?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 428 428" style="enable-background:new 0 0 428 428;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:url(#SVGID_1_);}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:url(#SVGID_2_);}
.st2{fill:url(#SVGID_3_);}
.st3{fill:url(#SVGID_4_);}
</style>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-12.625" y1="262.475" x2="165.425" y2="84.425" gradientTransform="matrix(1 0 0 -1 0 428)">
<stop offset="0" style="stop-color:#7E7E7E"/>
<stop offset="1" style="stop-color:#E9FFFF"/>
</linearGradient>
<path class="st0" d="M1.6,154v21.5v1.4c0.2,0,0.4,0,0.6,0c21.8,0,39.5,17.7,39.5,39.5S24,255.9,2.2,255.9c-0.2,0-0.4,0-0.6,0V408
H101V152c0.2,0.1,0.3,0.1,0.5,0.2V51.4L1.6,154z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="227.375" y1="343.175" x2="405.475" y2="165.075" gradientTransform="matrix(1 0 0 -1 0 428)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.3476" style="stop-color:#9B9B9B"/>
<stop offset="0.525" style="stop-color:#A1A3A3"/>
<stop offset="0.6639" style="stop-color:#ABB0B0"/>
<stop offset="0.7828" style="stop-color:#BAC3C3"/>
<stop offset="0.8889" style="stop-color:#CDDCDC"/>
<stop offset="0.9845" style="stop-color:#E5F9F9"/>
<stop offset="1" style="stop-color:#E9FFFF"/>
</linearGradient>
<path class="st1" d="M386.9,176.8L386.9,176.8V19h-93.7v256c-0.1-0.1-0.3-0.1-0.4-0.2v100.8l94.2-96.7v-23.2l0,0
c21.8,0,39.5-17.7,39.5-39.5C426.4,194.5,408.7,176.8,386.9,176.8z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="1.6" y1="341.5" x2="395.2748" y2="341.5" gradientTransform="matrix(1 0 0 -1 0 428)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.9889" style="stop-color:#E9FFFF"/>
</linearGradient>
<path class="st2" d="M181.3,19C126.4,19,1.6,31.5,1.6,154c0,0,49.3-42.7,136.9-25s160.9-0.7,207.6-49.1
c18.6-19.3,32.4-39.6,40.2-60.9H181.3z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-723.2346" y1="1360.2583" x2="-329.5598" y2="1360.2583" gradientTransform="matrix(-1 0 0 1 -336.3346 -1016.8083)">
<stop offset="0" style="stop-color:#E9FFFF"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path class="st3" d="M207.2,408c54.9,0,179.7-11.9,179.7-129.1c0,0-49.3,40.8-136.9,23.9s-160.9,0.7-207.6,47
C23.8,368.3,10.1,387.6,2.2,408H207.2z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

View File

@ -35,9 +35,6 @@ BaseView {
property bool successState: true
// signal to redirect the page to main view
signal loaderSourceChangeRequested(int sourceToLoad)
function slotMigrationButtonClicked() {
stackedWidget.currentIndex = AccountMigrationView.AccountMigrationStep.Synching;
AccountAdapter.setArchivePasswordAsync(CurrentAccountToMigrate.accountId, passwordInputLineEdit.text);

View File

@ -43,7 +43,6 @@ ApplicationWindow {
LayoutMirroring.childrenInherit: isRTL
enum LoadedSource {
WizardView,
MainView,
AccountMigrationView,
None
@ -66,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 {
id: focusOverlay
objectName: "focusOverlay"
@ -95,19 +103,13 @@ ApplicationWindow {
function checkLoadedSource() {
var sourceString = mainApplicationLoader.source.toString();
if (sourceString === JamiQmlUtils.wizardViewLoadPath)
return MainApplicationWindow.LoadedSource.WizardView;
else if (sourceString === JamiQmlUtils.mainViewLoadPath)
if (sourceString === JamiQmlUtils.mainViewLoadPath)
return MainApplicationWindow.LoadedSource.MainView;
return MainApplicationWindow.LoadedSource.None;
}
function startClient() {
if (UtilsAdapter.getAccountListSize() !== 0) {
setMainLoaderSource(JamiQmlUtils.mainViewLoadPath);
} else {
setMainLoaderSource(JamiQmlUtils.wizardViewLoadPath);
}
setMainLoaderSource(JamiQmlUtils.mainViewLoadPath);
}
function setMainLoaderSource(source) {
@ -129,9 +131,6 @@ ApplicationWindow {
// If we're in the onboarding wizard or 'MinimizeOnClose'
// is set, then we can quit
if (force || !UtilsAdapter.getAppValue(Settings.MinimizeOnClose) || !UtilsAdapter.getAccountListSize()) {
if (checkLoadedSource() === MainApplicationWindow.LoadedSource.MainView) {
cleanupMainView();
}
Qt.quit();
} else {
layoutManager.closeToTray();
@ -159,14 +158,6 @@ ApplicationWindow {
asynchronous: true
visible: status == Loader.Ready
Connections {
target: viewCoordinator
function onRequestAppWindowWizardView() {
setMainLoaderSource(JamiQmlUtils.wizardViewLoadPath);
}
}
Connections {
id: connectionMigrationEnded
@ -182,32 +173,16 @@ ApplicationWindow {
}
}
Connections {
target: mainApplicationLoader.item
function onLoaderSourceChangeRequested(sourceToLoad) {
if (sourceToLoad === MainApplicationWindow.LoadedSource.WizardView)
setMainLoaderSource(JamiQmlUtils.wizardViewLoadPath);
else if (sourceToLoad === MainApplicationWindow.LoadedSource.AccountMigrationView)
setMainLoaderSource(JamiQmlUtils.accountMigrationViewLoadPath);
else
setMainLoaderSource(JamiQmlUtils.mainViewLoadPath);
}
}
// Set `visible = false` when loading a new QML file.
onSourceChanged: windowSettingsLoaded = false
onLoaded: {
if (checkLoadedSource() === MainApplicationWindow.LoadedSource.WizardView) {
// Onboarding wizard window, these settings are fixed.
// - window screen will default to the primary
// - the window will showNormal once windowSettingsLoaded is
// set to true(then forcing visible to true)
appWindow.width = JamiTheme.wizardViewMinWidth;
appWindow.height = JamiTheme.wizardViewMinHeight;
appWindow.minimumWidth = JamiTheme.wizardViewMinWidth;
appWindow.minimumHeight = JamiTheme.wizardViewMinHeight;
if (UtilsAdapter.getAccountListSize() === 0) {
layoutManager.restoreWindowSettings();
if (!viewCoordinator.rootView)
// Set the viewCoordinator's root item.
viewCoordinator.init(item);
viewCoordinator.present("WizardView");
} else {
// Main window, load any valid app settings, and allow the
// layoutManager to handle as much as possible.
@ -220,8 +195,9 @@ ApplicationWindow {
viewCoordinator.present("WelcomePage");
viewCoordinator.preload("ConversationView");
});
// Set the viewCoordinator's root item.
viewCoordinator.init(item);
if (!viewCoordinator.rootView)
// Set the viewCoordinator's root item.
viewCoordinator.init(item);
if (CurrentAccountToMigrate.accountToMigrateListSize > 0)
viewCoordinator.present("AccountMigrationView");
}
@ -233,10 +209,10 @@ ApplicationWindow {
windowSettingsLoaded = true;
// Quiet check for updates on start if set to.
if (Qt.platform.os.toString() !== "osx") {
if (Qt.platform.os.toString() === "windows") {
if (UtilsAdapter.getAppValue(Settings.AutoUpdate)) {
UpdateManager.checkForUpdates(true);
UpdateManager.setAutoUpdateCheck(true);
AppVersionManager.checkForUpdates(true);
AppVersionManager.setAutoUpdateCheck(true);
}
}
@ -263,6 +239,10 @@ ApplicationWindow {
Connections {
target: MainApplication
function onAboutToQuit() {
cleanupMainView()
}
function onCloseRequested() {
close(true);
}
@ -288,7 +268,7 @@ ApplicationWindow {
}
function presentUpdateInfoDialog(infoText) {
viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
return viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
"title": JamiStrings.updateDialogTitle,
"infoText": infoText,
"buttonTitles": [JamiStrings.optionOk],
@ -297,10 +277,40 @@ ApplicationWindow {
});
}
Connections {
target: UpdateManager
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 onUpdateDownloadStarted() {
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 {
target: AppVersionManager
function onDownloadStarted() {
viewCoordinator.presentDialog(appWindow, "settingsview/components/UpdateDownloadDialog.qml", {
"title": JamiStrings.updateDialogTitle
});
@ -308,41 +318,26 @@ ApplicationWindow {
function onUpdateCheckReplyReceived(ok, found) {
if (!ok) {
// Show an error dialog describing that we could not successfully check for an update.
presentUpdateInfoDialog(JamiStrings.updateCheckError);
return;
}
if (!found) {
// Show a dialog describing that no update was found.
presentUpdateInfoDialog(JamiStrings.updateNotFound);
} else {
viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
"title": JamiStrings.updateDialogTitle,
"infoText": JamiStrings.updateFound,
"buttonTitles": [JamiStrings.optionUpgrade, JamiStrings.optionLater],
"buttonStyles": [SimpleMessageDialog.ButtonStyle.TintedBlue, SimpleMessageDialog.ButtonStyle.TintedBlue],
"buttonCallBacks": [function () {
UpdateManager.applyUpdates();
}]
});
// Show a dialog describing that an update were found, and offering to install it.
presentUpdateConfirmInstallDialog()
}
}
function onUpdateErrorOccurred(error) {
presentUpdateInfoDialog((function () {
switch (error) {
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 {};
}
})());
function onNetworkErrorOccurred(error) {
var errorStr = translateErrorToString(error);
presentUpdateInfoDialog(errorStr);
}
function onInstallErrorOccurred(errorMsg) {
presentUpdateInfoDialog(errorMsg);
}
}

View File

@ -27,7 +27,10 @@ QtObject {
required property QtObject viewManager
signal initialized
signal requestAppWindowWizardView
function requestAppWindowWizardView() {
viewCoordinator.present("WizardView");
}
// A map of view names to file paths for QML files that define each view.
property variant resources: {
@ -71,7 +74,7 @@ QtObject {
// Create, present, and return a dialog object.
function presentDialog(parent, path, props = {}) {
// 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 () {
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 = {}) {
if (views.hasOwnProperty(path)) {
// an instance of <path> already exists
const component = Qt.createComponent(Qt.resolvedUrl(path));
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) {
cb(views[path])
cb(views[viewName])
}
return views[path]
return views[viewName]
}
const component = Qt.createComponent(Qt.resolvedUrl(path))
if (component.status === Component.Ready) {
const obj = component.createObject(parent, props)
if (obj === null) {
print("error creating object")
console.error("error creating object")
return null
}
views[path] = obj
views[viewName] = obj
// Set the view name to the object name if it has one.
const viewName = obj.objectName.toString() !== '' ? obj.objectName : path.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "")
viewPaths[viewName] = path
const friendlyName = obj.objectName.toString() !== '' ?
obj.objectName :
viewName.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "")
viewPaths[friendlyName] = viewName
if (cb !== null) {
cb(obj)
}
return views[path]
return views[viewName]
}
print("error creating component", path)
console.error("error creating component", component.url)
console.error(component.errorString())
Qt.exit(1)
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) {
// The view may already have been destroyed.
if (!views.hasOwnProperty(path)) {

View File

@ -34,10 +34,12 @@ AccountAdapter::AccountAdapter(AppSettingsManager* settingsManager,
, settingsManager_(settingsManager)
, systemTray_(systemTray)
, accountListModel_(new AccountListModel(instance))
, deviceItemListModel_(new DeviceItemListModel(instance))
, deviceItemListModel_(new DeviceItemListModel(instance, parent))
, moderatorListModel_(new ModeratorListModel(instance, parent))
{
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, accountListModel_.get(), "AccountListModel");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, deviceItemListModel_.get(), "DeviceItemListModel");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, moderatorListModel_.get(), "ModeratorListModel");
connect(&lrcInstance_->accountModel(),
&AccountModel::accountStatusChanged,

View File

@ -22,6 +22,7 @@
#include "accountlistmodel.h"
#include "deviceitemlistmodel.h"
#include "moderatorlistmodel.h"
#include "systemtray.h"
#include "lrcinstance.h"
#include "utils.h"
@ -102,5 +103,6 @@ private:
QScopedPointer<AccountListModel> accountListModel_;
QScopedPointer<DeviceItemListModel> deviceItemListModel_;
QScopedPointer<ModeratorListModel> moderatorListModel_;
};
Q_DECLARE_METATYPE(AccountAdapter*)

View File

@ -34,7 +34,7 @@ extern const QString defaultDownloadPath;
// clang-format off
#define KEYS \
X(MinimizeOnClose, true) \
X(MinimizeOnClose, false) \
X(DownloadPath, defaultDownloadPath) \
X(ScreenshotPath, {}) \
X(EnableNotifications, true) \
@ -46,9 +46,10 @@ extern const QString defaultDownloadPath;
X(AppTheme, "System") \
X(BaseZoom, 1.0) \
X(ParticipantsSide, false) \
X(HideSelf, false) \
X(HideSelf, true) \
X(HideSpectators, false) \
X(AutoUpdate, true) \
X(PluginAutoUpdate, false) \
X(StartMinimized, false) \
X(ShowChatviewHorizontally, true) \
X(NeverShowMeAgain, false) \
@ -56,12 +57,14 @@ extern const QString defaultDownloadPath;
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(ShowSendOption, false)
X(ChatViewEnterIsNewLine, false) \
X(ShowSendOption, false) \
X(DonateVisibleDate, "2999-02-01 05:00")
/*
* A class to expose settings keys in both c++ and QML.
* Note: this is using a non-constructable class instead of a

View File

@ -0,0 +1,243 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "appversionmanager.h"
#include "lrcinstance.h"
#include "version.h"
#include <QProcess>
#include <QTimer>
#include <QDir>
#ifdef BETA
static constexpr bool isBeta = true;
#else
static constexpr bool isBeta = false;
#endif
static constexpr int updatePeriod = 1000 * 60 * 60 * 24; // one day in millis
static constexpr char downloadUrl[] = "https://dl.jami.net/windows";
static constexpr char versionSubUrl[] = "/version";
static constexpr char betaVersionSubUrl[] = "/beta/version";
static constexpr char msiSubUrl[] = "/jami.release.x64.msi";
static constexpr char betaMsiSubUrl[] = "/beta/jami.beta.x64.msi";
struct AppVersionManager::Impl : public QObject
{
Impl(const QString& url, LRCInstance* instance, AppVersionManager& parent)
: QObject(nullptr)
, parent_(parent)
, lrcInstance_(instance)
, baseUrlString_(url.isEmpty() ? downloadUrl : url)
, tempPath_(QDir::tempPath())
, updateTimer_(new QTimer(this))
{
connect(updateTimer_, &QTimer::timeout, this, [this] {
// Quiet period update check.
parent_.checkForUpdates(true);
});
};
~Impl() = default;
void checkForUpdates(bool quiet)
{
parent_.disconnect();
// Fail without UI if this is a programmatic check.
if (!quiet)
connect(&parent_,
&NetworkManager::errorOccurred,
&parent_,
&AppVersionManager::networkErrorOccurred);
cleanUpdateFiles();
const QUrl versionUrl {isBeta ? QUrl::fromUserInput(baseUrlString_ + betaVersionSubUrl)
: QUrl::fromUserInput(baseUrlString_ + versionSubUrl)};
parent_.sendGetRequest(versionUrl, [this, quiet](const QByteArray& latestVersionString) {
if (latestVersionString.isEmpty()) {
qWarning() << "Error checking version";
if (!quiet)
Q_EMIT parent_.updateCheckReplyReceived(false);
return;
}
auto currentVersion = QString(VERSION_STRING).toULongLong();
auto latestVersion = latestVersionString.toULongLong();
const QString channelStr = isBeta ? "beta" : "stable";
const auto newVersionFound = latestVersion > currentVersion;
qInfo().noquote() << "--------- Version info ------------"
<< QString("\n - Current: %1 (%2)").arg(currentVersion).arg(channelStr);
if (newVersionFound) {
qDebug() << " - Latest: " << latestVersion;
Q_EMIT parent_.updateCheckReplyReceived(true, true);
} else if (!quiet) {
Q_EMIT parent_.updateCheckReplyReceived(true, false);
}
});
};
void applyUpdates(bool beta = false)
{
parent_.disconnect();
connect(&parent_,
&NetworkManager::errorOccurred,
&parent_,
&AppVersionManager::networkErrorOccurred);
const QUrl downloadUrl {(beta || isBeta)
? QUrl::fromUserInput(baseUrlString_ + betaMsiSubUrl)
: QUrl::fromUserInput(baseUrlString_ + msiSubUrl)};
const auto lastDownloadReplyId = parent_.replyId_;
parent_.replyId_ = parent_.downloadFile(
downloadUrl,
lastDownloadReplyId,
[this, downloadUrl](bool success, const QString& errorMessage) {
Q_UNUSED(success)
Q_UNUSED(errorMessage)
QProcess process;
auto basePath = tempPath_ + QDir::separator();
auto msiPath = QDir::toNativeSeparators(basePath + downloadUrl.fileName());
auto logPath = QDir::toNativeSeparators(basePath + "jami_x64_install.log");
connect(&process, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) {
QString errorMsg;
if (error == QProcess::ProcessError::Timedout) {
errorMsg = tr("The installer process has timed out.");
} else {
errorMsg = process.readAllStandardError();
if (errorMsg.isEmpty())
errorMsg = tr("The installer process has failed.");
}
Q_EMIT parent_.installErrorOccurred(errorMsg);
});
connect(&process,
&QProcess::finished,
this,
[&](int exitCode, QProcess::ExitStatus exitStatus) {
if (exitStatus != QProcess::ExitStatus::NormalExit || exitCode != 0) {
auto errorMsg = process.readAllStandardOutput();
Q_EMIT parent_.installErrorOccurred(errorMsg);
}
});
process.start("msiexec",
QStringList() << "/i" << msiPath << "/passive"
<< "/norestart"
<< "WIXNONUILAUNCH=1"
<< "/L*V" << logPath);
process.waitForFinished();
},
tempPath_);
};
void cancelUpdate()
{
parent_.cancelDownload(parent_.replyId_);
};
void setAutoUpdateCheck(bool state)
{
// Quiet check for updates periodically, if set to.
if (!state) {
updateTimer_->stop();
return;
}
updateTimer_->start(updatePeriod);
};
void cleanUpdateFiles()
{
// Delete all logs and msi in the temporary directory before launching.
const QString dir = QDir::tempPath();
QDir log_dir(dir, {"jami*.log"});
for (const QString& filename : log_dir.entryList()) {
log_dir.remove(filename);
}
QDir msi_dir(dir, {"jami*.msi"});
for (const QString& filename : msi_dir.entryList()) {
msi_dir.remove(filename);
}
QDir version_dir(dir, {"version"});
for (const QString& filename : version_dir.entryList()) {
version_dir.remove(filename);
}
};
AppVersionManager& parent_;
LRCInstance* lrcInstance_ {nullptr};
QString baseUrlString_;
QString tempPath_;
QTimer* updateTimer_;
};
AppVersionManager::AppVersionManager(const QString& url,
ConnectivityMonitor* cm,
LRCInstance* instance,
QObject* parent)
: NetworkManager(cm, parent)
, replyId_(0)
, pimpl_(std::make_unique<Impl>(url, instance, *this))
{}
AppVersionManager::~AppVersionManager()
{
cancelDownload(replyId_);
}
void
AppVersionManager::checkForUpdates(bool quiet)
{
pimpl_->checkForUpdates(quiet);
}
void
AppVersionManager::applyUpdates(bool beta)
{
pimpl_->applyUpdates(beta);
}
void
AppVersionManager::cancelUpdate()
{
pimpl_->cancelUpdate();
}
void
AppVersionManager::setAutoUpdateCheck(bool state)
{
pimpl_->setAutoUpdateCheck(state);
}
bool
AppVersionManager::isCurrentVersionBeta()
{
return isBeta;
}
bool
AppVersionManager::isUpdaterEnabled()
{
#ifdef Q_OS_WIN
return true;
#endif
return false;
}
bool
AppVersionManager::isAutoUpdaterEnabled()
{
return false;
}

View File

@ -1,6 +1,5 @@
/*
* Copyright (C) 2020-2023 Savoir-faire Linux Inc.
* Author: Andreas Traczyk <andreas.traczyk@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
@ -25,51 +24,36 @@
class LRCInstance;
class ConnectivityMonitor;
class UpdateManager final : public NetworkManager
class AppVersionManager final : public NetworkManager
{
Q_OBJECT
Q_DISABLE_COPY(UpdateManager)
Q_DISABLE_COPY(AppVersionManager)
public:
explicit UpdateManager(const QString& url,
ConnectivityMonitor* cm,
LRCInstance* instance = nullptr,
QObject* parent = nullptr);
~UpdateManager();
enum GetStatus { STARTED, FINISHED };
Q_ENUM(GetStatus)
explicit AppVersionManager(const QString& url,
ConnectivityMonitor* cm,
LRCInstance* instance = nullptr,
QObject* parent = nullptr);
~AppVersionManager();
Q_INVOKABLE void checkForUpdates(bool quiet = false);
Q_INVOKABLE void applyUpdates(bool beta = false);
Q_INVOKABLE void cancelUpdate();
Q_INVOKABLE void setAutoUpdateCheck(bool state);
Q_INVOKABLE bool isCurrentVersionBeta();
Q_INVOKABLE bool isUpdaterEnabled();
Q_INVOKABLE bool isAutoUpdaterEnabled();
Q_INVOKABLE void cancelDownload();
void downloadFile(const QUrl& url,
std::function<void(bool, const QString&)> onDoneCallback,
const QString& filePath);
Q_INVOKABLE void setAutoUpdateCheck(bool state);
Q_INVOKABLE void cancelUpdate();
Q_INVOKABLE bool isCurrentVersionBeta();
Q_SIGNALS:
void statusChanged(GetStatus status);
void downloadProgressChanged(qint64 bytesRead, qint64 totalBytes);
void updateCheckReplyReceived(bool ok, bool found = false);
void updateErrorOccurred(const NetworkManager::GetError& error);
void updateDownloadStarted();
void updateDownloadProgressChanged(qint64 bytesRead, qint64 totalBytes);
void updateDownloadFinished();
void appCloseRequested();
void updateCheckReplyReceived(bool ok, bool found = false);
void updateDownloadProgressChanged(qint64 bytesRead, qint64 totalBytes);
void networkErrorOccurred(const NetworkManager::GetError& error);
void installErrorOccurred(const QString& errorMsg);
private:
void resetDownload();
QNetworkReply* downloadReply_ {nullptr};
QScopedPointer<QFile> file_;
private:
int replyId_;
struct Impl;
friend struct Impl;
std::unique_ptr<Impl> pimpl_;
};
Q_DECLARE_METATYPE(UpdateManager*)
Q_DECLARE_METATYPE(AppVersionManager*)

View File

@ -53,21 +53,21 @@ public:
return {};
}
auto imageId = idInfo.at(1);
const auto& imageId = idInfo.at(1);
if (!imageId.size()) {
qWarning() << Q_FUNC_INFO << "Missing id in the image url";
return {};
}
auto type = idInfo.at(0);
const auto& type = idInfo.at(0);
if (type == "conversation") {
if (imageId == "temp")
return Utils::tempConversationAvatar(requestedSize);
return Utils::conversationAvatar(lrcInstance_, imageId, requestedSize);
} else if (type == "account")
}
if (type == "account")
return Utils::accountPhoto(lrcInstance_, imageId, requestedSize);
else if (type == "contact")
if (type == "contact")
return Utils::contactPhoto(lrcInstance_, imageId, requestedSize);
qWarning() << Q_FUNC_INFO << "Missing valid prefix in the image url";

View File

@ -77,6 +77,7 @@ void
AvatarRegistry::onProfileUpdated(const QString& uri)
{
auto& convInfo = lrcInstance_->getConversationFromPeerUri(uri);
addOrUpdateImage(uri);
if (convInfo.uid.isEmpty())
return;

View File

@ -35,10 +35,11 @@ IndexRangeFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s
{
auto index = sourceModel()->index(sourceRow, 0, sourceParent);
bool predicate = true;
bool enabled = sourceModel()->data(index, CallControl::Role::Enabled).toBool();
if (filterRole() != Qt::DisplayRole) {
predicate = sourceModel()->data(index, filterRole()).toInt() != 0;
}
return sourceRow <= max_ && sourceRow >= min_ && predicate;
return sourceRow <= max_ && sourceRow >= min_ && predicate && enabled;
}
void
@ -197,10 +198,12 @@ CallControlListModel::data(const QModelIndex& index, int role) const
auto item = data_.at(index.row());
switch (role) {
case Role::ItemAction:
case CallControl::Role::ItemAction:
return QVariant::fromValue(item.itemAction);
case Role::UrgentCount:
case CallControl::Role::UrgentCount:
return QVariant::fromValue(item.urgentCount);
case CallControl::Role::Enabled:
return QVariant::fromValue(item.enabled);
}
return QVariant();
}
@ -212,6 +215,7 @@ CallControlListModel::roleNames() const
QHash<int, QByteArray> roles;
roles[ItemAction] = "ItemAction";
roles[UrgentCount] = "UrgentCount";
roles[Enabled] = "Enabled";
return roles;
}
@ -232,6 +236,24 @@ CallControlListModel::setUrgentCount(QVariant item, int count)
}
}
void
CallControlListModel::setEnabled(QObject* obj, bool enabled)
{
beginResetModel();
auto it = std::find_if(data_.cbegin(), data_.cend(), [obj](const auto& item) {
return item.itemAction == obj;
});
if (it != data_.cend()) {
auto row = std::distance(data_.cbegin(), it);
if (row >= rowCount())
return;
data_[row].enabled = enabled;
auto idx = index(row, 0);
Q_EMIT dataChanged(idx, idx);
}
endResetModel();
}
void
CallControlListModel::addItem(const CallControl::Item& item)
{
@ -264,15 +286,15 @@ CallOverlayModel::CallOverlayModel(LRCInstance* instance, QObject* parent)
}
void
CallOverlayModel::addPrimaryControl(const QVariant& action)
CallOverlayModel::addPrimaryControl(const QVariant& action, bool enabled)
{
primaryModel_->addItem(CallControl::Item {action.value<QObject*>()});
primaryModel_->addItem(CallControl::Item {action.value<QObject*>(), enabled});
}
void
CallOverlayModel::addSecondaryControl(const QVariant& action)
CallOverlayModel::addSecondaryControl(const QVariant& action, bool enabled)
{
secondaryModel_->addItem(CallControl::Item {action.value<QObject*>()});
secondaryModel_->addItem(CallControl::Item {action.value<QObject*>(), enabled});
setControlRanges();
}
@ -282,6 +304,13 @@ CallOverlayModel::setUrgentCount(QVariant row, int count)
secondaryModel_->setUrgentCount(row, count);
}
void
CallOverlayModel::setEnabled(QObject* obj, bool enabled)
{
primaryModel_->setEnabled(obj, enabled);
secondaryModel_->setEnabled(obj, enabled);
}
QVariant
CallOverlayModel::primaryModel()
{
@ -363,7 +392,8 @@ CallOverlayModel::eventFilter(QObject* object, QEvent* event)
void
CallOverlayModel::setControlRanges()
{
auto count = secondaryModel_->rowCount();
overflowModel_->setRange(0, overflowIndex_);
overflowVisibleModel_->setRange(overflowIndex_, secondaryModel_->rowCount());
overflowHiddenModel_->setRange(overflowIndex_ + 1, secondaryModel_->rowCount());
overflowVisibleModel_->setRange(overflowIndex_, count);
overflowHiddenModel_->setRange(overflowIndex_ + 1, count);
}

View File

@ -36,12 +36,13 @@
namespace CallControl {
Q_NAMESPACE
enum Role { ItemAction = Qt::UserRole + 1, UrgentCount };
enum Role { ItemAction = Qt::UserRole + 1, UrgentCount, Enabled};
Q_ENUM_NS(Role)
struct Item
{
QObject* itemAction;
bool enabled {true};
int urgentCount {0};
};
} // namespace CallControl
@ -106,6 +107,7 @@ public:
QHash<int, QByteArray> roleNames() const override;
void setUrgentCount(QVariant item, int count);
void setEnabled(QObject* obj, bool enabled);
void addItem(const CallControl::Item& item);
void clearData();
@ -121,9 +123,10 @@ class CallOverlayModel : public QObject
public:
CallOverlayModel(LRCInstance* instance, QObject* parent = nullptr);
Q_INVOKABLE void addPrimaryControl(const QVariant& action);
Q_INVOKABLE void addSecondaryControl(const QVariant& action);
Q_INVOKABLE void addPrimaryControl(const QVariant& action, bool enabled);
Q_INVOKABLE void addSecondaryControl(const QVariant& action, bool enabled);
Q_INVOKABLE void setUrgentCount(QVariant item, int count);
Q_INVOKABLE void setEnabled(QObject* obj, bool enabled);
Q_INVOKABLE void clearControls();
Q_INVOKABLE QVariant primaryModel();

View File

@ -38,7 +38,7 @@ Item {
property string imageId
readonly property string divider: '_'
readonly property string baseProviderPrefix: 'image://avatarImage'
readonly property string baseProviderPrefix: 'image://avatarimage'
property string typePrefix: {
switch (mode) {
case Avatar.Mode.Account:

View File

@ -20,6 +20,7 @@ import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import net.jami.Constants 1.1
import "../mainview/components"
Popup {
id: root
@ -28,64 +29,80 @@ Popup {
property bool autoClose: true
property alias backgroundColor: container.color
property alias title: titleText.text
property var popupContentLoader: containerSubContentLoader
property var popupcontainerSubContentLoader: containerSubContentLoader
property bool topLayoutVisible: true
property alias popupContentLoadStatus: containerSubContentLoader.status
property alias popupContent: containerSubContentLoader.sourceComponent
property int popupContentPreferredHeight: 0
property int popupContentPreferredWidth: 0
property int popupContentMargins: 0
property int popupContentMargins: JamiTheme.preferredMarginSize
parent: Overlay.overlay
// center in parent
x: Math.round((parent.width - width) / 2)
y: Math.round((parent.height - height) / 2)
anchors.centerIn: parent
modal: true
padding: popupContentMargins
padding: 0
// A popup is invisible until opened.
visible: false
focus: true
closePolicy: autoClose ? (Popup.CloseOnEscape | Popup.CloseOnPressOutside) : Popup.NoAutoClose
Rectangle {
contentItem: Control {
id: container
anchors.fill: parent
property color color: JamiTheme.secondaryBackgroundColor
padding: popupContentMargins
anchors.margins: popupContentMargins
anchors.centerIn: parent
ColumnLayout {
anchors.fill: parent
background: Rectangle {
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 {
id: titleText
RowLayout {
Layout.preferredWidth: parent.width
Layout.bottomMargin: JamiTheme.preferredMarginSize
visible: topLayoutVisible
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
Layout.margins: text.length === 0 ? 0 : 10
Label {
id: titleText
Layout.preferredHeight: text.length === 0 ? 0 : contentHeight
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
font.pointSize: JamiTheme.menuFontSize
color: JamiTheme.textColor
font.pointSize: 12
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 {
id: containerSubContentLoader
Layout.topMargin: popupContentMargins
Layout.bottomMargin: popupContentMargins
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 {
@ -102,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 {
NumberAnimation {
properties: "opacity"

View File

@ -28,7 +28,7 @@ SBSMessageBase {
component JoinCallButton: PushButton {
visible: root.isActive
toolTipText: JamiStrings.joinCall
preferredSize: 40
preferredSize: visible ? 40 : 0
imageColor: callLabel.color
normalColor: "transparent"
hoveredColor: Qt.rgba(255, 255, 255, 0.2)
@ -84,7 +84,7 @@ SBSMessageBase {
}
horizontalAlignment: Qt.AlignHCenter
font.pixelSize: JamiTheme.emojiBubbleSize
font.pointSize: JamiTheme.mediumFontSize
font.hintingPreference: Font.PreferNoHinting
font.bold: true
renderType: Text.NativeRendering

View File

@ -27,9 +27,6 @@ BaseModalDialog {
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 textLabel: ""
@ -40,7 +37,7 @@ BaseModalDialog {
id: labelAction
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: column.width - JamiTheme.preferredMarginSize * 2
Layout.maximumWidth: root.width - JamiTheme.preferredMarginSize * 4
color: JamiTheme.textColor
text: root.textLabel
@ -55,8 +52,8 @@ BaseModalDialog {
RowLayout {
spacing: 16
Layout.fillWidth: true
Layout.alignment: Qt.AlignCenter
Layout.topMargin: JamiTheme.preferredMarginSize
MaterialButton {
id: primaryBtn

View File

@ -30,17 +30,16 @@ Column {
property int timestamp: Timestamp
property string formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
property string formattedDay: MessagesAdapter.getFormattedDay(Timestamp)
property int seq: MsgSeq.single//a changer par textlabel
property int seq: MsgSeq.single
property alias messageToSend: textLabel.text
width: ListView.view ? ListView.view.width : 0
spacing: 2
topPadding: 12
bottomPadding: 12
height: timestampItem.height + textLabel.height
spacing: 0
ColumnLayout {
Item {
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
height: timestampItem.height + textLabel.height
TimestampInfo {
id: timestampItem
@ -49,46 +48,23 @@ Column {
showTime: root.showTime
formattedTime: root.formattedTime
formattedDay: root.formattedDay
Layout.alignment: Qt.AlignHCenter
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
}
Rectangle {
id: msg
Label {
id: textLabel
width: childrenRect.width
height: JamiTheme.contactMessageAvatarSize + 12
radius: JamiTheme.contactMessageAvatarSize / 2 + 6
Layout.alignment: Qt.AlignCenter
color: "transparent"
border.width: 1
border.color: CurrentConversation.isCoreDialog ? JamiTheme.messageInBgColor : CurrentConversation.color
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: timestampItem.bottom
RowLayout {
anchors.verticalCenter: parent.verticalCenter
Avatar {
Layout.leftMargin: 6
width: JamiTheme.contactMessageAvatarSize
height: JamiTheme.contactMessageAvatarSize
visible: ActionUri !== ""
imageId: ActionUri !== CurrentAccount.uri ? ActionUri : CurrentAccount.id
showPresenceIndicator: false
mode: ActionUri !== CurrentAccount.uri ? Avatar.Mode.Contact : Avatar.Mode.Account
}
Label {
id: textLabel
Layout.rightMargin: 6
width: parent.width
text: Body
horizontalAlignment: Qt.AlignHCenter
font.pointSize: JamiTheme.contactEventPointSize
font.bold: true
color: JamiTheme.chatviewTextColor
textFormat: TextEdit.PlainText
}
}
text: Body
horizontalAlignment: Qt.AlignHCenter
font.pointSize: JamiTheme.smallFontSize
color: JamiTheme.chatviewSecondaryInformationColor
textFormat: TextEdit.PlainText
}
}
opacity: 0

View File

@ -68,7 +68,8 @@ BaseModalDialog {
id: daemonReconnectPopupTextLabel
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
font.pointSize: JamiTheme.textFontSize + 2

View File

@ -88,8 +88,11 @@ Loader {
target: parent
enabled: canOpen
onHoveredChanged: {
dataTransferItem.hoveredLink = enabled && hovered ?
("file:///" + Body) : ""
if (enabled && hovered) {
dataTransferItem.hoveredLink = UtilsAdapter.urlFromLocalPath(Body)
} else {
dataTransferItem.hoveredLink = ""
}
}
cursorShape: enabled ?
Qt.PointingHandCursor :
@ -199,10 +202,12 @@ Loader {
Qt.PointingHandCursor :
Qt.ArrowCursor
onClicked: function (mouse) {
dataTransferItem.hoveredLink = canOpen ?
("file:///" + Body) : ""
if (dataTransferItem.hoveredLink)
if (canOpen) {
dataTransferItem.hoveredLink = UtilsAdapter.urlFromLocalPath(Body)
Qt.openUrlExternally(new Url(dataTransferItem.hoveredLink))
} else {
dataTransferItem.hoveredLink = ""
}
}
}
}
@ -303,7 +308,7 @@ Loader {
antialiasing: true
autoTransform: true
asynchronous: true
source: "file:///" + Body
source: UtilsAdapter.urlFromLocalPath(Body)
property real aspectRatio: implicitWidth / implicitHeight
property real adjustedWidth: Math.min(maxSize,
Math.max(minSize,
@ -348,7 +353,7 @@ Loader {
antialiasing: true
autoTransform: true
asynchronous: true
source: Body !== undefined ? "file:///" + Body : ''
source: Body !== undefined ? UtilsAdapter.urlFromLocalPath(Body) : ''
// The sourceSize represents the maximum source dimensions.
// This should not be a dynamic binding, as property changes

View File

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

View File

@ -85,10 +85,12 @@ BaseView {
clip: true
required property bool isMinorPane
onWidthChanged: {
if (!isSinglePane && ((isRTL && !isMinorPane) || (!isRTL && isMinorPane)))
if (!isSinglePane && isMinorPane)
previousMinorPaneWidth = width
if (!isSinglePane && ((isRTL && isMinorPane) || (!isRTL && !isMinorPane)))
if (!isSinglePane && !isMinorPane)
previousMajorPaneWidth = width
if (isMinorPane)
JamiTheme.currentLeftPaneWidth = width
}
Connections {
@ -101,8 +103,9 @@ BaseView {
}
}
SplitView.minimumWidth: isSinglePane ? viewNode.width : (isMinorPane && !isRTL ? minorPaneMinWidth : majorPaneMinWidth)
SplitView.maximumWidth: isSinglePane ? viewNode.width : viewNode.width - (isMinorPane && !isRTL ? majorPaneMinWidth : minorPaneMinWidth)
SplitView.preferredWidth: isMinorPane && !isRTL ? minorPaneMinWidth : majorPaneMinWidth
SplitView.minimumWidth: isSinglePane ? undefined : (isMinorPane ? minorPaneMinWidth : majorPaneMinWidth)
SplitView.maximumWidth: isSinglePane || !isMinorPane ? undefined : Math.abs(viewNode.width - majorPaneMinWidth)
SplitView.preferredWidth: isSinglePane || !isMinorPane ? undefined : JamiTheme.currentLeftPaneWidth
SplitView.fillWidth: !isMinorPane || isSinglePane
}
}

View File

@ -25,19 +25,13 @@ import net.jami.Constants 1.1
BaseModalDialog {
id: root
width: 488
height: 256
width: JamiTheme.secondaryDialogDimension
property var previousBodies: undefined
popupContent: Item {
id: rect
width: root.width
JamiListView {
anchors.fill: parent
anchors.margins: JamiTheme.preferredMarginSize
popupContent: JamiListView {
width: root.width - 4 * JamiTheme.preferredMarginSize
height: Math.min(count * 50, 150)
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

@ -31,7 +31,7 @@ Popup {
background.visible: false
parent: Overlay.overlay
property var emojiReaction
property var reactions
property string msgId
// center in parent
@ -42,6 +42,7 @@ Popup {
padding: 0
visible: false
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
Rectangle {
@ -88,9 +89,9 @@ Popup {
spacing: 15
Layout.preferredWidth: 400
Layout.preferredHeight: childrenRect.height + 30 < 700 ? childrenRect.height + 30 : 700
model: Object.entries(emojiReaction)
model: Object.entries(reactions)
clip: true
property int modelCount: Object.entries(emojiReaction).length
property int modelCount: Object.entries(reactions).length
delegate: RowLayout {
width: parent.width

View File

@ -24,19 +24,24 @@ import net.jami.Constants 1.1
Item {
id: root
property var emojiReaction
property real contentHeight: bubble.height
property real contentWidth: bubble.width
property var emojiTexts: ownEmojiList
width: reactionBubble.width
property var reactions
property real contentHeight: reactionBubble.height
property real contentWidth: reactionBubble.width
property color borderColor: undefined
property int maxWidth: JamiTheme.defaulMaxWidthReaction
visible: emojis.length && Body !== ""
property string emojis: {
if (reactions === undefined)
return [];
var space = "";
var emojiList = [];
var emojiNumberList = [];
for (const reactions of Object.entries(emojiReaction)) {
var authorEmojiList = reactions[1];
for (const reaction of Object.entries(reactions)) {
var authorEmojiList = reaction[1];
for (var emojiIndex in authorEmojiList) {
var emoji = authorEmojiList[emojiIndex];
if (emojiList.includes(emoji)) {
@ -60,12 +65,14 @@ Item {
return cur;
}
property var ownEmojiList: {
property var ownEmojis: {
if (reactions === undefined)
return [];
var list = [];
var index = 0;
for (const reactions of Object.entries(emojiReaction)) {
var authorUri = reactions[0];
var authorEmojiList = reactions[1];
for (const reaction of Object.entries(reactions)) {
var authorUri = reaction[0];
var authorEmojiList = reaction[1];
if (CurrentAccount.uri === authorUri) {
for (var emojiIndex in authorEmojiList) {
list[index] = authorEmojiList[emojiIndex];
@ -77,36 +84,30 @@ Item {
return [];
}
// TODO:
// -order emojis based on the timestamp of the reaction and/or the quantity of emojis
Rectangle {
id: bubble
id: reactionBubble
color: JamiTheme.emojiReactBubbleBgColor
width: textEmojis.width + 6
height: textEmojis.height + 6
radius: 10
Text {
id: textEmojis
anchors.margins: 10
anchors.centerIn: bubble
font.pointSize: JamiTheme.emojiReactSize
color: JamiTheme.chatviewTextColor
text: root.emojis
}
width: textEmojis.width + 10
height: textEmojis.height + 10
anchors.centerIn: textEmojis
radius: 5
border.color: root.borderColor
border.width: 1
}
DropShadow {
z: -1
Text {
id: textEmojis
anchors.margins: 10
anchors.centerIn: root
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
font.pointSize: JamiTheme.emojiReactSize
color: JamiTheme.chatviewTextColor
text: root.emojis
width: Math.min(implicitWidth,root.maxWidth)
wrapMode: Text.Wrap
}
}

View File

@ -40,6 +40,7 @@ Column {
ColumnLayout {
width: parent.width
spacing: 0
TimestampInfo {
id: timestampItem

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2022-2023 Savoir-faire Linux Inc.
* Author: Xavier Jouslin <xavier.jouslindenoray@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 Qt.labs.platform
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
RowLayout {
id: root
property string labelText: ""
property int widthOfSwitch: 50
property int heightOfSwitch: 10
property string tooltipText: ""
property alias toggleSwitch: autoupdate
property alias checked: autoupdate.checked
signal switchToggled
Layout.alignment: Qt.AlignRight
JamiSwitch {
id: autoupdate
Layout.alignment: Qt.AlignLeft
Layout.preferredWidth: widthOfSwitch
hoverEnabled: true
toolTipText: tooltipText
Accessible.role: Accessible.Button
Accessible.name: JamiStrings.autoUpdate
Accessible.description: root.tooltipText
onToggled: switchToggled()
}
Text {
id: description
Layout.rightMargin: JamiTheme.preferredMarginSize
text: JamiStrings.autoUpdate
font.pixelSize: JamiTheme.wizardViewButtonFontPixelSize
visible: labelText !== ""
font.kerning: true
wrapMode: Text.WordWrap
verticalAlignment: Text.AlignVCenter
color: JamiTheme.textColor
}
TapHandler {
target: parent
enabled: parent.visible
onTapped: function onTapped(eventPoint) {
// switchToggled should be emitted as onToggled is not called (because it's only called if the user click on the switch)
autoupdate.toggle();
switchToggled();
}
}
}

View File

@ -23,151 +23,188 @@ import net.jami.Adapters 1.1
import net.jami.Constants 1.1
Item {
id: root
id: jamiId
property alias backgroundColor: outerRect.color
property bool slimDisplay: true
property color backgroundColor: JamiTheme.welcomeBlockColor
property color contentColor: JamiTheme.tintedBlue
property bool centered: true
height: getHeight()
width: childrenRect.width
height: controlsLayout.height + usernameTextEdit.height + 2 * JamiTheme.preferredMarginSize
// Background rounded rectangle.
Rectangle {
id: outerRect
anchors.fill: parent
radius: 20
color: JamiTheme.secondaryBackgroundColor
function getHeight() {
return outerRow.height;
}
// Logo masked by outerRect.
Item {
anchors.fill: outerRect
layer.enabled: true
layer.effect: OpacityMask {
maskSource: outerRect
}
Rectangle {
id: logoRect
width: 97 + radius
height: 40
color: JamiTheme.mainColor
radius: 20
anchors.top: parent.top
anchors.left: parent.left
anchors.leftMargin: -radius
ResponsiveImage {
id: jamiIdLogo
anchors.horizontalCenter: parent.horizontalCenter
// Adjust offset for parent masking margin.
anchors.horizontalCenterOffset: parent.radius / 2
anchors.verticalCenter: parent.verticalCenter
width: JamiTheme.jamiIdLogoWidth
height: JamiTheme.jamiIdLogoHeight
source: JamiResources.jamiid_svg
}
}
}
ColumnLayout {
id: columnLayout
spacing: JamiTheme.preferredMarginSize
RowLayout {
id: controlsLayout
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.topMargin: JamiTheme.pushButtonMargin / 2
Layout.rightMargin: JamiTheme.pushButtonMargin
Layout.preferredHeight: childrenRect.height
JamiIdControlButton {
id: btnEdit
visible: CurrentAccount.registeredName === ""
border.color: enabled ? JamiTheme.buttonTintedBlue : JamiTheme.buttonTintedBlack
imageColor: enabled ? JamiTheme.buttonTintedBlue : JamiTheme.buttonTintedBlack
enabled: {
if (!usernameTextEdit.editMode)
return true;
switch (usernameTextEdit.nameRegistrationState) {
case UsernameTextEdit.NameRegistrationState.BLANK:
case UsernameTextEdit.NameRegistrationState.FREE:
return true;
case UsernameTextEdit.NameRegistrationState.SEARCHING:
case UsernameTextEdit.NameRegistrationState.INVALID:
case UsernameTextEdit.NameRegistrationState.TAKEN:
return false;
}
}
source: usernameTextEdit.editMode ? JamiResources.check_black_24dp_svg : JamiResources.round_edit_24dp_svg
toolTipText: JamiStrings.chooseUsername
onClicked: {
if (usernameTextEdit.readOnly) {
usernameTextEdit.startEditing();
usernameTextEdit.readOnly = false;
} else {
usernameTextEdit.accepted();
}
}
}
JamiIdControlButton {
id: btnCopy
source: JamiResources.content_copy_24dp_svg
toolTipText: JamiStrings.copy
onClicked: UtilsAdapter.setClipboardText(usernameTextEdit.staticText)
}
JamiIdControlButton {
id: btnShare
source: JamiResources.share_24dp_svg
toolTipText: JamiStrings.share
onClicked: viewCoordinator.presentDialog(appWindow, "mainview/components/WelcomePageQrDialog.qml")
}
JamiIdControlButton {
id: btnId
source: JamiResources.key_black_24dp_svg
visible: CurrentAccount.registeredName !== ""
toolTipText: JamiStrings.identifierURI
onClicked: {
if (clicked) {
usernameTextEdit.staticText = CurrentAccount.uri;
btnId.toolTipText = JamiStrings.identifierRegisterName;
} else {
usernameTextEdit.staticText = CurrentAccount.registeredName;
btnId.toolTipText = JamiStrings.identifierURI;
}
clicked = !clicked;
}
}
}
UsernameTextEdit {
id: usernameTextEdit
Layout.preferredWidth: 330
Layout.preferredHeight: implicitHeight + JamiTheme.preferredMarginSize
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
fontPixelSize: JamiTheme.jamiIdFontSize
editMode: false
isPersistent: false
readOnly: true
onAccepted: {
Connections {
target: CurrentAccount
function onIdChanged(id) {
if (!usernameTextEdit.readOnly) {
usernameTextEdit.readOnly = true;
if (dynamicText === '') {
return;
}
}
}
RowLayout {
id: outerRow
anchors.horizontalCenter: jamiId.centered ? parent.horizontalCenter : undefined
anchors.left: jamiId.centered ? undefined : parent.left
spacing: 2
RoundedBorderRectangle {
id: leftRect
fillColor: jamiId.backgroundColor
Layout.preferredWidth: childrenRect.width
Layout.maximumWidth: jamiId.width - rightRect.width
Layout.preferredHeight: childrenRect.height
radius: {
"tl": 5,
"tr": 0,
"br": 0,
"bl": 5
}
RowLayout {
anchors.verticalCenter: parent.verticalCenter
ResponsiveImage {
id: jamiIdLogoImage
Layout.preferredHeight: 40
containerHeight: 40
containerWidth: 40
Layout.leftMargin: JamiTheme.pushButtonMargins
source: JamiResources.jami_id_logo_svg
color: jamiId.contentColor
}
UsernameTextEdit {
id: usernameTextEdit
visible: !readOnly
Layout.preferredHeight: 40
Layout.alignment: Qt.AlignVCenter
textColor: jamiId.contentColor
fontPixelSize: staticText.length > 16 || dynamicText.length > 16 ? JamiTheme.jamiIdSmallFontSize : JamiTheme.bigFontSize
editMode: false
isPersistent: false
readOnly: true
onAccepted: {
usernameTextEdit.readOnly = true;
if (dynamicText === '') {
return;
}
var dlg = viewCoordinator.presentDialog(appWindow, "settingsview/components/NameRegistrationDialog.qml", {
"registeredName": dynamicText
});
dlg.accepted.connect(function () {
usernameTextEdit.nameRegistrationState = UsernameTextEdit.NameRegistrationState.BLANK;
});
}
}
Label{
id: usernameLabel
visible: usernameTextEdit.readOnly
Layout.alignment: Qt.AlignVCenter
Layout.rightMargin: JamiTheme.pushButtonMargins
Layout.maximumWidth: leftRect.width - 50
elide: Text.ElideRight
color: jamiId.contentColor
font.pixelSize : text.length > 16 ? JamiTheme.jamiIdSmallFontSize : JamiTheme.bigFontSize
property string registeredName: CurrentAccount.registeredName
property string infohash: CurrentAccount.uri
text: registeredName ? registeredName : infohash
}
}
}
RoundedBorderRectangle {
id: rightRect
fillColor: jamiId.backgroundColor
Layout.preferredWidth: childrenRect.width + 2 * JamiTheme.pushButtonMargins
Layout.preferredHeight: leftRect.height
radius: {
"tl": 0,
"tr": 5,
"br": 5,
"bl": 0
}
RowLayout {
id: controlsLayout
height: childrenRect.height
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: JamiTheme.pushButtonMargins
anchors.leftMargin: JamiTheme.pushButtonMargins
anchors.horizontalCenter: parent.horizontalCenter
JamiIdControlButton {
id: btnEdit
anchors.leftMargin: JamiTheme.pushButtonMargins
visible: CurrentAccount.registeredName === ""
border.color: enabled ? jamiId.contentColor : JamiTheme.buttonTintedBlack
imageColor: enabled ? jamiId.contentColor : JamiTheme.buttonTintedBlack
enabled: {
if (!usernameTextEdit.editMode)
return true;
switch (usernameTextEdit.nameRegistrationState) {
case UsernameTextEdit.NameRegistrationState.BLANK:
case UsernameTextEdit.NameRegistrationState.FREE:
return true;
case UsernameTextEdit.NameRegistrationState.SEARCHING:
case UsernameTextEdit.NameRegistrationState.INVALID:
case UsernameTextEdit.NameRegistrationState.TAKEN:
return false;
}
}
source: usernameTextEdit.editMode ? JamiResources.check_black_24dp_svg : JamiResources.round_edit_24dp_svg
toolTipText: JamiStrings.chooseUsername
onClicked: {
if (usernameTextEdit.readOnly) {
usernameTextEdit.startEditing();
usernameTextEdit.readOnly = false;
} else {
usernameTextEdit.accepted();
}
}
}
JamiIdControlButton {
id: btnCopy
anchors.leftMargin: JamiTheme.pushButtonMargins
source: JamiResources.content_copy_24dp_svg
border.color: "transparent"
toolTipText: JamiStrings.copy
onClicked: UtilsAdapter.setClipboardText(usernameTextEdit.staticText)
}
JamiIdControlButton {
id: btnShare
source: JamiResources.share_24dp_svg
border.color: "transparent"
toolTipText: JamiStrings.share
onClicked: viewCoordinator.presentDialog(appWindow, "mainview/components/WelcomePageQrDialog.qml")
}
JamiIdControlButton {
id: btnId
source: JamiResources.key_black_24dp_svg
visible: CurrentAccount.registeredName !== ""
border.color: "transparent"
toolTipText: JamiStrings.identifierURI
onClicked: {
if (clicked) {
usernameLabel.text = Qt.binding(function() {return CurrentAccount.uri} );
usernameTextEdit.staticText = Qt.binding(function() {return CurrentAccount.uri} );
btnId.toolTipText = JamiStrings.identifierRegisterName;
} else {
usernameLabel.text = Qt.binding(function() {return CurrentAccount.registeredName} );
usernameTextEdit.staticText = Qt.binding(function() {return CurrentAccount.registeredName} );
btnId.toolTipText = JamiStrings.identifierURI;
}
clicked = !clicked;
}
}
var dlg = viewCoordinator.presentDialog(appWindow, "settingsview/components/NameRegistrationDialog.qml", {
"registeredName": dynamicText
});
dlg.accepted.connect(function () {
usernameTextEdit.nameRegistrationState = UsernameTextEdit.NameRegistrationState.BLANK;
});
}
}
}
@ -175,11 +212,12 @@ Item {
component JamiIdControlButton: PushButton {
property bool clicked: true
preferredSize: 30
radius: 5
normalColor: JamiTheme.transparentColor
hoveredColor: JamiTheme.hoveredButtonColorWizard
imageContainerWidth: JamiTheme.pushButtonSize
imageContainerHeight: JamiTheme.pushButtonSize
border.color: JamiTheme.tintedBlue
imageColor: JamiTheme.buttonTintedBlue
border.color: jamiId.contentColor
imageColor: jamiId.contentColor
duration: 0
}
}

View File

@ -30,14 +30,18 @@ Popup {
padding: 0
property list<Action> menuTypoActionsSecond
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
contentItem: ListView {
id: listViewTypoSecond
width: contentWidth + leftMargin
width: contentWidth + leftMargin + rightMargin
height: JamiTheme.chatViewFooterButtonSize
orientation: ListView.Horizontal
interactive: false
leftMargin: 10
rightMargin: 10
spacing: 10
Rectangle {
@ -50,7 +54,7 @@ Popup {
model: menuTypoActionsSecond
delegate: PushButton {
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenter: parent ? parent.verticalCenter : undefined
preferredSize: JamiTheme.chatViewFooterRealButtonSize
imageContainerWidth: 20
@ -64,7 +68,7 @@ Popup {
focusPolicy: Qt.TabFocus
normalColor: JamiTheme.chatViewFooterListColor
imageColor: JamiTheme.chatViewFooterImgColor
imageColor: JamiTheme.chatViewFooterImgHoverColor
hoveredColor: JamiTheme.showMoreButtonOpenColor
pressedColor: hoveredColor

View File

@ -27,7 +27,6 @@ AbstractButton {
id: root
property bool autoAccelerator: false
property bool boldFont: false
property bool primary: false
property bool secondary: false
property bool tertiary: false
@ -51,12 +50,12 @@ AbstractButton {
height: buttontextHeightMargin + textButton.height
Layout.preferredHeight: height
Binding on width {
Binding on width {
when: root.preferredWidth !== undefined || root.Layout.fillWidth
value: root.preferredWidth
}
Binding on Layout.preferredWidth {
Binding on Layout.preferredWidth {
when: root.preferredWidth !== undefined || root.Layout.fillWidth
value: width
}
@ -66,7 +65,6 @@ AbstractButton {
value: height
}
hoverEnabled: true
focusPolicy: Qt.StrongFocus
Accessible.role: Accessible.Button
@ -96,7 +94,7 @@ AbstractButton {
contentItem: Item {
id: item
Binding on implicitWidth {
Binding on implicitWidth {
when: root.preferredWidth === undefined || !root.Layout.fillWidth
value: item.childrenRect.width
}
@ -105,7 +103,7 @@ AbstractButton {
RowLayout {
anchors.verticalCenter: parent.verticalCenter
Binding on width {
Binding on width {
when: root.preferredWidth !== undefined || root.Layout.fillWidth
value: root.availableWidth
}
@ -168,7 +166,6 @@ AbstractButton {
leftPadding: root.primary ? JamiTheme.buttontextWizzardPadding : textLeftPadding
rightPadding: root.primary ? JamiTheme.buttontextWizzardPadding : textRightPadding
text: root.text
font.weight: (root.hovered && root.hoverEnabled) || boldFont ? Font.Bold : Font.Medium
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
horizontalAlignment: root.textAlignment
@ -183,18 +180,18 @@ AbstractButton {
color: {
var baseColor = root.color;
if (root.primary) {
if (root.hovered && root.hoverEnabled)
if (root.hovered && root.enabled)
return root.hoveredColor;
return baseColor;
}
if (root.secondary || root.tertiary) {
if (root.hovered && root.hoverEnabled)
if (root.hovered && root.enabled)
return root.secHoveredColor;
return JamiTheme.transparentColor;
}
if (root.down)
return root.pressedColor;
if (root.hovered && root.hoverEnabled)
if (root.hovered && root.enabled)
return root.hoveredColor;
return baseColor;
}
@ -202,7 +199,7 @@ AbstractButton {
border.color: {
if (root.primary || root.tertiary)
return JamiTheme.transparentColor;
if (root.secondary && root.hovered && root.hoverEnabled)
if (root.secondary && root.hovered && root.enabled)
return JamiTheme.secondaryButtonHoveredBorderColor;
if (root.secondary)
return JamiTheme.secondaryButtonBorderColor;
@ -226,7 +223,7 @@ AbstractButton {
// We don't want to eat clicks on the Text.
acceptedButtons: Qt.NoButton
cursorShape: (root.hovered && root.hoverEnabled) ? Qt.PointingHandCursor : Qt.ArrowCursor
cursorShape: (root.hovered && root.enabled) ? Qt.PointingHandCursor : Qt.ArrowCursor
}
Shortcut {

View File

@ -74,7 +74,7 @@ RadioButton {
spacing: 10
anchors.left: root.indicator.right
anchors.leftMargin: root.spacing
anchors.leftMargin: 10
ResponsiveImage {
color: borderColor
@ -89,6 +89,8 @@ RadioButton {
font.pixelSize: JamiTheme.settingsDescriptionPixelSize
text: root.text
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
}
}
@ -100,7 +102,7 @@ RadioButton {
color: "transparent"
implicitHeight: 20
implicitWidth: 20
radius: JamiTheme.settingsBoxRadius
radius: 10
z: 1
border {
@ -114,7 +116,7 @@ RadioButton {
anchors.verticalCenter: parent.verticalCenter
color: checkedColor
height: 12
radius: JamiTheme.settingsBoxRadius
radius: 10
visible: checked || hovered
width: 12

View File

@ -33,9 +33,11 @@ Popup {
padding: 0
background.visible: false
required property var emojiReactions
property var emojiReplied: emojiReactions.ownEmojis
required property string msgId
required property string msgBody
required property var emojiReplied
required property bool isOutgoing
required property int type
required property string transferName
@ -47,6 +49,9 @@ Popup {
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
@ -107,27 +112,11 @@ Popup {
onClosed: if (emojiPicker) emojiPicker.closeEmojiPicker()
function getModel() {
var model = ["👍", "👎", "😂"]
var cur = []
//Add emoji reacted
var index = 0
for (let emoji of emojiReplied) {
if (index < model.length) {
cur[index] = emoji
index ++
}
}
//complete with default model
var modelIndex = cur.length
for (let j = 0; j < model.length; j++) {
if (cur.length < model.length) {
if (!cur.includes(model[j]) ) {
cur[modelIndex] = model[j]
modelIndex ++
}
}
}
return cur
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 {
@ -167,7 +156,7 @@ Popup {
background: Rectangle {
anchors.fill: parent
opacity: emojiReplied.includes(modelData) ? 1 : 0
opacity: emojiReplied ? (emojiReplied.includes(modelData) ? 1 : 0) : 0
color: JamiTheme.emojiReactPushButtonColor
radius: 10
}
@ -239,6 +228,18 @@ Popup {
}
}
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

View File

@ -75,7 +75,7 @@ Loader {
// Needed to give proper focus to loaded item
onFocusChanged: {
if (root.focus && root.isPersistent) {
if (item && root.focus && root.isPersistent) {
item.forceActiveFocus();
}
isEditing = !isEditing;

View File

@ -35,9 +35,6 @@ BaseModalDialog {
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: {
switch (purpose) {
case PasswordDialog.ExportAccount:
@ -75,7 +72,7 @@ BaseModalDialog {
popupContent: ColumnLayout {
id: popupContentColumnLayout
spacing: 0
spacing: 16
function validatePassword() {
switch (purpose) {
@ -128,6 +125,8 @@ BaseModalDialog {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: JamiTheme.preferredFieldWidth
Layout.preferredHeight: visible ? 48 : 0
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.ExportAccount
placeholderText: JamiStrings.enterCurrentPassword
@ -141,6 +140,8 @@ BaseModalDialog {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: JamiTheme.preferredFieldWidth
Layout.preferredHeight: visible ? 48 : 0
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.SetPassword
@ -155,6 +156,8 @@ BaseModalDialog {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: JamiTheme.preferredFieldWidth
Layout.preferredHeight: visible ? 48 : 0
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.rightMargin: JamiTheme.preferredMarginSize
visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.SetPassword
@ -163,49 +166,24 @@ BaseModalDialog {
onDynamicTextChanged: popupContentColumnLayout.validatePassword()
}
RowLayout {
spacing: 16
Layout.fillWidth: true
Layout.alignment: Qt.AlignCenter
MaterialButton {
id: btnConfirm
MaterialButton {
id: btnConfirm
Layout.alignment: Qt.AlignHCenter
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
hoveredColor: JamiTheme.buttonTintedBlackHovered
pressedColor: JamiTheme.buttonTintedBlackPressed
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()
onClicked: {
btnConfirm.enabled = false;
timerToOperate.restart();
}
}
}

View File

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

View File

@ -85,7 +85,7 @@ ItemDelegate {
id: prefLlabel
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.leftMargin: 8
Layout.leftMargin: 20
text: preferenceName
color: JamiTheme.textColor
@ -103,7 +103,7 @@ ItemDelegate {
normalColor: JamiTheme.primaryBackgroundColor
Layout.alignment: Qt.AlignRight | Qt.AlingVCenter
Layout.rightMargin: 8
Layout.rightMargin: 20
Layout.preferredWidth: preferredSize
Layout.preferredHeight: preferredSize
imageColor: JamiTheme.textColor
@ -119,7 +119,7 @@ ItemDelegate {
visible: preferenceType === PreferenceItemListModel.SWITCH
Layout.alignment: Qt.AlignRight | Qt.AlingVCenter
Layout.rightMargin: 16
Layout.rightMargin: 20
Layout.preferredHeight: 30
Layout.preferredWidth: 30
checked: preferenceCurrentValue === "1"
@ -134,7 +134,7 @@ ItemDelegate {
visible: preferenceType === PreferenceItemListModel.LIST
Layout.preferredWidth: root.width / 2 - 8
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.rightMargin: 4
Layout.rightMargin: 20
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
@ -157,7 +157,7 @@ ItemDelegate {
buttontextHeightMargin: JamiTheme.buttontextHeightMargin
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.rightMargin: 4
Layout.rightMargin: 20
text: UtilsAdapter.fileName(preferenceCurrentValue)
toolTipText: JamiStrings.chooseImageFile
@ -176,7 +176,7 @@ ItemDelegate {
Layout.preferredWidth: root.width / 2 - 8
Layout.preferredHeight: 30
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.rightMargin: 4
Layout.rightMargin: 20
visible: preferenceType === PreferenceItemListModel.EDITTEXT
width: root.width / 2 - 8

View File

@ -64,7 +64,7 @@ Item {
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
selectByMouse: true
font.pixelSize: IsEmojiOnly ? JamiTheme.chatviewEmojiSize : JamiTheme.emojiBubbleSize
font.pixelSize: IsEmojiOnly ? JamiTheme.chatviewEmojiSize : JamiTheme.mediumFontSize
font.hintingPreference: Font.PreferNoHinting
renderType: Text.NativeRendering
textFormat: Text.MarkdownText

View File

@ -31,7 +31,9 @@ Item {
property alias source: image.source
property alias status: image.status
property alias fillMode: image.fillMode
property alias cache: image.cache
property alias image: image
property alias mirror: image.mirror
property string color: "transparent"
property bool hovered: false
@ -68,6 +70,7 @@ Item {
antialiasing: true
asynchronous: true
visible: false
mipmap: true
function setSourceSize() {
sourceSize = undefined;

View File

@ -0,0 +1,77 @@
/*
* 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 Qt5Compat.GraphicalEffects
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
Canvas {
property var radius
property string fillColor: Style.colorBGPrimary
onRadiusChanged: requestPaint()
onFillColorChanged: requestPaint()
//Draw rounded rectangle.
onPaint: {
var ctx = getContext("2d");
var r = {};
Object.assign(r, radius);
if (typeof r === 'undefined')
r = 0;
if (typeof r === 'number')
r = {
"tl": r,
"tr": r,
"br": r,
"bl": r
};
else {
var defaultRadius = {
"tl": 0,
"tr": 0,
"br": 0,
"bl": 0
};
for (var side in defaultRadius)
r[side] = r[side] || defaultRadius[side];
}
var x0 = 0;
var y0 = x0;
var x1 = width;
var y1 = height;
ctx.reset();
ctx.beginPath();
ctx.moveTo(x0 + r.tl, y0);
ctx.lineTo(x1 - r.tr, y0);
ctx.quadraticCurveTo(x1, y0, x1, y0 + r.tr);
ctx.lineTo(x1, y1 - r.br);
ctx.quadraticCurveTo(x1, y1, x1 - r.br, y1);
ctx.lineTo(x0 + r.bl, y1);
ctx.quadraticCurveTo(x0, y1, x0, y1 - r.bl);
ctx.lineTo(x0, y0 + r.tl);
ctx.quadraticCurveTo(x0, y0, x0 + r.tl, y0);
ctx.closePath();
ctx.fillStyle = fillColor;
ctx.fill();
}
}

View File

@ -15,12 +15,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
@ -62,11 +60,20 @@ Control {
property real textContentHeight
property bool isReply: ReplyTo !== ""
property real maxMsgWidth: root.width - senderMargin - 2 * hPadding - avatarBlockWidth
// If the ListView attached properties are not available,
// then the root delegate is likely a Loader.
readonly property ListView listView: ListView.view ?
ListView.view :
parent.ListView.view
readonly property ListView listView: ListView.view ? ListView.view : parent.ListView.view
function getBaseColor() {
var baseColor = isOutgoing ? CurrentConversation.color : JamiTheme.messageInBgColor;
if (Id === MessagesAdapter.replyToId || Id === MessagesAdapter.editId) {
// If we are replying to or editing the message
return Qt.darker(baseColor, 1.5);
}
return baseColor;
}
rightPadding: hPadding
leftPadding: hPadding
@ -94,21 +101,21 @@ Control {
id: usernameblock
Layout.preferredHeight: (seq === MsgSeq.first || seq === MsgSeq.single) ? 10 : 0
visible: !isReply
Layout.topMargin: (seq === MsgSeq.first || seq === MsgSeq.single) && !isOutgoing && !root.showTime ? 20 : 0
Label {
id: username
text: UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author)
font.bold: true
visible:(seq === MsgSeq.first || seq === MsgSeq.single) && !isOutgoing
font.pixelSize: JamiTheme.usernameBlockFontSize
color: JamiTheme.chatviewUsernameColor
visible: (seq === MsgSeq.first || seq === MsgSeq.single) && !isOutgoing
font.pointSize: JamiTheme.smallFontSize
color: JamiTheme.chatviewSecondaryInformationColor
lineHeight: JamiTheme.usernameBlockLineHeight
leftPadding: JamiTheme.usernameBlockPadding
textFormat: TextEdit.PlainText
}
}
Item {
id: replyItem
property bool isSelf: ReplyToAuthor === CurrentAccount.uri
@ -119,18 +126,19 @@ Control {
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
Layout.topMargin: JamiTheme.sbsMessageBaseReplyTopMargin
Layout.topMargin: visible ? JamiTheme.sbsMessageBaseReplyTopMargin : 0
Layout.leftMargin: isOutgoing ? undefined : JamiTheme.sbsMessageBaseReplyMargin
Layout.rightMargin: !isOutgoing ? undefined : JamiTheme.sbsMessageBaseReplyMargin
transform: Translate { y: JamiTheme.sbsMessageBaseReplyBottomMargin }
transform: Translate {
y: JamiTheme.sbsMessageBaseReplyBottomMargin
}
ColumnLayout {
width: parent.width
spacing: 2
RowLayout{
RowLayout {
id: replyToLayout
Layout.alignment: isOutgoing ? Qt.AlignRight : Qt.AlignLeft
@ -155,8 +163,8 @@ Control {
showPresenceIndicator: false
imageId: {
if (replyItem.isSelf)
return CurrentAccount.id
return ReplyToAuthor
return CurrentAccount.id;
return ReplyToAuthor;
}
mode: replyItem.isSelf ? Avatar.Mode.Account : Avatar.Mode.Contact
}
@ -179,11 +187,10 @@ Control {
color: replyItem.isSelf ? CurrentConversation.color : JamiTheme.messageInBgColor
radius: msgRadius
Layout.preferredWidth: replyToRow.width + 2*JamiTheme.preferredMarginSize
Layout.preferredHeight: replyToRow.height + 2*JamiTheme.preferredMarginSize
Layout.preferredWidth: replyToRow.width + 2 * JamiTheme.preferredMarginSize
Layout.preferredHeight: replyToRow.height + 2 * JamiTheme.preferredMarginSize
Layout.alignment: isOutgoing ? Qt.AlignRight : Qt.AlignLeft
// place actual content here
ReplyToRow {
id: replyToRow
@ -194,8 +201,8 @@ Control {
MouseArea {
z: 2
anchors.fill: parent
onClicked: function(mouse) {
CurrentConversation.scrollToMsg(ReplyTo)
onClicked: function (mouse) {
CurrentConversation.scrollToMsg(ReplyTo);
}
}
}
@ -205,13 +212,13 @@ Control {
RowLayout {
id: msgRowlayout
Layout.preferredHeight: innerContent.height + root.extraHeight
Layout.preferredHeight: innerContent.height + root.extraHeight + (emojiReactions.emojis === "" ? 0 : emojiReactions.height - 8)
Layout.topMargin: ((seq === MsgSeq.first || seq === MsgSeq.single) && !root.isReply) ? 6 : 0
Item {
id: avatarBlock
Layout.preferredWidth: isOutgoing ? 0 : avatar.width + hPadding/3
Layout.preferredWidth: isOutgoing ? 0 : avatar.width + hPadding / 3
Layout.preferredHeight: isOutgoing ? 0 : bubble.height
Avatar {
id: avatar
@ -238,7 +245,7 @@ Control {
hoverEnabled: true
onClicked: function (mouse) {
if (root.hoveredLink) {
MessagesAdapter.openUrl(root.hoveredLink)
MessagesAdapter.openUrl(root.hoveredLink);
}
}
property bool bubbleHovered: containsMouse || textHovered
@ -276,30 +283,24 @@ Control {
anchors.verticalCenter: parent.verticalCenter
anchors.right: isOutgoing ? optionButtonItem.right : undefined
anchors.left: !isOutgoing ? optionButtonItem.left : undefined
visible: CurrentAccount.type !== Profile.Type.SIP && Body !== "" &&
(
bubbleArea.bubbleHovered
|| hovered
|| reply.hovered
|| bgHandler.hovered
)
visible: CurrentAccount.type !== Profile.Type.SIP && Body !== "" && (bubbleArea.bubbleHovered || hovered || reply.hovered || bgHandler.hovered)
source: JamiResources.more_vert_24dp_svg
width: optionButtonItem.width / 2
height: optionButtonItem.height
onClicked: {
var component = Qt.createComponent("qrc:/commoncomponents/MessageOptionsPopup.qml")
var component = Qt.createComponent("qrc:/commoncomponents/MessageOptionsPopup.qml");
var obj = component.createObject(bubble, {
"emojiReplied": Qt.binding(() => emojiReaction.emojiTexts),
"isOutgoing": isOutgoing,
"msgId": Id,
"msgBody": Body,
"type": Type,
"transferName": TransferName,
"msgBubble": bubble,
"listView": listView
})
obj.open()
"emojiReactions": emojiReactions,
"isOutgoing": isOutgoing,
"msgId": Id,
"msgBody": Body,
"type": Type,
"transferName": TransferName,
"msgBubble": bubble,
"listView": listView
});
obj.open();
}
}
@ -315,17 +316,11 @@ Control {
anchors.verticalCenter: parent.verticalCenter
anchors.right: isOutgoing ? more.left : 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)
onClicked: {
MessagesAdapter.editId = ""
MessagesAdapter.replyToId = Id
MessagesAdapter.editId = "";
MessagesAdapter.replyToId = Id;
}
}
}
@ -335,21 +330,11 @@ Control {
property bool isEdited: PreviousBodies.length !== 0
visible: !IsEmojiOnly
z:-1
z: -1
out: isOutgoing
type: seq
isReply: root.isReply
function getBaseColor() {
var baseColor = isOutgoing ? CurrentConversation.color : JamiTheme.messageInBgColor
if (Id === MessagesAdapter.replyToId || Id === MessagesAdapter.editId) {
// If we are replying to or editing the message
return Qt.darker(baseColor, 1.5)
}
return baseColor
}
color: getBaseColor()
color: root.getBaseColor()
radius: msgRadius
anchors.right: isOutgoing ? parent.right : undefined
anchors.top: parent.top
@ -358,6 +343,54 @@ Control {
height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0)
}
EmojiReactions {
id: emojiReactions
anchors.top: bubble.bottom
anchors.topMargin: -8
height: contentHeight + 5
reactions: Reactions
borderColor: root.getBaseColor()
maxWidth: 2 / 3 * maxMsgWidth - JamiTheme.emojiMargins
state: root.isOutgoing ? "anchorsRight" : (emojiReactions.width > bubble.width - JamiTheme.emojiMargins ? "anchorsLeft" : "anchorsRight")
TapHandler {
onTapped: {
reactionPopup.open();
}
}
states: [
State {
name: "anchorsRight"
AnchorChanges {
target: emojiReactions
anchors.right: bubble.right
anchors.left: undefined
}
PropertyChanges {
target: emojiReactions
anchors.rightMargin: JamiTheme.emojiMargins
anchors.leftMargin: 0
}
},
State {
name: "anchorsLeft"
AnchorChanges {
target: emojiReactions
anchors.right: undefined
anchors.left: bubble.left
}
PropertyChanges {
target: emojiReactions
anchors.rightMargin: 0
anchors.leftMargin: JamiTheme.emojiMargins
}
}
]
}
Rectangle {
id: bg
@ -412,8 +445,8 @@ Control {
target: CurrentConversation
function onScrollTo(id) {
if (id !== root.id)
return
selectAnimation.start()
return;
selectAnimation.start();
}
}
}
@ -444,10 +477,10 @@ Control {
width: {
if (root.readers.length === 0)
return 0
var nbAvatars = root.readers.length
var margin = JamiTheme.avatarReadReceiptSize / 3
return nbAvatars * JamiTheme.avatarReadReceiptSize - (nbAvatars - 1) * margin
return 0;
var nbAvatars = root.readers.length;
var margin = JamiTheme.avatarReadReceiptSize / 3;
return nbAvatars * JamiTheme.avatarReadReceiptSize - (nbAvatars - 1) * margin;
}
height: JamiTheme.avatarReadReceiptSize
@ -457,25 +490,6 @@ Control {
}
}
EmojiReactions {
id: emojiReaction
property bool isOutgoing: Author === CurrentAccount.uri
Layout.alignment: isOutgoing ? Qt.AlignRight : Qt.AlignLeft
Layout.rightMargin: isOutgoing ? status.width : undefined
Layout.leftMargin: !isOutgoing ? avatarBlock.width : undefined
Layout.topMargin: - contentHeight/4
Layout.preferredHeight: contentHeight + 5
Layout.preferredWidth: contentWidth
emojiReaction: Reactions
TapHandler {
onTapped: {
reactionPopup.open()
}
}
}
ListView {
id: infoCell
@ -483,10 +497,10 @@ Control {
orientation: ListView.Horizontal
Layout.preferredHeight: {
if (showTime || seq === MsgSeq.last)
return contentHeight + timestampItem.contentHeight
return contentHeight + timestampItem.contentHeight;
else if (readsMultiple.visible)
return JamiTheme.avatarReadReceiptSize
return 0
return JamiTheme.avatarReadReceiptSize;
return 0;
}
ReadStatus {
@ -494,14 +508,14 @@ Control {
visible: root.readers.length > 1 && CurrentAccount.sendReadReceipt
width: {
if (root.readers.length === 0)
return 0
var nbAvatars = root.readers.length
var margin = JamiTheme.avatarReadReceiptSize / 3
return nbAvatars * JamiTheme.avatarReadReceiptSize - (nbAvatars - 1) * margin
return 0;
var nbAvatars = root.readers.length;
var margin = JamiTheme.avatarReadReceiptSize / 3;
return nbAvatars * JamiTheme.avatarReadReceiptSize - (nbAvatars - 1) * margin;
}
anchors.right: parent.right
anchors.top : parent.top
anchors.top: parent.top
anchors.topMargin: 1
readers: root.readers
}
@ -511,7 +525,7 @@ Control {
EmojiReactionPopup {
id: reactionPopup
emojiReaction: Reactions
reactions: Reactions
msgId: Id
}
}

View File

@ -0,0 +1,134 @@
/*
* 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

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

View File

@ -32,9 +32,8 @@ Item {
property int spinningAnimationWidth: 4
property real outerCutRadius: root.height / 2
property int spinningAnimationDuration: 1000
property color color: "white"
visible: mode !== SpinningAnimation.Mode.Disabled
ConicalGradient {
id: conicalGradientOne
@ -48,7 +47,7 @@ Item {
}
GradientStop {
position: 1.0
color: "white"
color: mode === SpinningAnimation.Mode.Disabled ? "transparent" : root.color
}
}
@ -90,7 +89,7 @@ Item {
}
GradientStop {
position: 1.0
color: "white"
color: mode === SpinningAnimation.Mode.Disabled ? "transparent" : root.color
}
}

View File

@ -30,15 +30,14 @@ SBSMessageBase {
property bool isRemoteImage
property bool isEmojiOnly: IsEmojiOnly
property real maxMsgWidth: root.width - senderMargin - 2 * hPadding - avatarBlockWidth
property string colorUrl: UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewLinkColorLight : JamiTheme.chatviewLinkColorDark
property string colorText: UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
Connections {
target: bubble
function onColorChanged(color) {
root.colorUrl = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewLinkColorLight : JamiTheme.chatviewLinkColorDark
root.colorText = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
root.colorUrl = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewLinkColorLight : JamiTheme.chatviewLinkColorDark;
root.colorText = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark;
// Update parsed body with correct colors
if (Body !== "")
MessagesAdapter.parseMessage(Id, Body, UtilsAdapter.getAppValue(Settings.DisplayHyperlinkPreviews), root.colorUrl, bubble.color);
@ -65,7 +64,7 @@ SBSMessageBase {
text: {
if (Body !== "" && ParsedBody.length === 0) {
MessagesAdapter.parseMessage(Id, Body, UtilsAdapter.getAppValue(Settings.DisplayHyperlinkPreviews), root.colorUrl, bubble.color);
return ""
return "";
}
return (ParsedBody !== "") ? ParsedBody : "<i>(" + JamiStrings.deletedMessage + ")</i>";
}
@ -86,7 +85,7 @@ SBSMessageBase {
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
selectByMouse: true
font.pixelSize: isEmojiOnly ? JamiTheme.chatviewEmojiSize : JamiTheme.emojiBubbleSize
font.pointSize: isEmojiOnly ? JamiTheme.chatviewEmojiSize : JamiTheme.mediumFontSize
font.hintingPreference: Font.PreferNoHinting
renderType: Text.NativeRendering
textFormat: Text.RichText
@ -277,5 +276,5 @@ SBSMessageBase {
duration: 100
}
}
Component.onCompleted: opacity = 1;
Component.onCompleted: opacity = 1
}

View File

@ -49,8 +49,7 @@ ColumnLayout {
Layout.preferredHeight: childrenRect.height
Layout.fillWidth: true
Layout.topMargin: JamiTheme.dayTimestampTopMargin
Layout.bottomMargin: formattedTimeLabel.visible ? 0 : JamiTheme.dayTimestampBottomMargin
Layout.topMargin: 30
Rectangle {
id: line
@ -95,12 +94,12 @@ ColumnLayout {
id: formattedTimeLabel
text: formattedTime
Layout.bottomMargin: JamiTheme.timestampBottomMargin
Layout.topMargin: JamiTheme.timestampTopMargin
Layout.topMargin: 30
Layout.bottomMargin: 30
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
color: JamiTheme.timestampColor
color: JamiTheme.chatviewSecondaryInformationColor
visible: showTime || showDay
Layout.preferredHeight: visible * implicitHeight
font.pointSize: JamiTheme.timestampFont
font.pointSize: JamiTheme.smallFontSize
}
}

View File

@ -51,6 +51,7 @@ ModalTextEdit {
property bool isActive: false
property string infohash: CurrentAccount.uri
property string accountId: CurrentAccount.id
property string registeredName: CurrentAccount.registeredName
staticText: root.isActive ? registeredName : (registeredName ? registeredName : infohash)
@ -118,7 +119,7 @@ ModalTextEdit {
onTriggered: {
if (dynamicText.length !== 0) {
nameRegistrationState = UsernameTextEdit.NameRegistrationState.SEARCHING;
NameDirectory.lookupName(CurrentAccount.id, dynamicText);
NameDirectory.lookupName(root.accountId, dynamicText);
} else {
nameRegistrationState = UsernameTextEdit.NameRegistrationState.BLANK;
}

View File

@ -55,7 +55,7 @@ Item {
antialiasing: true
anchors.fill: parent
opacity: videoProvider.renderers[rendererId] !== undefined
opacity: videoProvider.activeRenderers[rendererId] === true
visible: opacity
fillMode: crop ? VideoOutput.PreserveAspectCrop : VideoOutput.PreserveAspectFit

View File

@ -20,6 +20,7 @@
pragma Singleton
import QtQuick
import net.jami.Adapters 1.1
import net.jami.Enums 1.1
Item {
property string qmlFilePrefix: "file:/"
@ -69,4 +70,9 @@ Item {
function clamp(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
return new Date() > new Date(Date.parse(UtilsAdapter.getAppValue(Settings.Key.DonateVisibleDate)));
}
}

View File

@ -35,7 +35,6 @@ Item {
property string incomingVideoCallFrom: qsTr("Incoming video call from {}")
property string startSwarm: qsTr("Start swarm")
property string createSwarm: qsTr("Create swarm")
property string showInvitations: qsTr("Show invitations")
property string invitations: qsTr("Invitations")
property string description: qsTr("Jami is a universal communication platform, with privacy as its foundation, that relies on a free distributed network for everyone.")
property string updateToSwarm: qsTr("Migrating to the Swarm technology will enable synchronizing this conversation across multiple devices and improve reliability. The legacy conversation history will be cleared in the process.")
@ -46,13 +45,10 @@ Item {
property string reconnectTry: qsTr("Trying to reconnect to the Jami daemon (jamid)…")
// AboutPopUp
property string version: qsTr("Version") + (UpdateManager.isCurrentVersionBeta() ? " (Beta)" : "")
property string companyDeclarationYear: declarationYear + " " + companyName
property string version: qsTr("Version") + (AppVersionManager.isCurrentVersionBeta() ? " (Beta)" : "")
property string declarationYear: "© 2015-2023"
property string companyName: "Savoir-faire Linux Inc."
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 credits: qsTr("Credits")
// AccountComboBox
property string displayQRCode: qsTr("Display QR code")
@ -84,7 +80,6 @@ Item {
property string autoAnswerCalls: qsTr("Automatically answer calls")
property string enableCustomRingtone: qsTr("Enable custom ringtone")
property string selectCustomRingtone: qsTr("Select custom ringtone")
property string addCustomRingtone: qsTr("Add a custom ringtone")
property string selectNewRingtone: qsTr("Select a new ringtone")
property string certificateFile: qsTr("Certificate File (*.crt)")
property string audioFile: qsTr("Audio File (*.wav *.ogg *.opus *.mp3 *.aiff *.wma)")
@ -100,7 +95,6 @@ Item {
// AdvancedSIPSecuritySettings && AdvancedJamiSecuritySettings
property string security: qsTr("Security")
property string enableSDES: qsTr("Enable SDES key exchange")
property string fallbackRTP: qsTr("Allow fallback on RTP")
property string encryptNegotiation: qsTr("Encrypt negotiation (TLS)")
property string caCertificate: qsTr("CA certificate")
property string userCertificate: qsTr("User certificate")
@ -110,7 +104,6 @@ Item {
property string verifyCertificatesClient: qsTr("Verify server TLS certificates")
property string tlsRequireConnections: qsTr("Require certificate for incoming TLS connections")
property string disableSecureDlgCheck: qsTr("Disable secure dialog check for incoming TLS data")
property string audioDeviceSelector: qsTr("Audio input device selector")
property string selectPrivateKey: qsTr("Select a private key")
property string selectUserCert: qsTr("Select a user certificate")
property string selectCACert: qsTr("Select a CA certificate")
@ -167,7 +160,7 @@ Item {
property string back: qsTr("Back")
property string accountSettingsMenuTitle: qsTr("Account")
property string generalSettingsTitle: qsTr("General")
property string pluginSettingsTitle: qsTr("Plugins")
property string pluginSettingsTitle: qsTr("Extensions")
property string enableAccountSettingsTitle: qsTr("Enable account")
property string manageAccountSettingsTitle: qsTr("Manage account")
property string linkedDevicesSettingsTitle: qsTr("Linked devices")
@ -197,21 +190,17 @@ Item {
property string selectFPS: qsTr("Select video frame rate (frames per second)")
property string enableHWAccel: qsTr("Enable hardware acceleration")
property string mirrorLocalVideo: qsTr("Mirror local video")
property string previewUnavailable: qsTr("Preview unavailable")
property string screenSharing: qsTr("Screen sharing")
property string selectScreenSharingFPS: qsTr("Select screen sharing frame rate (frames per second)")
property string noVideo: qsTr("no video")
// BackupKeyPage
property string whyBackupAccount: qsTr("Why should I back-up this account?")
property string backupAccountInfos: qsTr("Your account only exists on this device. " + "If you lose your device or uninstall the application, " + "your account will be deleted and CANNOT be recovered. " + "You can back up your account now or later (in the Account Settings).")
property string backupAccountInfos: qsTr("Your account only exists on this device. " + "If you lose your device or uninstall the application, " + "your account will be deleted and CANNOT be recovered. " + "You can <a href='blank'> back up your account </a> now or later (in the Account Settings).")
property string backupAccountHere: qsTr("Back up account here")
property string backupAccountBtn: qsTr("Back up account")
property string skip: qsTr("Skip")
property string success: qsTr("Success")
property string error: qsTr("Error")
property string neverShowAgain: qsTr("Never show me this again")
property string recommended: qsTr("Recommended")
property string jamiArchiveFiles: qsTr("Jami archive files (*.gz)")
property string allFiles: qsTr("All files (*)")
@ -223,8 +212,6 @@ Item {
// CallOverlay
property string isRecording: qsTr("is recording")
property string areRecording: qsTr("are recording")
property string peerStoppedRecording: qsTr("Peer stopped recording")
property string isCallingYou: qsTr("is calling you")
property string mute: qsTr("Mute")
property string unmute: qsTr("Unmute")
property string pauseCall: qsTr("Pause call")
@ -267,17 +254,14 @@ Item {
property string confirmBlockConversation: qsTr("Would you really like to block this conversation?")
property string removeContact: qsTr("Remove contact")
property string blockContact: qsTr("Block contact")
property string blockSwarm: qsTr("Block swarm")
property string convDetails: qsTr("Conversation details")
property string contactDetails: qsTr("Contact details")
// CallViewContextMenu
property string hold: qsTr("Hold")
property string sipInputPanel: qsTr("Sip input panel")
property string transferCall: qsTr("Transfer call")
property string stopRec: qsTr("Stop recording")
property string startRec: qsTr("Start recording")
property string exitFullScreen: qsTr("Exit full screen")
property string viewFullScreen: qsTr("View full screen")
property string shareScreen: qsTr("Share screen")
property string shareWindow: qsTr("Share window")
@ -312,10 +296,6 @@ Item {
// Share location/position
property string shareLocation: qsTr("Share location")
property string stopSharingLocation: qsTr("Stop sharing")
property string shortSharing: qsTr("10 minutes")
property string longSharing: qsTr("One hour")
property string minutesLeft: qsTr("%1 minutes left")
property string minuteLeft: qsTr("%1 minute left")
property string locationServicesError: qsTr("Your precise location could not be determined.\nIn Device Settings, please turn on \"Location Services\".\nOther participants' location can still be received.")
property string locationServicesClosedError: qsTr("Your precise location could not be determined. Please check your Internet connection.")
property string stopAllSharings: qsTr("Turn off location sharing")
@ -325,20 +305,22 @@ Item {
property string unpinStopSharingTooltip: qsTr("Pin map to be able to share location or to turn off location in specific conversations")
property string stopSharingSeveralConversationTooltip: qsTr("Location is shared in several conversations, click to choose how to turn off location sharing")
property string shareLocationToolTip: qsTr("Share location to participants of this conversation (%1)")
property string minimizeMapTooltip: qsTr("Minimize")
property string maximizeMapTooltip: qsTr("Maximize")
property string reduceMapTooltip: qsTr("Reduce")
property string extendMapTooltip: qsTr("Extend")
property string dragMapTooltip: qsTr("Drag")
property string centerMapTooltip: qsTr("Center")
property string closeMapTooltip: qsTr("Close")
property string unpin: qsTr("Unpin")
property string pinWindow: qsTr("Pin")
property string positionShareDuration: qsTr("Position share duration")
property string positionShareLimit: qsTr("Limit the duration of location sharing")
property string locationSharingLabel: qsTr("Location sharing")
property string maxLocationDuration: qsTr("Unlimited")
property string minLocationDuration: qsTr("1 min")
property string xhourxmin: qsTr("%1h%2min")
property string xhour: qsTr("%1h")
property string xminxsec: qsTr("%1min%2s")
property string xmin: qsTr("%1min")
property string xsec: qsTr("%sec")
// Chatview header
property string hideChat: qsTr("Hide chat")
@ -367,24 +349,16 @@ Item {
// ConnectToAccountManager
property string enterJAMSURL: qsTr("Enter the Jami Account Management Server (JAMS) URL")
property string required: qsTr("Required")
property string jamiManagementServerURL: qsTr("Jami Account Management Server URL")
property string jamsCredentials: qsTr("Enter JAMS credentials")
property string connect: qsTr("Connect")
property string creatingAccount: qsTr("Creating account…")
property string backToWelcome: qsTr("Back to welcome page")
// CreateAccountPage
property string chooseName: qsTr("Choose name")
property string chooseUsername: qsTr("Choose username")
property string chooseAUsername: qsTr("Choose a username")
property string chooseIdentifier: qsTr("Choose an identifier")
property string identifierNotAvailable: qsTr("The identifier is not available")
property string createPassword: qsTr("Encrypt account with password")
property string createAccount: qsTr("Create account")
property string confirmPassword: qsTr("Confirm password")
property string notePasswordRecovery: qsTr("Choose a password to encrypt your account on this device. Note that the password CANNOT be recovered.")
property string optional: qsTr("Optional")
property string chooseUsernameForAccount: qsTr("You can choose a username to help others more easily find and reach you on Jami.")
property string chooseUsernameForRV: qsTr("Choose a name for your rendezvous point")
property string chooseAName: qsTr("Choose a name")
@ -408,7 +382,6 @@ Item {
property string sipAccount: qsTr("SIP account")
property string proxy: qsTr("Proxy")
property string server: qsTr("Server")
property string createSIPAccount: qsTr("Create SIP account")
property string configureExistingSIP: qsTr("Configure an existing SIP account")
property string personalizeAccount: qsTr("Personalize account")
property string addSip: qsTr("Add SIP account")
@ -419,7 +392,7 @@ Item {
// accountSettingsPages
property string customizeAccountDescription: qsTr("Your profile is only shared with your contacts.\nYour picture and your nickname can be changed at all time in the settings of your account.")
property string usernameAccountDescription: qsTr("A chosen username can help to be found more easily on Jami.\nIf a username is not chosen, a randomly generated 40-character identifier will be assigned to this account as a username. It is more difficult to be found and reached with this identifier.")
property string ecryptAccountDescription: qsTr("Your Jami account is registered only on this device as an archive containing the keys of your account. Access to this archive can be protected by a password.")
property string encryptAccountDescription: qsTr("Your Jami account is registered only on this device as an archive containing the keys of your account. Access to this archive can be protected by a password.")
property string saveAccountTitle: qsTr("Backup account")
property string saveAccountDescription: qsTr("This Jami account exists only on this device.\nThe account will be lost if this device is lost or the application is uninstalled. It is recommended to make a backup of this account.")
property string deleteAccountTitle: qsTr("Delete your account")
@ -427,7 +400,6 @@ Item {
property string linkedAccountList: qsTr("List of the devices that are linked to this account:")
property string linkedThisDevice: qsTr("This device")
property string linkedOtherDevices: qsTr("Other linked devices")
property string linkedAccountDescription: qsTr("Linking this account to other devices enables it to be used on other devices.")
// CurrentAccountSettings && AdvancedSettings
property string backupSuccessful: qsTr("Backup successful")
@ -450,30 +422,28 @@ Item {
property string encryptTitle: qsTr("Encrypt account with a password")
property string encryptDescription: qsTr("A Jami account is created and stored locally only on this device, as an archive containing your account keys. Access to this archive can optionally be protected by a password.")
property string encryptWarning: qsTr("Please note that if you lose your password, it CANNOT be recovered!")
property string enterNickname: qsTr("Enter a nickname, surname...")
property string enterNickname: qsTr("Enter a nickname, surname")
property string linkTitle: qsTr("Use this account on other devices")
property string linkDescription: qsTr("This account is created and stored locally, if you want to use it on another device you have to link the new device to this account.")
property string linkAnotherDevice: qsTr("Link device")
// NameRegistrationDialog
property string setUsername: qsTr("Set username")
property string registeringName: qsTr("Registering name")
// JamiUserIdentity
property string registerAUsername: qsTr("Register a username")
property string registerUsername: qsTr("Register username")
property string identity: qsTr("Identity")
// LinkedDevices
property string tipLinkNewDevice: qsTr("Link a new device to this account")
property string linkAnotherDevice: qsTr("Link a new device")
property string linkNewDevice: qsTr("Exporting account…")
property string linkDevice: qsTr("Exporting account…")
property string removeDevice: qsTr("Remove Device")
property string sureToRemoveDevice: qsTr("Are you sure you wish to remove this device?")
property string yourPinIs: qsTr("Your PIN is:")
property string linkDeviceNetWorkError: qsTr("Error connecting to the network.\nPlease try again later.")
// BannedContacts
property string tipBannedContactsDisplay: qsTr("Display banned contacts")
property string banned: qsTr("Banned")
property string tipBannedContactsHide: qsTr("Hide banned contacts")
property string bannedContacts: qsTr("Banned contacts")
// DeleteAccountDialog
@ -483,6 +453,7 @@ Item {
// DeviceItemDelegate
property string saveNewDeviceName: qsTr("Save")
property string editDeviceName: qsTr("Edit")
property string deviceName: qsTr("Device name:")
property string unlinkDevice: qsTr("Remove")
property string deviceId: qsTr("Device Id")
@ -492,16 +463,12 @@ Item {
property string light: qsTr("Light")
property string selectFolder: qsTr("Select a folder")
property string enableNotifications: qsTr("Enable notifications")
property string applicationTheme: qsTr("Application theme")
property string showNotifications: qsTr("Show notifications")
property string keepMinimized: qsTr("Minimize on close")
property string tipRunStartup: qsTr("Run at system startup")
property string runStartup: qsTr("Launch at startup")
property string downloadFolder: qsTr("Choose download directory")
property string tipChooseDownloadFolder: qsTr("Choose download directory")
property string includeLocalVideo: qsTr("Include local video in recording")
property string textZoom: qsTr("Text zoom")
property string changeTextSize: qsTr("Change text size (%)")
property string defaultSettings: qsTr("Default settings")
// ChatviewSettings
@ -510,7 +477,6 @@ Item {
property string displayHyperlinkPreviews: qsTr("Show link preview in conversations")
property string displayHyperlinkPreviewsDescription: qsTr("Preview requires downloading content from third-party servers.")
property string layout: qsTr("Layout")
property string language: qsTr("User interface language")
property string verticalViewOpt: qsTr("Vertical view")
property string horizontalViewOpt: qsTr("Horizontal view")
@ -530,13 +496,12 @@ Item {
// Context Menu
property string saveFile: qsTr("Save file")
property string openLocation: qsTr("Open location")
property string me: qsTr("Me")
property string removeLocally: qsTr("Delete file from device")
// Updates
property string betaInstall: qsTr("Install beta version")
property string checkForUpdates: qsTr("Check for updates now")
property string enableAutoUpdates: qsTr("Enable/Disable automatic updates")
property string tipAutoUpdate: qsTr("Toggle automatic updates")
property string updatesTitle: qsTr("Updates")
property string updateDialogTitle: qsTr("Update")
property string updateFound: qsTr("A new version of Jami was found\nWould you like to update now?")
@ -548,6 +513,8 @@ Item {
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 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")
//Troubleshoot Settings
@ -559,7 +526,6 @@ Item {
property string experimentalCallSwarmTooltip: qsTr("This feature will enable call buttons in swarms with multiple participants.")
// Recording Settings
property string tipRecordFolder: qsTr("Select a record directory")
property string quality: qsTr("Quality")
property string saveRecordingsTo: qsTr("Save recordings to")
property string saveScreenshotsTo: qsTr("Save screenshots to")
@ -573,27 +539,9 @@ Item {
property string callKeyboardShortcuts: qsTr("Call")
property string settings: qsTr("Settings")
property string markdownKeyboardShortcuts: qsTr("Markdown")
property string openAccountList: qsTr("Open account list")
property string focusConversationsList: qsTr("Focus conversations list")
property string requestsList: qsTr("Requests list")
property string previousConversation: qsTr("Previous conversation")
property string nextConversation: qsTr("Next conversation")
property string searchBar: qsTr("Search bar")
property string fullScreen: qsTr("Full screen")
property string clearHistory: qsTr("Clear history")
property string mediaSettings: qsTr("Media settings")
property string generalSettings: qsTr("General settings")
property string pluginSettings: qsTr("Plugin settings")
property string answerIncoming: qsTr("Answer an incoming call")
property string declineCallRequest: qsTr("Decline the call request")
property string openAccountCreationWizard: qsTr("Open account creation wizard")
property string openKeyboardShortcutTable: qsTr("Open keyboard shortcut table")
// View Logs
property string logsViewTitle: qsTr("Debug")
property string logsViewShowStats: qsTr("Show Stats")
property string logsViewStart: qsTr("Start")
property string logsViewStop: qsTr("Stop")
property string logsViewCopy: qsTr("Copy")
property string logsViewReport: qsTr("Report Bug")
property string logsViewClear: qsTr("Clear")
@ -605,19 +553,14 @@ Item {
property string archive: qsTr("Archive")
property string openFile: qsTr("Open file")
property string importAccountArchive: qsTr("Create account from backup")
property string importAccountExplanation: qsTr("You can obtain an archive by clicking on \"Back up account\" " + "in the Account Settings. " + "This will create a .gz file on your device.")
property string connectFromBackup: qsTr("Restore account from backup")
property string generatingAccount: qsTr("Generating account…")
property string importFromBackup: qsTr("Import from backup")
property string importFromArchiveBackup: qsTr("Import from archive backup")
property string importFromArchiveBackupDescription: qsTr("Import Jami account from local archive file.")
property string selectArchiveFile: qsTr("Select archive file")
property string passwordArchive: qsTr("If the account is encrypted with a password, please fill the following field.")
// ImportFromDevicePage
property string mainAccountPassword: qsTr("Enter Jami account password")
property string enterPIN: qsTr("Enter the PIN from another configured Jami account. " + "Use the \"Link Another Device\" feature to obtain a PIN.")
property string connectFromAnotherDevice: qsTr("Link device")
property string importButton: qsTr("Import")
property string pin: qsTr("Enter the PIN code")
property string importFromDeviceDescription: qsTr("A PIN is required to use an existing Jami account on this device.")
@ -634,62 +577,70 @@ Item {
// LinkDevicesDialog
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 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 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
property string enterPassword: qsTr("Enter the password")
property string enterPassword: qsTr("Enter 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 confirmNewPassword: qsTr("Confirm new password")
property string change: qsTr("Change")
property string confirm: qsTr("Confirm")
property string exportAccount: qsTr("Export")
// PhotoBoothView
property string chooseAvatarImage: qsTr("Choose a picture as your avatar")
property string chooseAvatarPicture: qsTr("Choose a picture")
property string importFromFile: qsTr("Import avatar from image file")
property string stopTakingPhoto: qsTr("Stop taking photo")
property string clearAvatar: qsTr("Clear avatar image")
property string takePhoto: qsTr("Take photo")
property string imageFiles: qsTr("Image Files (*.png *.jpg *.jpeg *.JPG *.JPEG *.PNG)")
// Plugins
property string enable: qsTr("Enable")
property string autoUpdate: qsTr("Auto update")
property string disableAll: qsTr("Disable all")
property string installed: qsTr("Installed")
property string install: qsTr("Install")
property string installing: qsTr("Installing")
property string installManually: qsTr("Install manually")
property string installMannuallyDescription: qsTr("Install an extension directly from your device.")
property string pluginStoreTitle: qsTr("Available")
property string pluginStoreNotAvailable: qsTr("Plugins store is not available")
property string pluginPreferences: qsTr("Preferences")
property string installationFailed: qsTr("Installation failed")
property string pluginInstallationFailed: qsTr("The installation of the plugin failed")
property string reset: qsTr("Reset")
property string uninstall: qsTr("Uninstall")
property string resetPreferences: qsTr("Reset Preferences")
property string selectPluginInstall: qsTr("Select a plugin to install")
property string installPlugin: qsTr("Install plugin")
property string uninstallPlugin: qsTr("Uninstall plugin")
property string pluginResetConfirmation: qsTr("Are you sure you wish to reset %1 preferences?")
property string pluginUninstallConfirmation: qsTr("Are you sure you wish to uninstall %1?")
property string showHidePrefs: qsTr("Display or hide preferences")
property string addNewPlugin: qsTr("Add new plugin")
property string goBackToPluginsList: qsTr("Go back to plugins list")
property string selectFile: qsTr("Select a file")
property string select: qsTr("Select")
property string chooseImageFile: qsTr("Choose image file")
property string tipGeneralPluginSettingsDisplay: qsTr("Display or hide General plugin settings")
property string tipAccountPluginSettingsDisplay: qsTr("Display or hide Account plugin settings")
property string installedPlugins: qsTr("Installed plugins")
property string pluginFiles: qsTr("Plugin Files (*.jpl)")
property string loadUnload: qsTr("Load/Unload")
property string selectAnImage: qsTr("Select An Image to %1")
property string editPreference: qsTr("Edit preference")
property string onOff: qsTr("On/Off")
property string choosePlugin: qsTr("Choose Plugin")
property string versionPlugin: qsTr("Version %1")
property string lastUpdate: qsTr("Last update %1")
property string by: qsTr("By %1")
property string proposedBy: qsTr("Proposed by %1")
// ProfilePage
property string profileSharedWithContacts: qsTr("Profile is only shared with contacts")
property string saveProfile: qsTr("Save profile")
property string enterYourName: qsTr("Enter your name")
property string enterRVName: qsTr("Enter the rendezvous point's name")
property string generatingRV: qsTr("Creating rendezvous point…")
property string information: qsTr("Information")
property string moreInformation: qsTr("More information")
property string profile: qsTr("Profile")
// RevokeDevicePasswordDialog
@ -706,11 +657,7 @@ Item {
// UserProfile
property string qrCode: qsTr("QR code")
// Account QR
property string accountQr: qsTr("Account QR")
// WelcomePage
property string shareInvite: qsTr("This is your Jami username.\nCopy and share it with your friends!")
property string linkFromAnotherDevice: qsTr("Link this device to an existing account")
property string importAccountFromAnotherDevice: qsTr("Import from another device")
property string importAccountFromBackup: qsTr("Import from an archive backup")
@ -722,12 +669,10 @@ Item {
property string addSIPAccount: qsTr("Configure a SIP account")
property string errorCreateAccount: qsTr("Error while creating your account. Check your credentials.")
property string createNewRV: qsTr("Create a rendezvous point")
property string createAJamiAccount: qsTr("Create a Jami account")
property string joinJami: qsTr("Join Jami")
property string createNewJamiAccount: qsTr("Create new Jami account")
property string createNewSipAccount: qsTr("Create new SIP account")
property string aboutJami: qsTr("About Jami")
property string welcomeTo: qsTr("Welcome to")
property string introductionJami: qsTr("Share freely and privately with Jami")
property string alreadyHaveAccount: qsTr("I already have an account")
property string useExistingAccount: qsTr("Use existing Jami account")
@ -736,7 +681,6 @@ Item {
// SmartList
property string clearText: qsTr("Clear Text")
property string conversations: qsTr("Conversations")
property string conversation: qsTr("Conversation")
property string searchResults: qsTr("Search Results")
// SmartList context menu
@ -768,7 +712,6 @@ Item {
property string localMuted: qsTr("Local muted")
// Settings moderation
property string conferenceModeration: qsTr("Conference moderation")
property string defaultModerators: qsTr("Default moderators")
property string enableLocalModerators: qsTr("Enable local moderators")
property string enableAllModerators: qsTr("Make all participants moderators")
@ -780,34 +723,32 @@ Item {
property string reconnectDaemon: qsTr("Trying to reconnect to the Jami daemon (jamid)…")
property string reconnectionFailed: qsTr("Could not re-connect to the Jami daemon (jamid).\nJami will now quit.")
// Is Swarm
property string isSwarm: qsTr("Is swarm:")
property string trueStr: qsTr("True")
property string falseStr: qsTr("False")
// Message view
property string addEmoji: qsTr("Add emoji")
property string moreEmojis: qsTr("more emojis")
property string sendFile: qsTr("Send file")
property string leaveAudioMessage: qsTr("Leave audio message")
property string leaveVideoMessage: qsTr("Leave video message")
property string leaveAudioMessage: qsTr("Audio message")
property string leaveVideoMessage: qsTr("Video message")
property string showMore: qsTr("Show more")
property string showLess: qsTr("Show less")
property string showPreview: qsTr("Show preview")
property string continueEditing: qsTr("Continue editing")
property string bold: qsTr("Bold")
property string italic: qsTr("Italic")
property string strikethrough: qsTr("Strikethrough")
property string title: qsTr("Title")
property string heading: qsTr("Heading")
property string link: qsTr("Link")
property string code: qsTr("Code")
property string quote: qsTr("Quote")
property string unorderedList: qsTr("Unordered list")
property string orderedList: qsTr("Ordered list")
property string showFormating: qsTr("Show Formating")
property string hideFormating: qsTr("Hide Formating")
property string showFormatting: qsTr("Show formatting")
property string hideFormatting: qsTr("Hide formatting")
property string shiftEnterNewLine: qsTr("Press Shift+Enter to insert a new line")
property string enterNewLine: qsTr("Press Enter to insert a new line")
property string send: qsTr("Send")
property string remove: qsTr("Remove")
property string replyTo: qsTr("Reply to")
property string inReplyTo: qsTr("In reply to")
property string repliedTo: qsTr(" replied to")
@ -833,10 +774,8 @@ Item {
property string invitationViewWaitingForSync: qsTr("Waiting until %1\nconnects to synchronize the conversation.")
// SwarmDetailsPanel
property string about: qsTr("About")
property string members: qsTr("%1 Members")
property string member: qsTr("Member")
property string documents: qsTr("Documents")
property string swarmName: qsTr("Swarm's name")
property string contactName: qsTr("Contact's name")
property string addADescription: qsTr("Add a description")
@ -846,14 +785,12 @@ Item {
property string chooseAColor: qsTr("Choose a color")
property string defaultCallHost: qsTr("Default host (calls)")
property string leaveConversation: qsTr("Leave conversation")
property string leave: qsTr("Leave")
property string typeOfSwarm: qsTr("Type of swarm")
property string none: qsTr("None")
// NewSwarmPage
property string createTheSwarm: qsTr("Create the swarm")
property string goToConversation: qsTr("Go to conversation")
property string promoteAdministrator: qsTr("Promote to administrator")
property string kickMember: qsTr("Kick member")
property string reinstateMember: qsTr("Reinstate member")
property string administrator: qsTr("Administrator")
@ -866,9 +803,7 @@ Item {
property string tip: qsTr("Tip")
property string dismiss: qsTr("Dismiss")
property string customizeText: qsTr("Add a profile picture and nickname to complete your profile")
property string customizationDescription: qsTr("This profile is only shared with this account's contacts")
property string customizationDescription2: qsTr("Your profile is only shared with your contacts")
property string whySaveAccount: qsTr("Why should I save my account?")
property string customizationDescription: qsTr("Your profile is only shared with your contacts")
// Message options
property string deleteMessage: qsTr("Delete message")
@ -876,8 +811,7 @@ Item {
property string editMessage: qsTr("Edit message")
// Jami identifier
property string identifierDescription: qsTr("Share this Jami identifier to be contacted on this account!")
property string hereIsIdentifier: qsTr("Here is your Jami identifier, don't hesitate to share it in order to be contacted more easily!")
property string hereIsIdentifier: qsTr("Share your Jami identifier in order to be contacted more easily!")
property string jamiIdentity: qsTr("Jami identity")
property string identifierURI: qsTr("Show fingerprint")
property string identifierRegisterName: qsTr("Show registered name")
@ -903,4 +837,9 @@ Item {
// Appearence
property string theme: qsTr("Theme")
property string zoomLevel: qsTr("Text zoom level")
//Donation campaign
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")
}

View File

@ -58,9 +58,13 @@ Item {
property color blackColor: "#000000"
property color redColor: "red"
property color whiteColor: "#ffffff"
property color darkBlueGreen: "#123F4A"
property color darkGreyColor: "#272727"
property color darkGreyColorOpacityFade: "#cc000000" // 80%
property color darkGreyColorOpacity: "#be272727" // 77%
property color tintedBlue: darkTheme ? "#03B9E9" : "#005699"
property color tintedBlue: darkTheme ? lightTintedBlue : darkTintedBlue
property color lightTintedBlue: "#03B9E9"
property color darkTintedBlue: "#005699"
property color sysColor: "#F0EFEF"
property color transparentColor: "transparent"
@ -72,11 +76,11 @@ Item {
property color greyBorderColor: "#333"
property color selectionBlue: darkTheme ? "#0061a5" : "#109ede"
property color hoverColor: darkTheme ? "#515151" : "#c7c7c7"
property color hoverColor: darkTheme ? "#4d4d4d" : "#c7c7c7"
property color pressColor: darkTheme ? "#777" : "#c0c0c0"
property color selectedColor: darkTheme ? "#0e81c5" : "#e0e0e0"
property color smartListHoveredColor: darkTheme ? "#444444" : "#dedede"
property color smartListSelectedColor: darkTheme ? "#515151" : "#d1d1d1"
property color smartListHoveredColor: darkTheme ? "#4d4d4d" : "#dedede"
property color smartListSelectedColor: darkTheme ? "#4d4d4d" : "#dedede"
property color editBackgroundColor: darkTheme ? "#373737" : lightGrey_
property color textColor: primaryForegroundColor
property color textColorHovered: darkTheme ? "#cccccc" : "#333333"
@ -96,8 +100,8 @@ Item {
// General buttons
property color pressedButtonColor: darkTheme ? pressColor : "#a0a0a0"
property color hoveredButtonColor: darkTheme ? hoverColor : "#c7c7c7"
property color hoveredButtonColorWizard: darkTheme ? "#123F4A" : "#E5EEF5"
property color hoveredButtonColor: darkTheme ? "#4d4d4d" : "#dedede"
property color hoveredButtonColorWizard: darkTheme ? "#4d4d4d" : "#dedede"
property color normalButtonColor: darkTheme ? backgroundColor : "#e0e0e0"
property color invertedPressedButtonColor: Qt.rgba(0, 0, 0, 0.5)
@ -209,16 +213,17 @@ Item {
property color chatviewLinkColorDark: "#353637"
property real chatviewFontSize: calcSize(15)
property real chatviewEmojiSize: calcSize(60)
property color timestampColor: darkTheme ? "#bbb" : "#777"
property color timestampColor: darkTheme ? "#515151" : "#E5E5E5"
property color messageReplyColor: darkTheme ? "#bbb" : "#A7A7A7"
property color messageOutTxtColor: "#000000"
property color messageInBgColor: "#e5e5e5"
property color messageInBgColor: darkTheme ? "#303030" : "#dbdbdb"
property color messageOutBgColor: darkTheme ? "#616161" : "#005699"
property color messageInTxtColor: "#FFFFFF"
property color fileOutTimestampColor: darkTheme ? "#eee" : "#555"
property color fileInTimestampColor: darkTheme ? "#999" : "#555"
property color chatviewBgColor: darkTheme ? bgDarkMode_ : whiteColor
property color bgInvitationRectColor: darkTheme ? "#222222" : whiteColor
property color messageBarPlaceholderTextColor: darkTheme ? "#909090" : "#7e7e7e"
property color placeholderTextColor: darkTheme ? "#7a7a7a" : "black" //Qt.rgba(0, 0, 0, 0.2)
property color placeholderTextColorWhite: "#cccccc"
property color inviteHoverColor: darkTheme ? blackColor : whiteColor
@ -229,15 +234,23 @@ Item {
property color previewCardContainerColor: darkTheme ? blackColor : whiteColor
property color previewUrlColor: darkTheme ? "#eeeeee" : "#333"
property color messageWebViewFooterButtonImageColor: darkTheme ? "#838383" : "#656565"
property color chatviewUsernameColor: "#A7A7A7"
property color chatviewSecondaryInformationColor: "#A7A7A7"
// ChatView Footer
property color chatViewFooterListColor: darkTheme ? blackColor : "#E5E5E5"
property color chatViewFooterImgColor: darkTheme ? whiteColor : blackColor
property color showMoreButtonOpenColor: darkTheme ? "#123F4A" : "#CCCCCC"
property color chatViewFooterImgHoverColor: darkTheme ? whiteColor : blackColor
property color chatViewFooterImgColor: darkTheme ? "#909090" : "#7e7e7e"
property color chatViewFooterImgDisableColor: darkTheme ? "#4d4d4d" : "#cbcbcb"
property color showMoreButtonOpenColor: darkTheme ? "#4d4d4d" : "#e5e5e5"
property color chatViewFooterSeparateLineColor: darkTheme ? "#5c5c5c" : "#929292"
property color chatViewFooterSendButtonColor: darkTheme ? "#03B9E9" : "#005699"
property color chatViewFooterSendButtonDisableColor: darkTheme ? "#191a1c" : "#f0f0f1"
property color chatViewFooterSendButtonImgColor: darkTheme ? blackColor : whiteColor
property color chatViewFooterSendButtonImgColorDisable: darkTheme ? "#4d4d4d" : "#cbcbcb"
property color chatViewFooterRectangleBorderColor: darkTheme ? "#4d4d4d" : "#e5e5e5"
// ChatView Header
property real chatViewHeaderButtonRadius: 5
// mapPosition
property color mapButtonsOverlayColor: darkTheme ? "#000000" : "#f0f0f0"
@ -254,12 +267,13 @@ Item {
property real namePopupFontsize: calcSize(15)
property real avatarSize: 30
property int emojiPushButtonSize: 30
property int emojiMargins: 20
property int emojiMargins: 16
property color emojiReactBubbleBgColor: darkTheme ? darkGreyColor : whiteColor
property color emojiReactPushButtonColor: darkTheme ? "#bbb" : "#003b4e"
property real messageOptionTextFontSize: calcSize(15)
property int emojiPickerWidth: 400
property int emojiPickerHeight: 425
property int defaulMaxWidthReaction: 350
// Files To Send Container
property color removeFileButtonColor: Qt.rgba(96, 95, 97, 0.5)
@ -296,18 +310,20 @@ Item {
// Sizes
property real mainViewLeftPaneMinWidth: 300
property real mainViewPaneMinWidth: 430
property real currentLeftPaneWidth: mainViewLeftPaneMinWidth
property real mainViewPaneMinWidth: 490
property real qrCodeImageSize: 256
property real splitViewHandlePreferredWidth: 4
property real indicatorFontSize: calcSize(6)
property real tinyFontSize: calcSize(7 + fontSizeOffset)
property real textFontSize: calcSize(9 + fontSizeOffset)
property real smallFontSize: calcSize(9 + fontSizeOffsetSmall)
property real mediumFontSize: calcSize(10.5 + fontSizeOffset)
property real bigFontSize: calcSize(22)
property real settingsFontSize: calcSize(11 + fontSizeOffset)
property real buttonFontSize: calcSize(9)
property real materialButtonPreferredHeight: calcSize(36)
property real participantFontSize: calcSize(10 + fontSizeOffset)
property real participantSwarmDetailFontSize: calcSize(15 + fontSizeOffset)
property real menuFontSize: calcSize(12 + fontSizeOffset)
property real headerFontSize: calcSize(14.25 + fontSizeOffset)
property real titleFontSize: calcSize(16 + fontSizeOffset)
@ -315,9 +331,7 @@ Item {
property real tinyCreditsTextSize: calcSize(13 + fontSizeOffset)
property real creditsTextSize: calcSize(15 + fontSizeOffset)
property real primaryRadius: calcSize(4)
property real smartlistItemFontSize: calcSize(10.5 + fontSizeOffset)
property real smartlistItemInfoFontSize: calcSize(9 + fontSizeOffsetSmall)
property real filterItemFontSize: calcSize(smartlistItemFontSize)
property real filterItemFontSize: calcSize(mediumFontSize)
property real filterBadgeFontSize: calcSize(8.25)
property real editedFontSize: calcSize(8)
property real accountListItemHeight: 64
@ -373,6 +387,15 @@ Item {
property real minimumMapWidth: 250
property real pluginHandlersPopupViewHeight: 200
property real pluginHandlersPopupViewDelegateHeight: 50
property color pluginDefaultBackgroundColor: "#666666"
property real remotePluginMinimumDelegateWidth: 430
property real remotePluginMinimumDelegateHeight: 275
property real remotePluginMaximumDelegateWidth: 645
property real remotePluginMaximumDelegateHeight: 413
property real iconMargin: 30 * baseZoom
property real remotePluginDelegateWidth: remotePluginMinimumDelegateWidth * baseZoom
property real remotePluginDelegateHeight: remotePluginMinimumDelegateHeight * baseZoom
property color pluginViewBackgroundColor: darkTheme ? "#000000" : "#F0EFEF"
property real secondaryDialogDimension: 500
property real lineEditContextMenuItemsHeight: 15
@ -385,10 +408,6 @@ Item {
// TimestampInfo
property int timestampLinePadding: 40
property int dayTimestampTopMargin: 8
property int dayTimestampBottomMargin: 8
property int timestampBottomMargin: 16
property int timestampTopMargin: 16
property int dayTimestampHPadding: 16
property real dayTimestampVPadding: 32
property real timestampFont: calcSize(12)
@ -420,7 +439,7 @@ Item {
// Jami Identifier
property color mainColor: "#005699"
property real pushButtonSize: 22
property real pushButtonMargin: 10
property real pushButtonMargins: 10
// Modal Popup
property real modalPopupRadius: 20
@ -435,14 +454,14 @@ Item {
property real chatViewHairLineSize: 1
property real chatViewMaximumWidth: 900
property real chatViewHeaderPreferredHeight: 64
property real chatViewFooterPreferredHeight: 50
property real chatViewFooterMaximumHeight: 280
property real chatViewFooterPreferredHeight: 35
property real chatViewFooterMaximumHeight: 315
property real chatViewFooterRowSpacing: 4
property real chatViewFooterButtonSize: 36
property real chatViewFooterRealButtonSize: 26
property real chatViewFooterButtonIconSize: 48
property real chatViewFooterButtonRadius: 5
property real chatViewFooterTextAreaMaximumHeight: 130
property real chatViewFooterTextAreaMaximumHeight: 260
property real chatViewScrollToBottomButtonBottomMargin: 8
property real usernameBlockFontSize: calcSize(12)
@ -485,13 +504,11 @@ Item {
property real jamiIdMargins: 36
property real jamiIdLogoWidth: 70
property real jamiIdLogoHeight: 24
property real jamiIdFontSize: calcSize(13)
property real jamiIdFontSize: calcSize(19)
property real jamiIdSmallFontSize: calcSize(11)
property color jamiIdColor: darkTheme ? blackColor : sysColor
// MainView
property color welcomeViewBackgroundColor: darkTheme ? lightGrey_ : secondaryBackgroundColor
property real welcomeRectSideMargins: 45
property real welcomeRectTopMargin: 90
property color rectColor: darkTheme ? blackColor : "#e5eef5"
property color welcomeText: darkTheme ? "#0071c9" : "#002B4A"
property real illustrationWidth: 212
@ -519,6 +536,15 @@ Item {
property real welcomeLogoHeight: 100
property real wizardButtonWidth: 400
property real wizardButtonHeightMargin: 31
property color welcomeViewBackgroundColor: darkTheme ? lightGrey_ : secondaryBackgroundColor
property real welcomeRectSideMargins: 45
property real welcomeRectTopMargin: 90
property real welcomePageSpacing: 13
property real welcomeGridWidth: 3 * JamiTheme.tipBoxWidth + 2 * JamiTheme.welcomePageSpacing
property real welcomeHalfGridWidth: (welcomeGridWidth - JamiTheme.welcomePageSpacing) / 2
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
property color welcomeBlockColor: darkTheme ? "#4D000000" : "#4DFFFFFF"
// WizardView Advanced Account Settings
property color lightBlue_: darkTheme ? "#03B9E9" : "#e5eef5"
@ -540,6 +566,7 @@ Item {
property real infoBoxDescFontSize: calcSize(12)
// Tipbox
property real tipBoxWidth: 200
property real tipBoxTitleFontSize: calcSize(13)
property real tipBoxContentFontSize: calcSize(12)
property color tipBoxBackgroundColor: darkTheme ? blackColor : whiteColor
@ -583,7 +610,7 @@ Item {
property int keyboardShortcutDelegateSize: 50
// Main application spec
property real mainViewMinWidth: 430
property real mainViewMinWidth: 490
property real mainViewMinHeight: 500
property real wizardViewMinWidth: 500
@ -592,7 +619,7 @@ Item {
property real mainViewPreferredWidth: 730
property real mainViewPreferredHeight: 600
property real mainViewMargin: 30
property real mainViewMargin: 25
// Extras panel
property real extrasPanelMinWidth: 300
@ -610,15 +637,18 @@ Item {
property int settingsDescriptionPixelSize: calcSize(15)
property int settingsCategorySpacing: 15
property int settingsCategoryAudioVideoSpacing: 6
property int settingsBoxRadius: 10
property int settingsBoxRadius: 5
property int settingsBlockSpacing: 40
property int settingsMenuChildrenButtonHeight: 30
property int settingsMenuHeaderButtonHeight: 50
property int settingsListViewsSpacing: 10
// Link Device
property color pinBackgroundColor: "#D6E4EF"
// MaterialRadioButton
property int radioImageSize: 30
property color radioBackgroundColor: darkTheme ? "#515151" : "#F0EFEF"
property color radioBackgroundColor: darkTheme ? "#303030" : "#F0EFEF"
property color radioBorderColor: darkTheme ? "#03B9E9" : "#005699"
property color lightThemeBackgroundColor: JamiTheme.whiteColor
property color lightThemeCheckedColor: "#005699"
@ -627,6 +657,11 @@ Item {
property color darkThemeCheckedColor: "#03B9E9"
property color darkThemeBorderColor: "#03B9E9"
// Donation campaign
property color donationButtonTextColor: "#005699"
property color donationBackgroundColor: "#D5E4EF"
property string donationUrl: "https://jami.net/donate/"
function setTheme(dark) {
darkTheme = dark;
}

View File

@ -93,6 +93,7 @@ bool
ConversationListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
auto rx = filterRegularExpression();
auto uriStripper = URI(rx.pattern());
bool stripScheme = (uriStripper.schemeType() < URI::SchemeType::COUNT__);
@ -104,6 +105,11 @@ ConversationListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s
rx.setPattern(uriStripper.format(flags));
using namespace ConversationList;
if (index.data(Role::Uris).toStringList().isEmpty()) {
// TODO: Find out why, and fix in libjami/libjamiclient.
qCritical() << "Filtering 0 member conversation. Fix me";
return false;
}
QStringList toFilter;
toFilter += index.data(Role::Title).toString();

View File

@ -22,6 +22,9 @@
#include "qtutils.h"
#include "systemtray.h"
#include "qmlregister.h"
#include "qtutils.h"
#include "namedirectory.h"
#include <QApplication>
#include <QJsonObject>
@ -232,21 +235,37 @@ ConversationsAdapter::onNewTrustRequest(const QString& accountId,
if (convInfo.uid.isEmpty())
return;
}
auto& accInfo = lrcInstance_->getAccountInfo(accountId);
auto from = accInfo.contactModel->bestNameForContact(peerUri);
auto to = lrcInstance_->accountModel().bestNameForAccount(accountId);
auto preferences = accInfo.conversationModel->getConversationPreferences(convId);
// Ignore notifications for this conversation
if (preferences["ignoreNotifications"] == "true")
return;
auto contactPhoto = Utils::contactPhoto(lrcInstance_, peerUri, QSize(50, 50), accountId);
auto notifId = QString("%1;%2").arg(accountId, conv);
systemTray_->showNotification(notifId,
tr("%1 received a new trust request").arg(to),
"New request from " + from,
SystemTray::NotificationType::REQUEST,
Utils::QImageToByteArray(contactPhoto));
auto cb = [this, to, accountId, conv, peerUri](QString peerBestName) {
auto contactPhoto = Utils::contactPhoto(lrcInstance_, peerUri, QSize(50, 50), accountId);
auto notifId = QString("%1;%2").arg(accountId, conv);
systemTray_->showNotification(notifId,
tr("%1 received a new trust request").arg(to),
"New request from " + peerBestName,
SystemTray::NotificationType::REQUEST,
Utils::QImageToByteArray(contactPhoto));
};
// This peer is not yet a contact, so we don't have a name for it,
// but we can attempt to look it up using the name service before
// falling back to the bestNameForContact.
Utils::oneShotConnect(&NameDirectory::instance(),
&NameDirectory::registeredNameFound,
this,
[this, accountId, peerUri, cb](NameDirectory::LookupStatus status,
const QString& address,
const QString& name) {
if (address == peerUri) {
if (status == NameDirectory::LookupStatus::SUCCESS)
cb(name);
else {
auto& accInfo = lrcInstance_->getAccountInfo(accountId);
cb(accInfo.contactModel->bestNameForContact(peerUri));
}
}
});
std::ignore = NameDirectory::instance().lookupAddress(accountId, peerUri);
}
#else
Q_UNUSED(accountId)

View File

@ -179,7 +179,6 @@ CurrentAccount::updateData()
// SRTP
set_enableSRTP(accConfig.SRTP.enable, true);
set_rtpFallbackSRTP(accConfig.SRTP.rtpFallback, true);
set_keyExchangeSRTP(accConfig.SRTP.keyExchange, true);
// TURN
@ -222,6 +221,9 @@ CurrentAccount::updateData()
set_autoTransferSizeThreshold(settingsManager_->getValue(Settings::Key::AcceptTransferBelow)
.toInt(),
true);
// UI Customization settings
set_uiCustomization(accConfig.uiCustomization, true);
} catch (...) {
qWarning() << "Can't update current account info data for" << id_;
}

View File

@ -160,7 +160,6 @@ class CurrentAccount final : public QObject
// SRTP settings
QML_ACCOUNT_CONFIG_CATEGORY_SETTINGS_PROPERTY(bool, enable, SRTP)
QML_ACCOUNT_CONFIG_CATEGORY_SETTINGS_PROPERTY(bool, rtpFallback, SRTP)
QML_ACCOUNT_CONFIG_CATEGORY_SETTINGS_PROPERTY(lrc::api::account::KeyExchangeProtocol,
keyExchange,
SRTP)
@ -191,6 +190,9 @@ class CurrentAccount final : public QObject
QML_NEW_ACCOUNT_MODEL_SETTINGS_PROPERTY(bool, autoTransferFromTrusted, AutoAcceptFiles)
QML_NEW_ACCOUNT_MODEL_SETTINGS_PROPERTY(int, autoTransferSizeThreshold, AcceptTransferBelow)
// UI Customization settings
QML_ACCOUNT_CONFIG_SETTINGS_PROPERTY(QJsonObject, uiCustomization)
public:
explicit CurrentAccount(LRCInstance* lrcInstance,
AppSettingsManager* settingsManager,

View File

@ -125,6 +125,8 @@ CurrentAccountToMigrate::slotAccountStatusChanged(const QString& accountId)
void
CurrentAccountToMigrate::slotAccountRemoved(const QString& accountId)
{
if (accountToMigrateList_.isEmpty() || accountToMigrateList_.indexOf(accountId) < 0)
return;
if (accountToMigrateList_.removeOne(accountId))
updateData();
if (accountToMigrateList_.isEmpty())

View File

@ -43,6 +43,13 @@ CurrentCall::CurrentCall(LRCInstance* lrcInstance, QObject* parent)
this,
&CurrentCall::onShowIncomingCallView);
try {
auto& accInfo = lrcInstance_->getCurrentAccountInfo();
set_isSIP(accInfo.profileInfo.type == profile::Type::SIP);
} catch (const std::exception& e) {
qWarning() << "Can't update current call type" << e.what();
}
connectModel();
}

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