- Send multiple files in one message, with preview.
- Message preview manage huge heights. - Chat design rework. - Sort timelines by unread chat rooms. - Fix thumbnails that weren't deleted. - Play audio record on playback device instead of ringer device. - Fix binding loops on scrollable areas. - Change timeline filter to a minimal version. - Fix record button hovering. - Fix camera button in fullscreen.
|
|
@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Added
|
||||
- Features:
|
||||
* Messages features : Reply, forward (to contact, to a SIP address or to a timeline), Vocal record and play, multi contents.
|
||||
* Messages features : Reply, forward (to contact, to a SIP address or to a timeline), Vocal record and play, multi contents, preview.
|
||||
- Add a feedback on fetching remote provisioning when it failed.
|
||||
- Option to enable message notifications.
|
||||
- CPIM on basic chat rooms.
|
||||
|
|
@ -18,7 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Based on Linphone SDK 5.1
|
||||
|
||||
### Fixed
|
||||
- Simplify filtering timelines on 3 kind of search : security level, simple/group chats, ephemerals.
|
||||
- Simplify filtering timelines with 2 modes (minimal or exhaustive) and on 3 kind of search : security level, simple/group chats, ephemerals.
|
||||
- Sort timelines by taken account of unread events in chat rooms.
|
||||
- Fix systemTrayIcon that could be cloned on each restart.
|
||||
- Fix errors on Action-Buttons on restart.
|
||||
- Enable G729 on public builds.
|
||||
|
|
@ -27,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Adapt UserAgent with device name.
|
||||
- Video freeze on network change.
|
||||
- Set default log size to 50MB
|
||||
- Crash on the smart search bar.
|
||||
|
||||
## 4.3.2
|
||||
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ set(SOURCES
|
|||
src/components/calls/CallsListProxyModel.cpp
|
||||
src/components/camera/Camera.cpp
|
||||
src/components/camera/CameraPreview.cpp
|
||||
src/components/chat/ChatModel.cpp
|
||||
src/components/chat-events/ChatCallModel.cpp
|
||||
src/components/chat-events/ChatEvent.cpp
|
||||
src/components/chat-events/ChatMessageModel.cpp
|
||||
|
|
@ -238,6 +239,7 @@ set(HEADERS
|
|||
src/components/calls/CallsListProxyModel.hpp
|
||||
src/components/camera/Camera.hpp
|
||||
src/components/camera/CameraPreview.hpp
|
||||
src/components/chat/ChatModel.hpp
|
||||
src/components/chat-events/ChatCallModel.hpp
|
||||
src/components/chat-events/ChatEvent.hpp
|
||||
src/components/chat-events/ChatMessageModel.hpp
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
viewBox="0 0 80 80"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="chat_audio_pause.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
sodipodi:docname="chat_audio_pause_custom.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -22,26 +22,17 @@
|
|||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="5.3231707"
|
||||
inkscape:cx="28.460481"
|
||||
inkscape:cy="64.623139"
|
||||
inkscape:zoom="7.5281002"
|
||||
inkscape:cx="28.493245"
|
||||
inkscape:cy="43.304418"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
id="g6"
|
||||
transform="scale(0.96277665,0.97560976)">
|
||||
<g
|
||||
fill="#444444"
|
||||
id="g4">
|
||||
<path
|
||||
d="m 41.547,0 c 22.945,0 41.546,18.356 41.546,41 0,22.644 -18.6,41 -41.546,41 C 18.6,82 0,63.644 0,41 0,18.356 18.601,0 41.547,0 Z M 30.04,21.5 c -1.933,0 -3.5,1.567 -3.5,3.5 v 32 l 0.005,0.192 c 0.1,1.844 1.626,3.308 3.495,3.308 1.933,0 3.5,-1.567 3.5,-3.5 V 25 L 33.535,24.808 C 33.435,22.964 31.909,21.5 30.04,21.5 Z m 21,0 c -1.933,0 -3.5,1.567 -3.5,3.5 v 32 l 0.005,0.192 c 0.1,1.844 1.626,3.308 3.495,3.308 1.933,0 3.5,-1.567 3.5,-3.5 V 25 L 54.535,24.808 C 54.435,22.964 52.909,21.5 51.04,21.5 Z"
|
||||
id="path2" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
d="m 28.078632,24.714815 v 30.46462 M 49.08815,24.714815 v 30.46462"
|
||||
id="path823"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:8.94461;stroke-linecap:round;stroke-linejoin:round" />
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.2 KiB |
|
|
@ -4,44 +4,51 @@
|
|||
height="80"
|
||||
viewBox="0 0 80 80"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="chat_audio_play.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
id="svg14"
|
||||
sodipodi:docname="chat_audio_play_custom.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs12" />
|
||||
id="defs18" />
|
||||
<sodipodi:namedview
|
||||
id="namedview10"
|
||||
id="namedview16"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
showgrid="false"
|
||||
inkscape:zoom="5.3231707"
|
||||
inkscape:cx="29.024055"
|
||||
inkscape:cy="63.683849"
|
||||
inkscape:zoom="6.5078125"
|
||||
inkscape:cx="7.7599039"
|
||||
inkscape:cy="15.827131"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
inkscape:current-layer="g8" />
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
id="g6"
|
||||
transform="scale(0.96277665,0.97560976)">
|
||||
id="g12">
|
||||
<g
|
||||
fill="#444444"
|
||||
id="g4">
|
||||
<path
|
||||
d="m 41.547,0 c 22.945,0 41.546,18.356 41.546,41 0,22.644 -18.6,41 -41.546,41 C 18.6,82 0,63.644 0,41 0,18.356 18.601,0 41.547,0 Z M 29.975,20.97 V 59.812 L 61.75,41.12 Z"
|
||||
id="path2" />
|
||||
id="g10">
|
||||
<g
|
||||
id="g8">
|
||||
<g
|
||||
transform="scale(4.9340074,5)"
|
||||
id="g6">
|
||||
<path
|
||||
fill="#000000"
|
||||
fill-rule="nonzero"
|
||||
d="m 5.849,4.092 v 7.579 l 6.2,-3.648 z"
|
||||
id="path4" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="80"
|
||||
height="80"
|
||||
viewBox="0 0 80 80"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="chat_audio_pause.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs12" />
|
||||
<sodipodi:namedview
|
||||
id="namedview10"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="5.3231707"
|
||||
inkscape:cx="28.460481"
|
||||
inkscape:cy="64.623139"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
id="g6"
|
||||
transform="scale(0.96277665,0.97560976)">
|
||||
<g
|
||||
fill="#444444"
|
||||
id="g4">
|
||||
<path
|
||||
d="m 41.547,0 c 22.945,0 41.546,18.356 41.546,41 0,22.644 -18.6,41 -41.546,41 C 18.6,82 0,63.644 0,41 0,18.356 18.601,0 41.547,0 Z M 30.04,21.5 c -1.933,0 -3.5,1.567 -3.5,3.5 v 32 l 0.005,0.192 c 0.1,1.844 1.626,3.308 3.495,3.308 1.933,0 3.5,-1.567 3.5,-3.5 V 25 L 33.535,24.808 C 33.435,22.964 31.909,21.5 30.04,21.5 Z m 21,0 c -1.933,0 -3.5,1.567 -3.5,3.5 v 32 l 0.005,0.192 c 0.1,1.844 1.626,3.308 3.495,3.308 1.933,0 3.5,-1.567 3.5,-3.5 V 25 L 54.535,24.808 C 54.435,22.964 52.909,21.5 51.04,21.5 Z"
|
||||
id="path2" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="80"
|
||||
height="80"
|
||||
viewBox="0 0 80 80"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="chat_audio_play.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs12" />
|
||||
<sodipodi:namedview
|
||||
id="namedview10"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="5.3231707"
|
||||
inkscape:cx="29.024055"
|
||||
inkscape:cy="63.683849"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
id="g6"
|
||||
transform="scale(0.96277665,0.97560976)">
|
||||
<g
|
||||
fill="#444444"
|
||||
id="g4">
|
||||
<path
|
||||
d="m 41.547,0 c 22.945,0 41.546,18.356 41.546,41 0,22.644 -18.6,41 -41.546,41 C 18.6,82 0,63.644 0,41 0,18.356 18.601,0 41.547,0 Z M 29.975,20.97 V 59.812 L 61.75,41.12 Z"
|
||||
id="path2" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
|
@ -1,12 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="500"
|
||||
width="60"
|
||||
height="60"
|
||||
viewBox="0 0 500 60"
|
||||
viewBox="0 0 60 60"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="chat_audio_soundwave_custom.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -22,27 +22,29 @@
|
|||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.2704082"
|
||||
inkscape:cx="250.70682"
|
||||
inkscape:cy="-59.036143"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
inkscape:zoom="2.5408164"
|
||||
inkscape:cx="-1.37751"
|
||||
inkscape:cy="35.421686"
|
||||
inkscape:window-width="1458"
|
||||
inkscape:window-height="749"
|
||||
inkscape:window-x="146"
|
||||
inkscape:window-y="99"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg8"
|
||||
showguides="false" />
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
id="g6"
|
||||
transform="matrix(1.0204082,0,0,0.66666667,0,10)">
|
||||
transform="matrix(0.5,0,0,0.66666667,0,10)">
|
||||
<g
|
||||
fill="#444444"
|
||||
fill-rule="nonzero"
|
||||
id="g4">
|
||||
<path
|
||||
d="m 65,0 c 2.761,0 5,2.239 5,5 v 50 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 5 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 50 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 5 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 50 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 5 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 50 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 5 c 0,-2.761 2.239,-5 5,-5 z M 85,5 c 2.761,0 5,2.239 5,5 v 40 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 10 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 40 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 10 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 40 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 10 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 40 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 10 c 0,-2.761 2.239,-5 5,-5 z M 45,5 c 2.761,0 5,2.239 5,5 v 40 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 10 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 40 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 10 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 40 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 10 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 40 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 10 c 0,-2.761 2.239,-5 5,-5 z M 25,15 c 2.761,0 5,2.239 5,5 v 20 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 20 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 20 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 20 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 20 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 20 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 20 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 20 c 0,-2.761 2.239,-5 5,-5 z m -280,0 c 2.761,0 5,2.239 5,5 v 20 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 20 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 20 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 20 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 20 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 20 c 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 v 20 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 20 c 0,-2.761 2.239,-5 5,-5 z M 5,25 c 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 z m 120,0 c 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 z"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
d="m 65,0 c 2.761,0 5,2.239 5,5 v 50 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 5 c 0,-2.761 2.239,-5 5,-5 z m 20,5 c 2.761,0 5,2.239 5,5 v 40 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 10 C 80,7.239 82.239,5 85,5 Z M 45,5 c 2.761,0 5,2.239 5,5 v 40 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 10 C 40,7.239 42.239,5 45,5 Z M 25,15 c 2.761,0 5,2.239 5,5 v 20 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 20 c 0,-2.761 2.239,-5 5,-5 z m 80,0 c 2.761,0 5,2.239 5,5 v 20 c 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 V 20 c 0,-2.761 2.239,-5 5,-5 z M 5,25 c 2.761,0 5,2.239 5,5 0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 z m 115,5 C 40,5.0000002e-8 80,15 120,30 Z"
|
||||
sodipodi:nodetypes="sssssssssssssssssssssssssssssssssssssssscc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 2 KiB |
|
|
@ -2,18 +2,19 @@
|
|||
<svg
|
||||
width="80"
|
||||
height="80"
|
||||
viewBox="0 0 80 80"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
id="svg12"
|
||||
sodipodi:docname="menu_copy_text_custom.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
id="defs16" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
id="namedview14"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
|
|
@ -21,19 +22,33 @@
|
|||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4.2868349"
|
||||
inkscape:cx="15.512611"
|
||||
inkscape:cy="30.791949"
|
||||
inkscape:zoom="6.4191176"
|
||||
inkscape:cx="21.887744"
|
||||
inkscape:cy="29.599084"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1131"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
d="M 44.50799,60 H 28.995997 C 25.416665,60 22.5,57.195556 22.5,53.748889 V 32.577778 c 0,-3.444445 2.914332,-6.248889 6.495997,-6.248889 H 44.50799 c 3.581666,0 6.495998,2.802222 6.495998,6.248889 V 53.748889 C 51.003988,57.195556 48.087322,60 44.50799,60 Z M 28.995997,29.453333 a 3.2666653,3.1111111 0 0 0 -3.247998,3.124445 v 21.171111 a 3.2666653,3.1111111 0 0 0 3.247998,3.126667 H 44.50799 a 3.2666653,3.1111111 0 0 0 3.247999,-3.126667 V 32.577778 A 3.2666653,3.1111111 0 0 0 44.50799,29.453333 Z M 57.499985,49.844444 V 26.251111 C 57.499985,22.804444 54.585653,20 51.003988,20 H 32.976662 a 1.6333326,1.5555556 0 0 0 -1.623999,1.562222 1.6333326,1.5555556 0 0 0 1.623999,1.562222 h 18.027326 a 3.2666653,3.1111111 0 0 1 3.247998,3.126667 v 23.593333 a 1.6333326,1.5555556 0 0 0 1.624,1.562223 1.6333326,1.5555556 0 0 0 1.623999,-1.562223 z"
|
||||
fill="#000000"
|
||||
fill-rule="nonzero"
|
||||
id="path2"
|
||||
style="stroke-width:2.2771" />
|
||||
inkscape:current-layer="svg12" />
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
id="g10"
|
||||
transform="matrix(2.8947749,0,0,2.9411765,20,15)">
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-rule="nonzero"
|
||||
id="g8">
|
||||
<g
|
||||
id="g6">
|
||||
<g
|
||||
id="g4">
|
||||
<path
|
||||
d="m 8.446,17 c 1.399,0 2.095,-0.716 2.095,-2.122 v -1.25 h 1.182 c 1.392,0 2.095,-0.716 2.095,-2.121 V 6.02 c 0,-0.83 -0.17,-1.358 -0.676,-1.878 L 9.73,0.676 C 9.25,0.182 8.682,0 7.96,0 H 5.371 C 3.98,0 3.277,0.716 3.277,2.122 v 1.25 H 2.095 C 0.703,3.372 0,4.082 0,5.493 v 9.385 C 0,16.291 0.696,17 2.095,17 h 6.35 z m 3.216,-4.46 H 10.541 V 9.602 c 0,-0.865 -0.102,-1.243 -0.642,-1.797 L 6.176,4.015 C 5.662,3.487 5.236,3.373 4.48,3.373 H 4.365 v -1.23 c 0,-0.669 0.358,-1.054 1.06,-1.054 h 2.987 v 3.466 c 0,0.784 0.379,1.155 1.156,1.155 h 3.162 v 5.777 c 0,0.676 -0.365,1.055 -1.068,1.055 z M 12.446,4.73 H 9.723 C 9.486,4.73 9.392,4.628 9.392,4.392 V 1.622 Z M 8.392,15.912 h -6.25 c -0.696,0 -1.054,-0.378 -1.054,-1.054 V 5.507 c 0,-0.662 0.358,-1.048 1.06,-1.048 h 2.217 v 3.92 c 0,0.85 0.432,1.276 1.27,1.276 h 3.818 v 5.203 c 0,0.676 -0.365,1.054 -1.061,1.054 z M 9.243,8.635 H 5.763 C 5.493,8.635 5.385,8.527 5.385,8.257 V 4.709 Z"
|
||||
id="path2" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.3 KiB |
|
|
@ -6,7 +6,7 @@
|
|||
version="1.1"
|
||||
id="svg10"
|
||||
sodipodi:docname="send_custom.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -26,8 +26,8 @@
|
|||
inkscape:cx="9.408651"
|
||||
inkscape:cy="46.187923"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1131"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg10" />
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
id="g8"
|
||||
transform="matrix(2.0833639,0,0,2.083344,15.000137,14.999696)">
|
||||
transform="matrix(2.5000367,0,0,2.5000128,10.000164,9.9996351)">
|
||||
<g
|
||||
fill="#444444"
|
||||
fill-rule="nonzero"
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
|
@ -2634,6 +2634,16 @@ Click here: <a href="%1">%1</a>
|
|||
<extracomment>'Mipmap filtering gives better visual quality when scaling down compared to smooth, but it may come at a performance cost (both when initializing the image and during rendering).' : Second line of a tooltip about Mipmap mode.</extracomment>
|
||||
<translation>Mipmap filtering gives better visual quality when scaling down compared to smooth, but it may come at a performance cost (both when initializing the image and during rendering).</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>minimalTimelineFilterLabel</source>
|
||||
<extracomment>'Minimal Timeline filter'</extracomment>
|
||||
<translation>Minimal Timeline filter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>minimalTimelineFilterTooltip</source>
|
||||
<extracomment>'Show a minimal version of what to display in timeline.' :</extracomment>
|
||||
<translation>Show a minimal version of what to display in timeline.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsVideo</name>
|
||||
|
|
@ -2833,6 +2843,11 @@ Click here: <a href="%1">%1</a>
|
|||
<extracomment>'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled.</extracomment>
|
||||
<translation>Without ephemerals</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>timelineFilterConferences</source>
|
||||
<extracomment>'Conferences' : Filter item. Selecting it will show all conferences.</extracomment>
|
||||
<translation>Conferences</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>UseAppSipAccount</name>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@
|
|||
<file>assets/images/chat_audio_pause_custom.svg</file>
|
||||
<file>assets/images/chat_audio_play_custom.svg</file>
|
||||
<file>assets/images/chat_audio_soundwave_custom.svg</file>
|
||||
<file>assets/images/chat_audio_stop_custom.svg</file>
|
||||
<file>assets/images/chat_audio_preview_pause_custom.svg</file>
|
||||
<file>assets/images/chat_audio_preview_play_custom.svg</file>
|
||||
<file>assets/images/chat_audio_preview_stop_custom.svg</file>
|
||||
<file>assets/images/chat_count.svg</file>
|
||||
<file>assets/images/chat_delivered.svg</file>
|
||||
<file>assets/images/chat_error.svg</file>
|
||||
|
|
@ -281,6 +283,7 @@
|
|||
<file>ui/modules/Linphone/Chat/ChatAudioMessage.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatAudioPreview.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatFileMessage.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatFilePreview.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatForwardMessage.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatMessagePreview.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatReplyMessage.qml</file>
|
||||
|
|
@ -301,6 +304,7 @@
|
|||
<file>ui/modules/Linphone/Contact/Contact.qml</file>
|
||||
<file>ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml</file>
|
||||
<file>ui/modules/Linphone/Dialog/SipAddressDialog.qml</file>
|
||||
<file>ui/modules/Linphone/File/FileView.qml</file>
|
||||
<file>ui/modules/Linphone/History/History.qml</file>
|
||||
<file>ui/modules/Linphone/History/History.js</file>
|
||||
<file>ui/modules/Linphone/History/Event.qml</file>
|
||||
|
|
@ -327,6 +331,7 @@
|
|||
<file>ui/modules/Linphone/Styles/Chat/ChatStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Chat/ChatAudioMessageStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Chat/ChatAudioPreviewStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Chat/ChatFilePreviewStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Chat/ChatForwardMessageStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Chat/ChatReplyMessageStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Codecs/CodecsViewerStyle.qml</file>
|
||||
|
|
|
|||
|
|
@ -120,33 +120,36 @@ QString ChatMessageModel::AppDataManager::toString(){
|
|||
}
|
||||
ChatMessageModel::ChatMessageModel ( std::shared_ptr<linphone::ChatMessage> chatMessage, QObject * parent) : ChatEvent(ChatRoomModel::EntryType::MessageEntry, parent) {
|
||||
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it
|
||||
mParticipantImdnStateListModel = std::make_shared<ParticipantImdnStateListModel>(chatMessage);
|
||||
mChatMessageListener = std::make_shared<ChatMessageListener>(this, parent);
|
||||
mChatMessage = chatMessage;
|
||||
if(chatMessage){
|
||||
mParticipantImdnStateListModel = std::make_shared<ParticipantImdnStateListModel>(chatMessage);
|
||||
mChatMessageListener = std::make_shared<ChatMessageListener>(this, parent);
|
||||
mChatMessage = chatMessage;
|
||||
mChatMessage->addListener(mChatMessageListener);
|
||||
if( mChatMessage->isReply()){
|
||||
auto replyMessage = mChatMessage->getReplyMessage();
|
||||
if( replyMessage)// Reply message could be inexistant (for example : when locally deleted)
|
||||
mReplyChatMessageModel = create(replyMessage, parent);
|
||||
}
|
||||
connect(this, &ChatMessageModel::remove, dynamic_cast<ChatRoomModel*>(parent), &ChatRoomModel::removeEntry);
|
||||
|
||||
std::list<std::shared_ptr<linphone::Content>> contents = chatMessage->getContents();
|
||||
QString txt;
|
||||
for(auto content : contents){
|
||||
if(content->isText())
|
||||
txt += content->getUtf8Text().c_str();
|
||||
}
|
||||
mContent = txt;
|
||||
}
|
||||
mWasDownloaded = false;
|
||||
mChatMessage->addListener(mChatMessageListener);
|
||||
|
||||
mTimestamp = QDateTime::fromMSecsSinceEpoch(chatMessage->getTime() * 1000);
|
||||
if( mChatMessage->isReply()){
|
||||
auto replyMessage = mChatMessage->getReplyMessage();
|
||||
if( replyMessage)// Reply message could be inexistant (for example : when locally deleted)
|
||||
mReplyChatMessageModel = create(replyMessage, parent);
|
||||
}
|
||||
|
||||
connect(this, &ChatMessageModel::remove, dynamic_cast<ChatRoomModel*>(parent), &ChatRoomModel::removeEntry);
|
||||
|
||||
std::list<std::shared_ptr<linphone::Content>> contents = chatMessage->getContents();
|
||||
QString txt;
|
||||
for(auto content : contents){
|
||||
if(content->isText())
|
||||
txt += content->getUtf8Text().c_str();
|
||||
}
|
||||
mContent = txt;
|
||||
|
||||
mContentListModel = std::make_shared<ContentListModel>(this);
|
||||
}
|
||||
|
||||
ChatMessageModel::~ChatMessageModel(){
|
||||
mChatMessage->removeListener(mChatMessageListener);
|
||||
if(mChatMessage)
|
||||
mChatMessage->removeListener(mChatMessageListener);
|
||||
}
|
||||
std::shared_ptr<ChatMessageModel> ChatMessageModel::create(std::shared_ptr<linphone::ChatMessage> chatMessage, QObject * parent){
|
||||
auto model = std::make_shared<ChatMessageModel>(chatMessage, parent);
|
||||
|
|
@ -163,7 +166,7 @@ std::shared_ptr<ContentModel> ChatMessageModel::getContentModel(std::shared_ptr<
|
|||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
QString ChatMessageModel::getFromDisplayName() const{
|
||||
return Utils::getDisplayName(mChatMessage->getFromAddress());
|
||||
return mChatMessage ? Utils::getDisplayName(mChatMessage->getFromAddress()) : "";
|
||||
}
|
||||
|
||||
QString ChatMessageModel::getFromDisplayNameReplyMessage() const{
|
||||
|
|
@ -174,40 +177,40 @@ QString ChatMessageModel::getFromDisplayNameReplyMessage() const{
|
|||
}
|
||||
|
||||
QString ChatMessageModel::getFromSipAddress() const{
|
||||
return Utils::cleanSipAddress(Utils::coreStringToAppString(mChatMessage->getFromAddress()->asStringUriOnly()));
|
||||
return mChatMessage ? Utils::cleanSipAddress(Utils::coreStringToAppString(mChatMessage->getFromAddress()->asStringUriOnly())) : "";
|
||||
}
|
||||
|
||||
QString ChatMessageModel::getToDisplayName() const{
|
||||
return Utils::getDisplayName(mChatMessage->getToAddress());
|
||||
return mChatMessage ? Utils::getDisplayName(mChatMessage->getToAddress()) : "";
|
||||
}
|
||||
|
||||
QString ChatMessageModel::getToSipAddress() const{
|
||||
return Utils::cleanSipAddress(Utils::coreStringToAppString(mChatMessage->getToAddress()->asStringUriOnly()));
|
||||
return mChatMessage ? Utils::cleanSipAddress(Utils::coreStringToAppString(mChatMessage->getToAddress()->asStringUriOnly())) : "";
|
||||
}
|
||||
|
||||
ContactModel * ChatMessageModel::getContactModel() const{
|
||||
return CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(Utils::coreStringToAppString(mChatMessage->getFromAddress()->asString()));
|
||||
return mChatMessage ? CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(Utils::coreStringToAppString(mChatMessage->getFromAddress()->asString())) : nullptr;
|
||||
}
|
||||
|
||||
bool ChatMessageModel::isEphemeral() const{
|
||||
return mChatMessage->isEphemeral();
|
||||
return mChatMessage && mChatMessage->isEphemeral();
|
||||
}
|
||||
|
||||
qint64 ChatMessageModel::getEphemeralExpireTime() const{
|
||||
time_t t = mChatMessage->getEphemeralExpireTime();
|
||||
time_t t = mChatMessage ? mChatMessage->getEphemeralExpireTime() : 0;
|
||||
return t >0 ? t - QDateTime::currentSecsSinceEpoch() : 0;
|
||||
}
|
||||
|
||||
long ChatMessageModel::getEphemeralLifetime() const{
|
||||
return mChatMessage->getEphemeralLifetime();
|
||||
return mChatMessage ? mChatMessage->getEphemeralLifetime() : 0;
|
||||
}
|
||||
|
||||
LinphoneEnums::ChatMessageState ChatMessageModel::getState() const{
|
||||
return LinphoneEnums::fromLinphone(mChatMessage->getState());
|
||||
return mChatMessage ? LinphoneEnums::fromLinphone(mChatMessage->getState()) : LinphoneEnums::ChatMessageStateIdle;
|
||||
}
|
||||
|
||||
bool ChatMessageModel::isOutgoing() const{
|
||||
return mChatMessage->isOutgoing();
|
||||
return mChatMessage && mChatMessage->isOutgoing();
|
||||
}
|
||||
|
||||
ParticipantImdnStateProxyModel * ChatMessageModel::getProxyImdnStates(){
|
||||
|
|
@ -229,7 +232,7 @@ std::shared_ptr<ContentListModel> ChatMessageModel::getContents() const{
|
|||
}
|
||||
|
||||
bool ChatMessageModel::isReply() const{
|
||||
return mChatMessage->isReply();
|
||||
return mChatMessage && mChatMessage->isReply();
|
||||
}
|
||||
|
||||
ChatMessageModel * ChatMessageModel::getReplyChatMessageModel() const{
|
||||
|
|
@ -237,11 +240,11 @@ ChatMessageModel * ChatMessageModel::getReplyChatMessageModel() const{
|
|||
}
|
||||
|
||||
bool ChatMessageModel::isForward() const{
|
||||
return mChatMessage->isForward();
|
||||
return mChatMessage && mChatMessage->isForward();
|
||||
}
|
||||
|
||||
QString ChatMessageModel::getForwardInfo() const{
|
||||
return Utils::coreStringToAppString(mChatMessage->getForwardInfo());
|
||||
return mChatMessage ? Utils::coreStringToAppString(mChatMessage->getForwardInfo()) : "";
|
||||
}
|
||||
|
||||
QString ChatMessageModel::getForwardInfoDisplayName() const{
|
||||
|
|
@ -279,7 +282,6 @@ void ChatMessageModel::resendMessage (){
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void ChatMessageModel::deleteEvent(){
|
||||
if (mChatMessage && mChatMessage->getFileTransferInformation()) {// Remove thumbnail
|
||||
mChatMessage->cancelFileTransfer();
|
||||
|
|
@ -293,7 +295,8 @@ void ChatMessageModel::deleteEvent(){
|
|||
}
|
||||
mChatMessage->setAppdata("");// Remove completely Thumbnail from the message
|
||||
}
|
||||
mChatMessage->getChatRoom()->deleteMessage(mChatMessage);
|
||||
if(mChatMessage)
|
||||
mChatMessage->getChatRoom()->deleteMessage(mChatMessage);
|
||||
}
|
||||
void ChatMessageModel::updateFileTransferInformation(){
|
||||
mContentListModel->updateContents(this);
|
||||
|
|
@ -317,7 +320,7 @@ void ChatMessageModel::onFileTransferProgressIndication (const std::shared_ptr<l
|
|||
void ChatMessageModel::onMsgStateChanged (const std::shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessage::State state) {
|
||||
updateFileTransferInformation();// On message state, file transfert information Content can be changed
|
||||
// File message downloaded.
|
||||
if (state == linphone::ChatMessage::State::FileTransferDone && !mChatMessage->isOutgoing()) {
|
||||
if (mChatMessage && state == linphone::ChatMessage::State::FileTransferDone && !mChatMessage->isOutgoing()) {
|
||||
mContentListModel->downloaded();
|
||||
setWasDownloaded(true);
|
||||
App::getInstance()->getNotifier()->notifyReceivedFileMessage(message);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "app/paths/Paths.hpp"
|
||||
#include "app/providers/ThumbnailProvider.hpp"
|
||||
#include "components/calls/CallsListModel.hpp"
|
||||
#include "components/chat/ChatModel.hpp"
|
||||
#include "components/chat-events/ChatCallModel.hpp"
|
||||
#include "components/chat-events/ChatEvent.hpp"
|
||||
#include "components/chat-events/ChatMessageModel.hpp"
|
||||
|
|
@ -45,6 +46,8 @@
|
|||
#include "components/contact/ContactModel.hpp"
|
||||
#include "components/contact/VcardModel.hpp"
|
||||
#include "components/contacts/ContactsListModel.hpp"
|
||||
#include "components/content/ContentListModel.hpp"
|
||||
#include "components/content/ContentModel.hpp"
|
||||
#include "components/core/CoreHandlers.hpp"
|
||||
#include "components/core/CoreManager.hpp"
|
||||
#include "components/notifier/Notifier.hpp"
|
||||
|
|
@ -567,6 +570,10 @@ QString ChatRoomModel::getParticipantAddress(){
|
|||
}
|
||||
}
|
||||
|
||||
int ChatRoomModel::getAllUnreadCount(){
|
||||
return mUnreadMessagesCount + mMissedCallsCount;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
|
||||
void ChatRoomModel::setSubject(QString& subject){
|
||||
|
|
@ -654,7 +661,6 @@ ChatMessageModel * ChatRoomModel::getReply()const{
|
|||
return mReplyModel.get();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
|
||||
void ChatRoomModel::deleteChatRoom(){
|
||||
|
|
@ -694,63 +700,33 @@ void ChatRoomModel::updateParticipants(const QVariantList& participants){
|
|||
|
||||
void ChatRoomModel::sendMessage (const QString &message) {
|
||||
shared_ptr<linphone::ChatMessage> _message;
|
||||
if(mReplyModel && mReplyModel->getChatMessage())
|
||||
if(mReplyModel && mReplyModel->getChatMessage()) {
|
||||
_message = mChatRoom->createReplyMessage(mReplyModel->getChatMessage());
|
||||
else
|
||||
}else
|
||||
_message= mChatRoom->createEmptyMessage();
|
||||
auto recorder = CoreManager::getInstance()->getRecorderManager();
|
||||
if(recorder->haveVocalRecorder()) {
|
||||
recorder->getVocalRecorder()->stop();
|
||||
auto content = recorder->getVocalRecorder()->getRecorder()->createContent();
|
||||
if(content)
|
||||
if(content) {
|
||||
_message->addContent(content);
|
||||
}
|
||||
if(!message.isEmpty())
|
||||
_message->addUtf8TextContent(message.toUtf8().toStdString());
|
||||
_message->send();
|
||||
emit messageSent(_message);
|
||||
setReply(nullptr);
|
||||
if(recorder->haveVocalRecorder())
|
||||
recorder->clearVocalRecorder();
|
||||
}
|
||||
|
||||
void ChatRoomModel::sendFileMessage (const QString &path) {
|
||||
|
||||
QFile file(path);
|
||||
if (!file.exists())
|
||||
return;
|
||||
|
||||
qint64 fileSize = file.size();
|
||||
if (fileSize > Constants::FileSizeLimit) {
|
||||
qWarning() << QStringLiteral("Unable to send file. (Size limit=%1)").arg(Constants::FileSizeLimit);
|
||||
return;
|
||||
}
|
||||
|
||||
shared_ptr<linphone::Content> content = CoreManager::getInstance()->getCore()->createContent();
|
||||
{
|
||||
QStringList mimeType = QMimeDatabase().mimeTypeForFile(path).name().split('/');
|
||||
if (mimeType.length() != 2) {
|
||||
qWarning() << QStringLiteral("Unable to get supported mime type for: `%1`.").arg(path);
|
||||
return;
|
||||
}
|
||||
content->setType(Utils::appStringToCoreString(mimeType[0]));
|
||||
content->setSubtype(Utils::appStringToCoreString(mimeType[1]));
|
||||
}
|
||||
content->setSize(size_t(fileSize));
|
||||
content->setName(QFileInfo(file).fileName().toStdString());
|
||||
|
||||
shared_ptr<linphone::ChatMessage> message = mChatRoom->createFileTransferMessage(content);
|
||||
message->getContents().front()->setFilePath(Utils::appStringToCoreString(path));
|
||||
|
||||
auto recorder = CoreManager::getInstance()->getRecorderManager();
|
||||
if(recorder->haveVocalRecorder()) {
|
||||
auto content = recorder->getVocalRecorder()->getRecorder()->createContent();
|
||||
if(content)
|
||||
message->addContent(content);
|
||||
auto fileContents = CoreManager::getInstance()->getChatModel()->getContentListModel()->getContents();
|
||||
for(auto content : fileContents){
|
||||
_message->addFileContent(content->getContent());
|
||||
}
|
||||
if(!message.isEmpty()) {
|
||||
_message->addUtf8TextContent(message.toUtf8().toStdString());
|
||||
}
|
||||
if(_message->getContents().size() > 0){// Have something to send
|
||||
_message->send();
|
||||
emit messageSent(_message);
|
||||
setReply(nullptr);
|
||||
if(recorder->haveVocalRecorder())
|
||||
recorder->clearVocalRecorder();
|
||||
CoreManager::getInstance()->getChatModel()->clear();
|
||||
}
|
||||
message->send();
|
||||
|
||||
emit messageSent(message);
|
||||
}
|
||||
|
||||
void ChatRoomModel::forwardMessage(ChatMessageModel * model){
|
||||
|
|
|
|||
|
|
@ -154,8 +154,6 @@ public:
|
|||
Q_PROPERTY(bool entriesLoading READ isEntriesLoading WRITE setEntriesLoading NOTIFY entriesLoadingChanged)
|
||||
|
||||
|
||||
|
||||
//ChatRoomModel (const QString &peerAddress, const QString &localAddress, const bool& isSecure);
|
||||
static std::shared_ptr<ChatRoomModel> create(std::shared_ptr<linphone::ChatRoom> chatRoom);
|
||||
ChatRoomModel (std::shared_ptr<linphone::ChatRoom> chatRoom, QObject * parent = nullptr);
|
||||
~ChatRoomModel ();
|
||||
|
|
@ -202,6 +200,7 @@ public:
|
|||
std::shared_ptr<linphone::ChatRoom> getChatRoom();
|
||||
QList<QString> getComposers();
|
||||
QString getParticipantAddress(); // return peerAddress if not secure else return the first participant SIP address.
|
||||
int getAllUnreadCount(); // Return unread messages and missed call.
|
||||
|
||||
//---- Setters
|
||||
void setSubject(QString& subject);
|
||||
|
|
@ -219,6 +218,8 @@ public:
|
|||
void setReply(ChatMessageModel * model);
|
||||
ChatMessageModel * getReply()const;
|
||||
void clearReply();
|
||||
|
||||
void clearFilesToSend();
|
||||
|
||||
// Tools
|
||||
|
||||
|
|
@ -226,7 +227,6 @@ public:
|
|||
Q_INVOKABLE void leaveChatRoom ();
|
||||
Q_INVOKABLE void updateParticipants(const QVariantList& participants);
|
||||
void sendMessage (const QString &message);
|
||||
void sendFileMessage (const QString &path);
|
||||
Q_INVOKABLE void forwardMessage(ChatMessageModel * model);
|
||||
void compose ();
|
||||
Q_INVOKABLE void resetMessageCount ();
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ ChatRoomProxyModel::ChatRoomProxyModel (QObject *parent) : QSortFilterProxyModel
|
|||
|
||||
CREATE_PARENT_MODEL_FUNCTION(removeAllEntries)
|
||||
|
||||
CREATE_PARENT_MODEL_FUNCTION_WITH_PARAM(sendFileMessage, const QString &)
|
||||
CREATE_PARENT_MODEL_FUNCTION_WITH_PARAM(sendMessage, const QString &)
|
||||
CREATE_PARENT_MODEL_FUNCTION_WITH_PARAM(forwardMessage, ChatMessageModel *)
|
||||
|
||||
|
|
|
|||
|
|
@ -67,8 +67,6 @@ public:
|
|||
|
||||
Q_INVOKABLE void sendMessage (const QString &message);
|
||||
|
||||
Q_INVOKABLE void sendFileMessage (const QString &path);
|
||||
|
||||
Q_INVOKABLE void forwardMessage(ChatMessageModel * model);
|
||||
|
||||
Q_INVOKABLE void compose (const QString& text);
|
||||
|
|
|
|||
52
linphone-app/src/components/chat/ChatModel.cpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 "ChatModel.hpp"
|
||||
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QDesktopServices>
|
||||
#include <QImageReader>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "app/App.hpp"
|
||||
#include "app/paths/Paths.hpp"
|
||||
#include "app/providers/ThumbnailProvider.hpp"
|
||||
|
||||
#include "components/chat-events/ChatMessageModel.hpp"
|
||||
|
||||
#include "utils/QExifImageHeader.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
#include "utils/Constants.hpp"
|
||||
#include "components/Components.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
ChatModel::ChatModel(QObject * parent ) : QObject(parent){
|
||||
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE
|
||||
mContents = std::make_shared<ContentListModel>(nullptr);
|
||||
}
|
||||
|
||||
std::shared_ptr<ContentListModel> ChatModel::getContentListModel() const {
|
||||
return mContents;
|
||||
}
|
||||
|
||||
void ChatModel::clear() {
|
||||
mContents->clear();
|
||||
}
|
||||
48
linphone-app/src/components/chat/ChatModel.hpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// Used to store data between chats
|
||||
|
||||
#ifndef CHAT_MODEL_H_
|
||||
#define CHAT_MODEL_H_
|
||||
|
||||
#include <linphone++/linphone.hh>
|
||||
// =============================================================================
|
||||
#include <QObject>
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
class ContentListModel;
|
||||
|
||||
class ChatModel : public QObject{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ChatModel(QObject * parent = nullptr);
|
||||
|
||||
// Getters
|
||||
std::shared_ptr<ContentListModel> getContentListModel() const;
|
||||
|
||||
// Tools
|
||||
Q_INVOKABLE void clear();
|
||||
|
||||
private:
|
||||
std::shared_ptr<ContentListModel> mContents;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "ContentListModel.hpp"
|
||||
#include "ContentModel.hpp"
|
||||
#include "utils/Constants.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
||||
#include "components/Components.hpp"
|
||||
|
|
@ -31,11 +32,14 @@
|
|||
// =============================================================================
|
||||
|
||||
ContentListModel::ContentListModel (ChatMessageModel * message) : QAbstractListModel(message) {
|
||||
std::list<std::shared_ptr<linphone::Content>> contents = message->getChatMessage()->getContents() ;
|
||||
for(auto content : contents){
|
||||
auto contentModel = std::make_shared<ContentModel>(content, message);
|
||||
connect(this, &ContentListModel::updateTransferDataRequested, contentModel.get(), &ContentModel::updateTransferData);
|
||||
mList << contentModel;
|
||||
mParent = message;
|
||||
if(message){
|
||||
std::list<std::shared_ptr<linphone::Content>> contents = message->getChatMessage()->getContents() ;
|
||||
for(auto content : contents){
|
||||
auto contentModel = std::make_shared<ContentModel>(content, message);
|
||||
connect(this, &ContentListModel::updateTransferDataRequested, contentModel.get(), &ContentModel::updateTransferData);
|
||||
mList << contentModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,6 +69,57 @@ QVariant ContentListModel::data (const QModelIndex &index, int role) const {
|
|||
return QVariant();
|
||||
}
|
||||
|
||||
std::shared_ptr<ContentModel> ContentListModel::add(std::shared_ptr<linphone::Content> content){
|
||||
int row = mList.count();
|
||||
auto contentModel = std::make_shared<ContentModel>(content, mParent);
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
mList << contentModel;
|
||||
endInsertRows();
|
||||
emit contentsChanged();
|
||||
return contentModel;
|
||||
}
|
||||
|
||||
void ContentListModel::addFile(const QString& path){
|
||||
QFile file(path);
|
||||
if (!file.exists())
|
||||
return;
|
||||
|
||||
qint64 fileSize = file.size();
|
||||
if (fileSize > Constants::FileSizeLimit) {
|
||||
qWarning() << QStringLiteral("Unable to send file. (Size limit=%1)").arg(Constants::FileSizeLimit);
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::Content> content = CoreManager::getInstance()->getCore()->createContent();
|
||||
{
|
||||
QStringList mimeType = QMimeDatabase().mimeTypeForFile(path).name().split('/');
|
||||
if (mimeType.length() != 2) {
|
||||
qWarning() << QStringLiteral("Unable to get supported mime type for: `%1`.").arg(path);
|
||||
return;
|
||||
}
|
||||
content->setType(Utils::appStringToCoreString(mimeType[0]));
|
||||
content->setSubtype(Utils::appStringToCoreString(mimeType[1]));
|
||||
}
|
||||
content->setSize(size_t(fileSize));
|
||||
content->setName(QFileInfo(file).fileName().toStdString());
|
||||
content->setFilePath(Utils::appStringToCoreString(path));
|
||||
|
||||
auto modelAdded = add(content);
|
||||
if(!content->isFile())
|
||||
modelAdded->createThumbnail(true); // Was not created because linphone::Content is not considered as a file (yet)
|
||||
}
|
||||
|
||||
void ContentListModel::remove(ContentModel * model){
|
||||
int count = 0;
|
||||
for(auto it = mList.begin() ; it != mList.end() ; ++count, ++it) {
|
||||
if( it->get() == model) {
|
||||
model->removeThumbnail();
|
||||
removeRow(count, QModelIndex());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ContentListModel::removeRow (int row, const QModelIndex &parent){
|
||||
return removeRows(row, 1, parent);
|
||||
}
|
||||
|
|
@ -84,6 +139,17 @@ bool ContentListModel::removeRows (int row, int count, const QModelIndex &parent
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContentListModel::clear(){
|
||||
// Delete thumbnails
|
||||
for(auto contentModel : mList){
|
||||
contentModel->removeThumbnail();
|
||||
}
|
||||
beginResetModel();
|
||||
mList.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
std::shared_ptr<ContentModel> ContentListModel::getContentModel(std::shared_ptr<linphone::Content> content){
|
||||
for(auto c : mList)
|
||||
if(c->getContent() == content)
|
||||
|
|
@ -95,6 +161,11 @@ std::shared_ptr<ContentModel> ContentListModel::getContentModel(std::shared_ptr<
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<ContentModel>> ContentListModel::getContents(){
|
||||
return mList;
|
||||
}
|
||||
|
||||
void ContentListModel::updateContent(std::shared_ptr<linphone::Content> oldContent, std::shared_ptr<linphone::Content> newContent){
|
||||
int row = 0;
|
||||
for(auto content = mList.begin() ; content != mList.end() ; ++content, ++row){
|
||||
|
|
|
|||
|
|
@ -43,8 +43,15 @@ public:
|
|||
|
||||
virtual QHash<int, QByteArray> roleNames () const override;
|
||||
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
std::shared_ptr<ContentModel> add(std::shared_ptr<linphone::Content> content);
|
||||
void addFile(const QString& path);
|
||||
Q_INVOKABLE void remove(ContentModel * model);
|
||||
|
||||
void clear();
|
||||
|
||||
std::shared_ptr<ContentModel> getContentModel(std::shared_ptr<linphone::Content> content);// Return the contentModel by checking Content, or if it is the same file.
|
||||
QList<std::shared_ptr<ContentModel>> getContents();
|
||||
|
||||
void updateContent(std::shared_ptr<linphone::Content> oldContent, std::shared_ptr<linphone::Content> newContent);
|
||||
void updateContents(ChatMessageModel * messageModel);
|
||||
void updateAllTransferData();
|
||||
|
|
@ -52,12 +59,14 @@ public:
|
|||
|
||||
signals:
|
||||
void updateTransferDataRequested();
|
||||
void contentsChanged();
|
||||
|
||||
private:
|
||||
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
|
||||
virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
QList<std::shared_ptr<ContentModel>> mList;
|
||||
ChatMessageModel * mParent;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@
|
|||
|
||||
// =============================================================================
|
||||
|
||||
ContentModel::ContentModel(ChatMessageModel* chatModel){
|
||||
ContentModel::ContentModel(ChatMessageModel* chatModel) : mAppData(""){
|
||||
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE
|
||||
mChatMessageModel = chatModel;
|
||||
mWasDownloaded = false;
|
||||
mFileOffset = 0;
|
||||
}
|
||||
ContentModel::ContentModel(std::shared_ptr<linphone::Content> content, ChatMessageModel* chatModel){
|
||||
ContentModel::ContentModel(std::shared_ptr<linphone::Content> content, ChatMessageModel* chatModel) : mAppData(""){
|
||||
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE
|
||||
mChatMessageModel = chatModel;
|
||||
mWasDownloaded = false;
|
||||
|
|
@ -131,12 +131,12 @@ bool ContentModel::isVoiceRecording()const{
|
|||
}
|
||||
|
||||
// Create a thumbnail from the first content that have a file and store it in Appdata
|
||||
void ContentModel::createThumbnail () {
|
||||
if(isFile() || isFileEncrypted() || isFileTransfer()){
|
||||
void ContentModel::createThumbnail (const bool& force) {
|
||||
if(force || isFile() || isFileEncrypted() || isFileTransfer()){
|
||||
QString id;
|
||||
QString path = getFilePath();
|
||||
|
||||
auto appdata = ChatMessageModel::AppDataManager(QString::fromStdString(mChatMessageModel->getChatMessage()->getAppdata()));
|
||||
auto appdata = ChatMessageModel::AppDataManager(mChatMessageModel ? QString::fromStdString(mChatMessageModel->getChatMessage()->getAppdata()) : "");
|
||||
|
||||
if(!appdata.mData.contains(path)
|
||||
|| !QFileInfo(QString::fromStdString(Paths::getThumbnailsDirPath())+appdata.mData[path]).isFile()){
|
||||
|
|
@ -179,7 +179,9 @@ void ContentModel::createThumbnail () {
|
|||
qWarning() << QStringLiteral("Unable to create thumbnail of: `%1`.").arg(path);
|
||||
}else{
|
||||
appdata.mData[path] = id;
|
||||
mChatMessageModel->getChatMessage()->setAppdata(appdata.toString().toStdString());
|
||||
mAppData.mData[path] = id;
|
||||
if(mChatMessageModel)
|
||||
mChatMessageModel->getChatMessage()->setAppdata(appdata.toString().toStdString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -192,6 +194,16 @@ void ContentModel::createThumbnail () {
|
|||
}
|
||||
}
|
||||
|
||||
void ContentModel::removeThumbnail(){
|
||||
for(QMap<QString, QString>::iterator itData = mAppData.mData.begin() ; itData != mAppData.mData.end() ; ++itData){
|
||||
QString thumbnailPath = QString::fromStdString(Paths::getThumbnailsDirPath()) +itData.value();
|
||||
if( QFileInfo(thumbnailPath).isFile()){
|
||||
QFile(thumbnailPath).remove();
|
||||
}
|
||||
}
|
||||
mAppData.mData.clear();
|
||||
}
|
||||
|
||||
void ContentModel::downloadFile(){
|
||||
switch (mChatMessageModel->getState()) {
|
||||
case LinphoneEnums::ChatMessageStateDelivered:
|
||||
|
|
@ -228,10 +240,11 @@ void ContentModel::downloadFile(){
|
|||
}
|
||||
|
||||
void ContentModel::openFile (bool showDirectory) {
|
||||
if ((!mWasDownloaded && !mChatMessageModel->isOutgoing()) || mContent->getFilePath() == "") {
|
||||
if (mChatMessageModel && ((!mWasDownloaded && !mChatMessageModel->isOutgoing()) || mContent->getFilePath() == "")) {
|
||||
downloadFile();
|
||||
}else{
|
||||
QFileInfo info( Utils::coreStringToAppString(mContent->getFilePath()));
|
||||
showDirectory = showDirectory || !info.exists();
|
||||
QDesktopServices::openUrl(
|
||||
QUrl(QStringLiteral("file:///%1").arg(showDirectory ? info.absolutePath() : info.absoluteFilePath()))
|
||||
);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@
|
|||
#include <QObject>
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
class ChatMessageModel;
|
||||
|
||||
#include "components/chat-events/ChatMessageModel.hpp"
|
||||
|
||||
class ContentModel : public QObject{
|
||||
Q_OBJECT
|
||||
|
|
@ -67,9 +68,11 @@ public:
|
|||
Q_INVOKABLE bool isText() const;
|
||||
Q_INVOKABLE bool isVoiceRecording()const;
|
||||
|
||||
void createThumbnail ();
|
||||
void createThumbnail (const bool& force = false);
|
||||
void removeThumbnail ();
|
||||
|
||||
Q_INVOKABLE void downloadFile();
|
||||
Q_INVOKABLE void openFile (bool showDirectory = false);
|
||||
Q_INVOKABLE void openFile (bool showDirectory = false);
|
||||
|
||||
|
||||
QString mThumbnail;
|
||||
|
|
@ -88,6 +91,7 @@ signals:
|
|||
private:
|
||||
std::shared_ptr<linphone::Content> mContent;
|
||||
ChatMessageModel* mChatMessageModel;
|
||||
ChatMessageModel::AppDataManager mAppData; // Used if there is no Chat Message model set.
|
||||
};
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<ContentModel>)
|
||||
|
||||
|
|
|
|||
|
|
@ -26,13 +26,14 @@
|
|||
#include "utils/Utils.hpp"
|
||||
|
||||
#include "components/Components.hpp"
|
||||
#include "components/chat/ChatModel.hpp"
|
||||
#include "components/chat-events/ChatMessageModel.hpp"
|
||||
#include "ContentListModel.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
ContentProxyModel::ContentProxyModel (QObject * parent) : QSortFilterProxyModel(parent){
|
||||
|
||||
setContentListModel(CoreManager::getInstance()->getChatModel()->getContentListModel().get());
|
||||
}
|
||||
|
||||
void ContentProxyModel::setChatMessageModel(ChatMessageModel * message){
|
||||
|
|
@ -43,6 +44,17 @@ void ContentProxyModel::setChatMessageModel(ChatMessageModel * message){
|
|||
emit chatMessageModelChanged();
|
||||
}
|
||||
|
||||
void ContentProxyModel::setContentListModel(ContentListModel * model){
|
||||
setSourceModel(model);
|
||||
sort(0);
|
||||
emit chatMessageModelChanged();
|
||||
}
|
||||
|
||||
void ContentProxyModel::addFile(const QString& path){
|
||||
ContentListModel* model = dynamic_cast<ContentListModel*>(sourceModel());
|
||||
model->addFile(path);
|
||||
}
|
||||
|
||||
bool ContentProxyModel::filterAcceptsRow (
|
||||
int sourceRow,
|
||||
const QModelIndex &sourceParent
|
||||
|
|
@ -55,13 +67,13 @@ bool ContentProxyModel::filterAcceptsRow (
|
|||
bool ContentProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
|
||||
const ContentModel *contentA = sourceModel()->data(left).value<ContentModel *>();
|
||||
const ContentModel *contentB = sourceModel()->data(right).value<ContentModel *>();
|
||||
bool aIsForward = contentA->getChatMessageModel()->isForward();
|
||||
bool aIsReply = contentA->getChatMessageModel()->isReply();
|
||||
bool aIsForward = contentA->getChatMessageModel() && contentA->getChatMessageModel()->isForward();
|
||||
bool aIsReply = contentA->getChatMessageModel() && contentA->getChatMessageModel()->isReply();
|
||||
bool aIsVoiceRecording = contentA->isVoiceRecording();
|
||||
bool aIsFile = contentA->isFile() || contentA->isFileEncrypted() || contentA->isFileTransfer();
|
||||
bool aIsText = contentA->isText() ;
|
||||
bool bIsForward = contentB->getChatMessageModel()->isForward();
|
||||
bool bIsReply = contentB->getChatMessageModel()->isReply();
|
||||
bool bIsForward = contentB->getChatMessageModel() && contentB->getChatMessageModel()->isForward();
|
||||
bool bIsReply = contentB->getChatMessageModel() && contentB->getChatMessageModel()->isReply();
|
||||
bool bIsVoiceRecording = contentB->isVoiceRecording();
|
||||
bool bIsFile = contentB->isFile() || contentB->isFileEncrypted() || contentB->isFileTransfer();
|
||||
bool bIsText = contentB->isText() ;
|
||||
|
|
@ -76,3 +88,10 @@ bool ContentProxyModel::lessThan (const QModelIndex &left, const QModelIndex &ri
|
|||
)
|
||||
);
|
||||
}
|
||||
void ContentProxyModel::remove(ContentModel * model){
|
||||
dynamic_cast<ContentListModel*>(sourceModel())->remove(model);
|
||||
}
|
||||
|
||||
void ContentProxyModel::clear(){
|
||||
dynamic_cast<ContentListModel*>(sourceModel())->clear();
|
||||
}
|
||||
|
|
@ -41,6 +41,10 @@ public:
|
|||
Q_PROPERTY(ChatMessageModel * chatMessageModel WRITE setChatMessageModel NOTIFY chatMessageModelChanged)
|
||||
|
||||
void setChatMessageModel(ChatMessageModel * message);
|
||||
Q_INVOKABLE void setContentListModel(ContentListModel * model);
|
||||
Q_INVOKABLE void addFile(const QString& path);
|
||||
Q_INVOKABLE void remove(ContentModel * model);
|
||||
Q_INVOKABLE void clear();
|
||||
|
||||
signals:
|
||||
void chatMessageModelChanged();
|
||||
|
|
@ -49,7 +53,7 @@ protected:
|
|||
virtual bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
virtual bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
|
||||
|
||||
std::shared_ptr<ContentListModel> mContens;
|
||||
std::shared_ptr<ContentListModel> mContents;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "app/paths/Paths.hpp"
|
||||
#include "components/calls/CallsListModel.hpp"
|
||||
#include "components/chat/ChatModel.hpp"
|
||||
#include "components/chat-room/ChatRoomModel.hpp"
|
||||
#include "components/chat-room/ChatRoomListModel.hpp"
|
||||
#include "components/contact/VcardModel.hpp"
|
||||
|
|
@ -90,6 +91,7 @@ CoreManager::~CoreManager(){
|
|||
|
||||
void CoreManager::initCoreManager(){
|
||||
mCallsListModel = new CallsListModel(this);
|
||||
mChatModel = new ChatModel(this);
|
||||
mChatRoomListModel = new ChatRoomListModel(this);
|
||||
mContactsListModel = new ContactsListModel(this);
|
||||
mContactsImporterListModel = new ContactsImporterListModel(this);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class QTimer;
|
|||
class AbstractEventCountNotifier;
|
||||
class AccountSettingsModel;
|
||||
class CallsListModel;
|
||||
class ChatModel;
|
||||
class ChatRoomModel;
|
||||
class ChatRoomListModel;
|
||||
class ContactsListModel;
|
||||
|
|
@ -140,6 +141,10 @@ public:
|
|||
|
||||
AbstractEventCountNotifier * getEventCountNotifier();
|
||||
|
||||
ChatModel * getChatModel() const{
|
||||
return mChatModel;
|
||||
}
|
||||
|
||||
static CoreManager *getInstance ();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -220,6 +225,7 @@ private:
|
|||
ContactsImporterListModel *mContactsImporterListModel = nullptr;
|
||||
TimelineListModel *mTimelineListModel = nullptr;
|
||||
ChatRoomListModel *mChatRoomListModel = nullptr;
|
||||
ChatModel *mChatModel = nullptr;
|
||||
|
||||
SipAddressesModel *mSipAddressesModel = nullptr;
|
||||
SettingsModel *mSettingsModel = nullptr;
|
||||
|
|
|
|||
|
|
@ -217,7 +217,17 @@ class ColorListModel : public QAbstractListModel {
|
|||
ADD_COLOR("me_d_b_inv_fg", "#80FFFFFF", "[M] Menu disabled button : inverse foreground")
|
||||
ADD_COLOR("me_h_b_inv_fg", "#B0FFFFFF", "[M] Menu hovered button : inverse foreground")
|
||||
ADD_COLOR("me_p_b_inv_fg", "white", "[M] Menu pressed button : inverse foreground")
|
||||
//-------------------------------------
|
||||
// Wave Play
|
||||
ADD_COLOR_WITH_LINK("w_n_b_bg", "", "[M] Wave play normal button : background", "ma_n_b_bg")
|
||||
ADD_COLOR_WITH_LINK("w_d_b_bg", "", "[M] Wave play disabled button : background", "ma_d_b_bg")
|
||||
ADD_COLOR_WITH_LINK("w_h_b_bg", "", "[M] Wave play hovered button : background", "ma_h_b_bg")
|
||||
ADD_COLOR_WITH_LINK("w_p_b_bg", "", "[M] Wave play pressed button : background", "ma_p_b_bg")
|
||||
|
||||
ADD_COLOR_WITH_LINK("w_n_b_fg", "", "[M] Wave play normal button : foreground", "ma_n_b_fg")
|
||||
ADD_COLOR_WITH_LINK("w_d_b_fg", "", "[M] Wave play disabled button : foreground", "ma_d_b_fg")
|
||||
ADD_COLOR_WITH_LINK("w_h_b_fg", "", "[M] Wave play hovered button : foreground", "ma_h_b_fg")
|
||||
ADD_COLOR_WITH_LINK("w_p_b_fg", "", "[M] Wave play pressed button : foreground", "ma_p_b_fg")
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1372,7 +1372,16 @@ void SettingsModel::setMipmapEnabled(const bool& enabled){
|
|||
mConfig->setInt(UiSection, "mipmap_enabled", enabled);
|
||||
emit mipmapEnabledChanged();
|
||||
}
|
||||
|
||||
|
||||
bool SettingsModel::useMinimalTimelineFilter() const{
|
||||
return !!mConfig->getInt(UiSection, "use_minimal_timeline_filter", 1);
|
||||
}
|
||||
|
||||
void SettingsModel::setUseMinimalTimelineFilter(const bool& useMinimal) {
|
||||
mConfig->setInt(UiSection, "use_minimal_timeline_filter", useMinimal);
|
||||
emit useMinimalTimelineFilterChanged();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Advanced.
|
||||
// =============================================================================
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@ class SettingsModel : public QObject {
|
|||
Q_PROPERTY(bool showStartVideoCallButton READ getShowStartVideoCallButton CONSTANT)
|
||||
|
||||
Q_PROPERTY(bool mipmapEnabled READ isMipmapEnabled WRITE setMipmapEnabled NOTIFY mipmapEnabledChanged)
|
||||
Q_PROPERTY(bool useMinimalTimelineFilter READ useMinimalTimelineFilter WRITE setUseMinimalTimelineFilter NOTIFY useMinimalTimelineFilterChanged)
|
||||
|
||||
// Advanced. -----------------------------------------------------------------
|
||||
|
||||
|
|
@ -509,6 +510,9 @@ public:
|
|||
bool isMipmapEnabled() const;
|
||||
void setMipmapEnabled(const bool& enabled);
|
||||
|
||||
bool useMinimalTimelineFilter() const;
|
||||
void setUseMinimalTimelineFilter(const bool& useMinimal);
|
||||
|
||||
// Advanced. ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
|
@ -688,6 +692,7 @@ signals:
|
|||
|
||||
void exitOnCloseChanged (bool value);
|
||||
void mipmapEnabledChanged();
|
||||
void useMinimalTimelineFilterChanged();
|
||||
|
||||
void checkForUpdateEnabledChanged();
|
||||
void versionCheckUrlChanged();
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ void SoundPlayer::buildInternalPlayer () {
|
|||
SettingsModel *settingsModel = coreManager->getSettingsModel();
|
||||
|
||||
mInternalPlayer = coreManager->getCore()->createLocalPlayer(
|
||||
Utils::appStringToCoreString(settingsModel->getRingerDevice()), "", nullptr
|
||||
Utils::appStringToCoreString(settingsModel->getPlaybackDevice()), "", nullptr
|
||||
);
|
||||
if(mInternalPlayer)
|
||||
mInternalPlayer->addListener(mHandlers);
|
||||
|
|
|
|||
|
|
@ -123,6 +123,8 @@ bool TimelineProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &sou
|
|||
bool TimelineProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
|
||||
const TimelineModel* a = sourceModel()->data(left).value<TimelineModel*>();
|
||||
const TimelineModel* b = sourceModel()->data(right).value<TimelineModel*>();
|
||||
|
||||
return a->getChatRoomModel()->mLastUpdateTime > b->getChatRoomModel()->mLastUpdateTime;
|
||||
bool aHaveUnread = a->getChatRoomModel()->getAllUnreadCount() > 0;
|
||||
bool bHaveUnread = b->getChatRoomModel()->getAllUnreadCount() > 0;
|
||||
return (aHaveUnread && !bHaveUnread)
|
||||
|| (aHaveUnread == bHaveUnread && a->getChatRoomModel()->mLastUpdateTime > b->getChatRoomModel()->mLastUpdateTime);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ Item {
|
|||
property alias placeholderText: textArea.placeholderText
|
||||
property alias text: textArea.text
|
||||
property alias cursorPosition: textArea.cursorPosition
|
||||
property alias recordAudioToggled: recordAudioButton.toggled
|
||||
|
||||
property bool dropEnabled: true
|
||||
property string dropDisabledReason
|
||||
|
|
@ -56,11 +57,11 @@ Item {
|
|||
// ---------------------------------------------------------------------------
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
spacing: DroppableTextAreaStyle.fileChooserButton.margins
|
||||
spacing: 0
|
||||
// Handle click to select files.
|
||||
ActionButton {
|
||||
id: fileChooserButton
|
||||
property int totalWidth: DroppableTextAreaStyle.fileChooserButton.margins + width
|
||||
property int totalWidth: width
|
||||
|
||||
Layout.leftMargin: DroppableTextAreaStyle.fileChooserButton.margins
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
|
@ -88,12 +89,11 @@ Item {
|
|||
}
|
||||
// Record audio
|
||||
ActionButton {
|
||||
visible:droppableTextArea.enabled
|
||||
id: recordAudioButton
|
||||
visible: droppableTextArea.enabled
|
||||
|
||||
//anchors.verticalCenter: parent.verticalCenter
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
Layout.leftMargin: 0
|
||||
enabled: droppableTextArea.dropEnabled
|
||||
isCustom: true
|
||||
backgroundRadius: 8
|
||||
|
|
@ -111,6 +111,7 @@ Item {
|
|||
Layout.maximumHeight: parent.height-20
|
||||
Layout.topMargin: 10
|
||||
Layout.bottomMargin: 10
|
||||
Layout.leftMargin: 2
|
||||
//anchors.fill: parent
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
clip:true
|
||||
|
|
@ -137,9 +138,7 @@ Item {
|
|||
}
|
||||
}
|
||||
function handleValidation () {
|
||||
if (RecorderManager.haveVocalRecorder || text.length !== 0) {
|
||||
validText(text)
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
|
|
@ -194,7 +193,7 @@ Item {
|
|||
ActionButton {
|
||||
id: sendButton
|
||||
property int totalWidth: Layout.rightMargin + Layout.leftMargin + width
|
||||
Layout.rightMargin: DroppableTextAreaStyle.fileChooserButton.margins+15
|
||||
Layout.rightMargin: 15
|
||||
Layout.leftMargin: 10
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: droppableTextArea.enabled
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Controls.TextField {
|
|||
property string error: ''
|
||||
property var tools
|
||||
property QtObject textFieldStyle : TextFieldStyle.normal
|
||||
property bool persistentIcon: false
|
||||
property bool showWhenEmpty: true
|
||||
onTextFieldStyleChanged: if( !textFieldStyle) textFieldStyle = TextFieldStyle.normal
|
||||
|
||||
signal iconClicked()
|
||||
|
|
@ -87,7 +87,7 @@ Controls.TextField {
|
|||
}
|
||||
|
||||
iconSize: parent.contentHeight
|
||||
visible: persistentIcon || !parent.text
|
||||
visible: showWhenEmpty && !parent.text || !showWhenEmpty && parent.text
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: textField.iconClicked()
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ ProgressBar {
|
|||
property alias colorSet: progression.colorSet
|
||||
property alias backgroundColor: backgroundArea.color
|
||||
property alias durationTextColor: durationText.color
|
||||
property int waveLeftMargin: 0
|
||||
|
||||
function start(){
|
||||
progressBar.value = 0
|
||||
|
|
@ -61,13 +62,14 @@ ProgressBar {
|
|||
progression.percentageDisplayed = value
|
||||
}
|
||||
|
||||
anchors.topMargin: 5
|
||||
anchors.bottomMargin: 5
|
||||
anchors.topMargin: 2
|
||||
anchors.bottomMargin: 2
|
||||
|
||||
background: Rectangle {
|
||||
id: backgroundArea
|
||||
color: MediaProgressBarStyle.backgroundColor
|
||||
radius: 5
|
||||
clip: false
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -76,16 +78,19 @@ ProgressBar {
|
|||
anchors.fill: parent
|
||||
radius: 5
|
||||
color: 'transparent'
|
||||
clip: false
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
spacing: 0
|
||||
ActionButton{
|
||||
id: progression
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: progressBar.waveLeftMargin
|
||||
backgroundRadius: 5
|
||||
fillMode: Image.TileHorizontally
|
||||
verticalAlignment: Image.AlignLeft
|
||||
horizontalAlignment: Image.AlignLeft
|
||||
isCustom: true
|
||||
colorSet: MediaProgressBarStyle.progressionWave
|
||||
percentageDisplayed: 0
|
||||
|
|
@ -95,13 +100,15 @@ ProgressBar {
|
|||
id: durationText
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: implicitWidth
|
||||
Layout.rightMargin: 5
|
||||
Layout.leftMargin: 15
|
||||
Layout.rightMargin: 6
|
||||
horizontalAlignment: Qt.AlignRight
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: progressBar.progressPosition >= 0 ? Utils.formatElapsedTime( progressBar.progressPosition / 1000 ) : '-'
|
||||
text: progressBar.progressPosition > 0 ? Utils.formatElapsedTime( progressBar.progressPosition / 1000 )
|
||||
:( progressBar.progressPosition == 0 ? Utils.formatElapsedTime( progressBar.progressDuration / 1000) : '-')
|
||||
property font customFont : SettingsModel.textMessageFont
|
||||
font.family: customFont.family
|
||||
font.pointSize: Units.dp * (customFont.pointSize + 2)
|
||||
font.pointSize: Units.dp * (customFont.pointSize + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ QtObject {
|
|||
property int iconSize: 40
|
||||
property string icon : 'attachment_custom'
|
||||
property string name : 'attachment'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg').color
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_h_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_n_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
|
||||
}
|
||||
|
|
@ -35,24 +35,27 @@ QtObject {
|
|||
property int iconSize: 40
|
||||
property string name : 'micro'
|
||||
property string icon : 'chat_micro_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg').color
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_h_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_n_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color backgroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 'me_p_b_bg').color
|
||||
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
property color foregroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 'me_p_b_fg').color
|
||||
|
||||
}
|
||||
property QtObject send: QtObject {
|
||||
property int margins: 6
|
||||
property int iconSize: 40
|
||||
property int margins: 5
|
||||
property int iconSize: 30
|
||||
property string name : 'send'
|
||||
property string icon : 'send_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg').color
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_h_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_n_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ QtObject {
|
|||
property string gaugeIcon: 'chat_audio_soundwave_custom'
|
||||
|
||||
property QtObject progressionWave: QtObject{
|
||||
property int iconSize: 30
|
||||
property int iconHeight: 40
|
||||
property int iconWidth: 250
|
||||
property int iconSize: 60
|
||||
property int iconHeight: 60
|
||||
property int iconWidth: 60
|
||||
property string name : 'progression_soundwave'
|
||||
property string icon : 'chat_audio_soundwave_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'a_n_b_bg').color
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ import Common 1.0
|
|||
|
||||
ListView {
|
||||
id: view
|
||||
property bool hideScrollBars: false
|
||||
property alias verticalScrollPolicy : vScrollBar.policy
|
||||
property alias horizontalScrollPolicy : hScrollBar.policy
|
||||
|
||||
function getVisibleIndex(checkMax) {
|
||||
var center_x = view.x + view.width / 2
|
||||
|
|
@ -35,21 +38,55 @@ ListView {
|
|||
|
||||
ScrollBar.vertical: ForceScrollBar {
|
||||
id: vScrollBar
|
||||
onPressedChanged: pressed ? view.movementStarted() : view.movementEnded()
|
||||
// ScrollBar.AsNeeded doesn't work. Do it ourself.
|
||||
policy: ScrollBar.AlwaysOff
|
||||
function updatePolicy(){
|
||||
policy = (view.orientation == Qt.Vertical && view.contentHeight > view.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff)
|
||||
}
|
||||
Timer{// Delay to avoid binding loops
|
||||
id:delayUpdateVPolicy
|
||||
interval:10
|
||||
onTriggered: vScrollBar.updatePolicy()
|
||||
}
|
||||
Component.onCompleted: if(!hideScrollBars) updatePolicy()
|
||||
}
|
||||
ScrollBar.horizontal: ForceScrollBar {
|
||||
id: hScrollBar
|
||||
|
||||
onPressedChanged: pressed ? view.movementStarted() : view.movementEnded()
|
||||
// ScrollBar.AsNeeded doesn't work. Do it ourself.
|
||||
policy: (view.contentHeight > view.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff)
|
||||
policy: ScrollBar.AlwaysOff
|
||||
function updatePolicy() {
|
||||
policy = (view.orientation == Qt.Horizontal && view.contentWidth > view.width? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff)
|
||||
}
|
||||
Timer{// Delay to avoid binding loops
|
||||
id:delayUpdateHPolicy
|
||||
interval:10
|
||||
onTriggered: hScrollBar.updatePolicy()
|
||||
}
|
||||
Component.onCompleted: if(!hideScrollBars) updatePolicy()
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
boundsMovement: Flickable.StopAtBounds
|
||||
boundsBehavior: Flickable.DragOverBounds
|
||||
clip: true
|
||||
contentWidth: width - (vScrollBar.visible?vScrollBar.width:0)
|
||||
contentHeight: height - (hScrollBar.visible?hScrollBar.height:0)
|
||||
spacing: 0
|
||||
synchronousDrag: true
|
||||
onContentHeightChanged: cacheBuffer=view.contentHeight
|
||||
cacheBuffer: height
|
||||
|
||||
onContentHeightChanged: {
|
||||
cacheBuffer= (view.contentHeight > 0 ? view.contentHeight : 0)
|
||||
if(!hideScrollBars)
|
||||
delayUpdateVPolicy.restart()
|
||||
}
|
||||
onHeightChanged: {
|
||||
if(!hideScrollBars)
|
||||
delayUpdateVPolicy.restart()
|
||||
}
|
||||
onContentWidthChanged: if(!hideScrollBars) delayUpdateHPolicy.restart()
|
||||
onWidthChanged: if(!hideScrollBars) delayUpdateHPolicy.restart()
|
||||
cacheBuffer: height > 0 ? height : 0
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// TODO: Find a solution at this bug =>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ function getComponentFromEntry (chatEntry) {
|
|||
|
||||
function handleFilesDropped (files) {
|
||||
chat.bindToEnd = true
|
||||
files.forEach(container.proxyModel.sendFileMessage)
|
||||
files.forEach(chatMessagePreview.addFile)
|
||||
}
|
||||
|
||||
function handleMoreEntriesLoaded (n) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import Linphone 1.0
|
|||
import Linphone.Styles 1.0
|
||||
import Utils 1.0
|
||||
import UtilsCpp 1.0
|
||||
import LinphoneEnums 1.0
|
||||
|
||||
import Units 1.0
|
||||
|
||||
|
|
@ -46,7 +47,6 @@ Rectangle {
|
|||
|
||||
ScrollableListView {
|
||||
id: chat
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
property bool bindToEnd: false
|
||||
property bool displaying: false
|
||||
|
|
@ -371,128 +371,140 @@ Rectangle {
|
|||
|
||||
|
||||
}
|
||||
ChatMessagePreview{
|
||||
id: chatMessagePreview
|
||||
Layout.fillWidth: true
|
||||
|
||||
replyChatRoomModel: proxyModel.chatRoomModel
|
||||
|
||||
}
|
||||
Rectangle{
|
||||
id: messageBlock
|
||||
onHeightChanged: height = Layout.preferredHeight
|
||||
Layout.preferredHeight: visible && opacity > 0 ? 32 : 0
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: ChatStyle.entry.leftMargin
|
||||
Layout.rightMargin: ChatStyle.entry.rightMargin
|
||||
color: ChatStyle.messageBanner.color
|
||||
radius: 10
|
||||
state: "hidden"
|
||||
Timer{
|
||||
id: hideNoticeBanner
|
||||
interval: 4000
|
||||
repeat: false
|
||||
onTriggered: messageBlock.state = "hidden"
|
||||
}
|
||||
RowLayout{
|
||||
anchors.centerIn: parent
|
||||
spacing: 5
|
||||
Icon{
|
||||
icon: ChatStyle.copyTextIcon
|
||||
overwriteColor: ChatStyle.messageBanner.textColor
|
||||
iconSize: 20
|
||||
}
|
||||
Text{
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
text: container.noticeBannerText
|
||||
font {
|
||||
pointSize: ChatStyle.messageBanner.pointSize
|
||||
}
|
||||
color: ChatStyle.messageBanner.textColor
|
||||
}
|
||||
}
|
||||
states: [
|
||||
State {
|
||||
name: "hidden"
|
||||
PropertyChanges { target: messageBlock; opacity: 0 }
|
||||
},
|
||||
State {
|
||||
name: "showed"
|
||||
PropertyChanges { target: messageBlock; opacity: 1 }
|
||||
}
|
||||
]
|
||||
transitions: [
|
||||
Transition {
|
||||
from: "*"; to: "showed"
|
||||
SequentialAnimation{
|
||||
NumberAnimation{ properties: "opacity"; easing.type: Easing.OutBounce; duration: 500 }
|
||||
ScriptAction{ script: hideNoticeBanner.start()}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
SequentialAnimation{
|
||||
NumberAnimation{ properties: "opacity"; duration: 1000 }
|
||||
ScriptAction{ script: container.noticeBannerText = '' }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
// -------------------------------------------------------------------------
|
||||
// Send area.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Borders {
|
||||
id: textAreaBorders
|
||||
Rectangle {
|
||||
id: bottomChatBackground
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: textArea.height
|
||||
|
||||
borderColor: ChatStyle.sendArea.border.color
|
||||
topWidth: ChatStyle.sendArea.border.width
|
||||
visible: proxyModel.chatRoomModel && !proxyModel.chatRoomModel.hasBeenLeft && (!proxyModel.chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled || proxyModel.chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled)
|
||||
|
||||
|
||||
DroppableTextArea {
|
||||
id: textArea
|
||||
|
||||
enabled:proxyModel && proxyModel.chatRoomModel ? !proxyModel.chatRoomModel.hasBeenLeft:false
|
||||
isEphemeral : proxyModel && proxyModel.chatRoomModel ? proxyModel.chatRoomModel.ephemeralEnabled:false
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
height:ChatStyle.sendArea.height + ChatStyle.sendArea.border.width
|
||||
minimumHeight:ChatStyle.sendArea.height + ChatStyle.sendArea.border.width
|
||||
maximumHeight:container.height/2
|
||||
|
||||
dropEnabled: SettingsModel.fileTransferUrl.length > 0
|
||||
dropDisabledReason: qsTr('noFileTransferUrl')
|
||||
placeholderText: qsTr('newMessagePlaceholder')
|
||||
|
||||
onDropped: Logic.handleFilesDropped(files)
|
||||
onTextChanged: Logic.handleTextChanged(text)
|
||||
onValidText: {
|
||||
textArea.text = ''
|
||||
chat.bindToEnd = true
|
||||
if(proxyModel.chatRoomModel) {
|
||||
proxyModel.sendMessage(text)
|
||||
}else{
|
||||
console.log("Peer : " +proxyModel.peerAddress+ "/"+chat.model.peerAddress)
|
||||
proxyModel.chatRoomModel = CallsListModel.createChat(proxyModel.peerAddress)
|
||||
proxyModel.sendMessage(text)
|
||||
}
|
||||
}
|
||||
onAudioRecordRequest: RecorderManager.resetVocalRecorder()
|
||||
Component.onCompleted: {text = proxyModel.cachedText; cursorPosition=text.length}
|
||||
Layout.preferredHeight: textAreaBorders.height + chatMessagePreview.height+messageBlock.height
|
||||
color: ChatStyle.sendArea.backgroundBorder.color
|
||||
clip: true
|
||||
ColumnLayout{
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
Rectangle{
|
||||
anchors.fill:parent
|
||||
color:'white'
|
||||
opacity: 0.5
|
||||
visible:!textArea.enabled
|
||||
id: messageBlock
|
||||
onHeightChanged: height = Layout.preferredHeight
|
||||
Layout.preferredHeight: visible && opacity > 0 ? 32 : 0
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: ChatStyle.entry.leftMargin
|
||||
Layout.rightMargin: ChatStyle.entry.rightMargin
|
||||
color: ChatStyle.messageBanner.color
|
||||
radius: 10
|
||||
state: "hidden"
|
||||
Timer{
|
||||
id: hideNoticeBanner
|
||||
interval: 4000
|
||||
repeat: false
|
||||
onTriggered: messageBlock.state = "hidden"
|
||||
}
|
||||
RowLayout{
|
||||
anchors.centerIn: parent
|
||||
spacing: 5
|
||||
Icon{
|
||||
icon: ChatStyle.copyTextIcon
|
||||
overwriteColor: ChatStyle.messageBanner.textColor
|
||||
iconSize: 20
|
||||
}
|
||||
Text{
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
text: container.noticeBannerText
|
||||
font {
|
||||
pointSize: ChatStyle.messageBanner.pointSize
|
||||
}
|
||||
color: ChatStyle.messageBanner.textColor
|
||||
}
|
||||
}
|
||||
states: [
|
||||
State {
|
||||
name: "hidden"
|
||||
PropertyChanges { target: messageBlock; opacity: 0 }
|
||||
},
|
||||
State {
|
||||
name: "showed"
|
||||
PropertyChanges { target: messageBlock; opacity: 1 }
|
||||
}
|
||||
]
|
||||
transitions: [
|
||||
Transition {
|
||||
from: "*"; to: "showed"
|
||||
SequentialAnimation{
|
||||
NumberAnimation{ properties: "opacity"; easing.type: Easing.OutBounce; duration: 500 }
|
||||
ScriptAction{ script: hideNoticeBanner.start()}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
SequentialAnimation{
|
||||
NumberAnimation{ properties: "opacity"; duration: 1000 }
|
||||
ScriptAction{ script: container.noticeBannerText = '' }
|
||||
}
|
||||
}
|
||||
]
|
||||
}// MessageBlock
|
||||
ChatMessagePreview{
|
||||
id: chatMessagePreview
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: ChatStyle.sendArea.backgroundBorder.width
|
||||
maxHeight: container.height - textAreaBorders.height
|
||||
replyChatRoomModel: proxyModel.chatRoomModel
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------
|
||||
// Send area.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Borders {
|
||||
id: textAreaBorders
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: textArea.height
|
||||
Layout.leftMargin: ChatStyle.sendArea.backgroundBorder.width
|
||||
borderColor: ChatStyle.sendArea.border.color
|
||||
topWidth: ChatStyle.sendArea.border.width
|
||||
visible: proxyModel.chatRoomModel && !proxyModel.chatRoomModel.hasBeenLeft && (!proxyModel.chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled || proxyModel.chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled)
|
||||
|
||||
DroppableTextArea {
|
||||
id: textArea
|
||||
|
||||
enabled:proxyModel && proxyModel.chatRoomModel ? !proxyModel.chatRoomModel.hasBeenLeft:false
|
||||
isEphemeral : proxyModel && proxyModel.chatRoomModel ? proxyModel.chatRoomModel.ephemeralEnabled:false
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
height:ChatStyle.sendArea.height + ChatStyle.sendArea.border.width
|
||||
minimumHeight:ChatStyle.sendArea.height + ChatStyle.sendArea.border.width
|
||||
maximumHeight:container.height/2
|
||||
|
||||
dropEnabled: SettingsModel.fileTransferUrl.length > 0
|
||||
dropDisabledReason: qsTr('noFileTransferUrl')
|
||||
placeholderText: qsTr('newMessagePlaceholder')
|
||||
recordAudioToggled: RecorderManager.haveVocalRecorder && RecorderManager.getVocalRecorder().state != LinphoneEnums.RecorderStateClosed
|
||||
|
||||
onDropped: Logic.handleFilesDropped(files)
|
||||
onTextChanged: Logic.handleTextChanged(text)
|
||||
onValidText: {
|
||||
textArea.text = ''
|
||||
chat.bindToEnd = true
|
||||
if(proxyModel.chatRoomModel) {
|
||||
proxyModel.sendMessage(text)
|
||||
}else{
|
||||
console.log("Peer : " +proxyModel.peerAddress+ "/"+chat.model.peerAddress)
|
||||
proxyModel.chatRoomModel = CallsListModel.createChat(proxyModel.peerAddress)
|
||||
proxyModel.sendMessage(text)
|
||||
}
|
||||
}
|
||||
onAudioRecordRequest: RecorderManager.resetVocalRecorder()
|
||||
Component.onCompleted: {text = proxyModel.cachedText; cursorPosition=text.length}
|
||||
Rectangle{
|
||||
anchors.fill:parent
|
||||
color:'white'
|
||||
opacity: 0.5
|
||||
visible:!textArea.enabled
|
||||
}
|
||||
}
|
||||
}// Send Area
|
||||
}// ColumnLayout
|
||||
}// Bottom background
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,14 @@ Loader{
|
|||
property ContentModel contentModel
|
||||
property int maxWidth : parent.width
|
||||
property int fitWidth: active ? Math.max(maxWidth - ChatAudioMessageStyle.emptySpace, ChatAudioMessageStyle.minWidth) : 0
|
||||
property int fitHeight: active ? 40 : 0
|
||||
property int fitHeight: active ? 60 : 0
|
||||
|
||||
property font customFont : SettingsModel.textMessageFont
|
||||
property bool isOutgoing : contentModel && (contentModel.chatMessageModel.isOutgoing || contentModel.chatMessageModel.state == LinphoneEnums.ChatMessageStateIdle);
|
||||
property bool isOutgoing : contentModel && contentModel.chatMessageModel && (contentModel.chatMessageModel.isOutgoing || contentModel.chatMessageModel.state == LinphoneEnums.ChatMessageStateIdle);
|
||||
property bool isActive: active
|
||||
|
||||
active: contentModel && contentModel.isVoiceRecording()
|
||||
|
||||
sourceComponent: Item{
|
||||
id: loadedItem
|
||||
property bool isPlaying : vocalPlayer.item && vocalPlayer.item.playbackState === SoundPlayer.PlayingState
|
||||
|
|
@ -70,6 +72,7 @@ Loader{
|
|||
Layout.leftMargin: 15
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
isCustom: true
|
||||
backgroundRadius: width
|
||||
colorSet: (loadedItem.isPlaying ? ChatAudioMessageStyle.pauseAction
|
||||
: ChatAudioMessageStyle.playAction)
|
||||
onClicked:{
|
||||
|
|
@ -84,7 +87,9 @@ Loader{
|
|||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.rightMargin: 15
|
||||
Layout.rightMargin: 10
|
||||
Layout.topMargin: 10
|
||||
Layout.bottomMargin: 10
|
||||
MediaProgressBar{
|
||||
id: mediaProgressBar
|
||||
anchors.fill: parent
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ Rectangle{
|
|||
mediaProgressBar.stop()
|
||||
onIsPlayingChanged: isPlaying ? mediaProgressBar.resume() : mediaProgressBar.stop()
|
||||
|
||||
Layout.preferredHeight: visible ? 70 : 0
|
||||
Layout.preferredHeight: visible ? ChatAudioPreviewStyle.height : 0
|
||||
|
||||
color: ChatAudioPreviewStyle.backgroundColor
|
||||
radius: 0
|
||||
|
|
@ -54,17 +54,19 @@ Rectangle{
|
|||
RowLayout{
|
||||
id: lineLayout
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
spacing: 0
|
||||
ActionButton{
|
||||
Layout.preferredHeight: iconSize
|
||||
Layout.preferredWidth: iconSize
|
||||
Layout.leftMargin: 10
|
||||
Layout.leftMargin: 6
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
isCustom: true
|
||||
colorSet: ChatAudioPreviewStyle.deleteAction
|
||||
onClicked: RecorderManager.clearVocalRecorder()
|
||||
}
|
||||
VuMeter {
|
||||
Layout.leftMargin: 6
|
||||
Layout.rightMargin: 6
|
||||
Timer {
|
||||
interval: 50
|
||||
repeat: true
|
||||
|
|
@ -78,17 +80,22 @@ Rectangle{
|
|||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.topMargin: 5
|
||||
Layout.bottomMargin: 5
|
||||
Layout.topMargin: 10
|
||||
Layout.bottomMargin: 10
|
||||
Layout.leftMargin: 6
|
||||
MediaProgressBar{
|
||||
id: mediaProgressBar
|
||||
anchors.fill: parent
|
||||
waveLeftMargin: !vocalPlayer.item && vocalRecorder ? 10 : 0
|
||||
progressDuration: !vocalPlayer.item && vocalRecorder? vocalRecorder.getDuration() : 0
|
||||
progressPosition: !vocalPlayer.item ? progressDuration : 0
|
||||
value: !vocalPlayer.item ? 0.01 * progressDuration / 5 : 100
|
||||
stopAtEnd: !audioPreviewBlock.isRecording
|
||||
resetAtEnd: false
|
||||
colorSet: isRecording ? ChatAudioPreviewStyle.recordingProgressionWave : ChatAudioPreviewStyle.progressionWave
|
||||
function progressComputation(t) {
|
||||
return 1 * Math.sqrt(1 - (t=t/1-1)*t);
|
||||
}
|
||||
function refresh(){
|
||||
if( vocalPlayer.item){
|
||||
progressPosition = vocalPlayer.item.getPosition()
|
||||
|
|
@ -96,7 +103,10 @@ Rectangle{
|
|||
}else{// Recording
|
||||
progressDuration = vocalRecorder.getDuration()
|
||||
progressPosition = progressDuration
|
||||
value = value + 0.01
|
||||
if( value == 0)
|
||||
value = 1
|
||||
else
|
||||
value = value + Math.pow(value,-0.7)
|
||||
}
|
||||
}
|
||||
onEndReached:{
|
||||
|
|
@ -114,8 +124,8 @@ Rectangle{
|
|||
ActionButton{
|
||||
Layout.preferredHeight: iconSize
|
||||
Layout.preferredWidth: iconSize
|
||||
Layout.rightMargin: 15
|
||||
Layout.leftMargin: 5
|
||||
Layout.rightMargin: ChatStyle.rightButtonMargin
|
||||
Layout.leftMargin: ChatStyle.rightButtonLMargin
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
isCustom: true
|
||||
colorSet: audioPreviewBlock.isRecording ? ChatAudioPreviewStyle.stopAction
|
||||
|
|
@ -124,7 +134,7 @@ Rectangle{
|
|||
onClicked:{
|
||||
if(audioPreviewBlock.isRecording){// Stop the record and save the file
|
||||
audioPreviewBlock.vocalRecorder.stop()
|
||||
//mediaProgressBar.value = 100
|
||||
mediaProgressBar.value = 0
|
||||
}else if(audioPreviewBlock.isPlaying){// Pause the play
|
||||
vocalPlayer.item.pause()
|
||||
}else{// Play the audio
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ Column{
|
|||
|
||||
spacing: 0
|
||||
|
||||
property bool isOutgoing : contentModel && (contentModel.chatMessageModel.isOutgoing || contentModel.chatMessageModel.state == LinphoneEnums.ChatMessageStateIdle);
|
||||
property bool isOutgoing : contentModel && contentModel.chatMessageModel && (contentModel.chatMessageModel.isOutgoing || contentModel.chatMessageModel.state == LinphoneEnums.ChatMessageStateIdle);
|
||||
|
||||
ChatAudioMessage{
|
||||
id: audioMessage
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Row {
|
|||
|
||||
property ChatMessageModel chatMessageModel: contentModel && contentModel.chatMessageModel
|
||||
property ContentModel contentModel
|
||||
property bool isOutgoing : contentModel && ( chatMessageModel.isOutgoing || chatMessageModel.state == LinphoneEnums.ChatMessageStateIdle);
|
||||
property bool isOutgoing : chatMessageModel && ( chatMessageModel.isOutgoing || chatMessageModel.state == LinphoneEnums.ChatMessageStateIdle);
|
||||
property int fitWidth: visible ? Math.max(fileName.implicitWidth + 5 + thumbnailProvider.width + 3*ChatStyle.entry.message.file.margins
|
||||
, Math.max(ChatStyle.entry.message.file.width, ChatStyle.entry.message.outgoing.areaSize)) : 0
|
||||
property int fitHeight: visible ? rectangle.height : 0
|
||||
|
|
|
|||
86
linphone-app/ui/modules/Linphone/Chat/ChatFilePreview.qml
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import Common 1.0
|
||||
import Linphone 1.0
|
||||
import Linphone.Styles 1.0
|
||||
import Utils 1.0
|
||||
import UtilsCpp 1.0
|
||||
|
||||
import Units 1.0
|
||||
|
||||
import 'Chat.js' as Logic
|
||||
|
||||
// =============================================================================
|
||||
Item{
|
||||
visible: mainListView.count > 0
|
||||
Layout.preferredHeight: visible ? ChatFilePreviewStyle.height : 0
|
||||
|
||||
function addFile(path){
|
||||
contents.addFile(path)
|
||||
}
|
||||
|
||||
ScrollableListView{
|
||||
id: mainListView
|
||||
|
||||
spacing: ChatFilePreviewStyle.filePreview.closeButton.iconSize
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: ChatStyle.rightButtonMargin + ChatStyle.rightButtonLMargin + ChatStyle.rightButtonSize
|
||||
orientation: Qt.Horizontal
|
||||
model: ContentProxyModel{
|
||||
id: contents
|
||||
}
|
||||
header:Component{
|
||||
Item{
|
||||
width: ChatFilePreviewStyle.filePreview.closeButton.iconSize/2
|
||||
height:mainListView.height
|
||||
}
|
||||
}
|
||||
footer: Component{
|
||||
Item{
|
||||
width: ChatFilePreviewStyle.filePreview.closeButton.iconSize
|
||||
height:mainListView.height
|
||||
}
|
||||
}
|
||||
delegate:
|
||||
FileView{
|
||||
height:mainListView.height-ChatFilePreviewStyle.filePreview.heightMargins
|
||||
width: height * ChatFilePreviewStyle.filePreview.format
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: 7
|
||||
//anchors.horizontalCenter: parent.horizontalCenter
|
||||
thumbnail: modelData.thumbnail
|
||||
name: modelData.name
|
||||
animationScale: 1.1
|
||||
onClickOnFile: {
|
||||
modelData.openFile()
|
||||
}
|
||||
ActionButton{
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: -height/2
|
||||
anchors.left: parent.right
|
||||
anchors.leftMargin: -width/2
|
||||
isCustom: true
|
||||
backgroundRadius: width
|
||||
colorSet: ChatFilePreviewStyle.filePreview.removeButton
|
||||
z: parent.z+1
|
||||
onClicked:{
|
||||
contents.remove(modelData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ActionButton{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: ChatStyle.rightButtonMargin
|
||||
isCustom: true
|
||||
backgroundRadius: width
|
||||
colorSet: ChatFilePreviewStyle.filePreview.closeButton
|
||||
z: parent.z+1
|
||||
onClicked:{
|
||||
contents.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,18 +15,48 @@ import 'Chat.js' as Logic
|
|||
// =============================================================================
|
||||
ColumnLayout{
|
||||
property alias replyChatRoomModel : replyPreview.chatRoomModel
|
||||
property int maxHeight: parent.height - ( audioPreview.visible ? audioPreview.height : 0)
|
||||
property int maxHeight: parent.height
|
||||
property int fitHeight: (replyPreview.visible ? replyPreview.height + replySeparator.height: 0 )
|
||||
+ (audioPreview.visible ? audioPreview.height + audioSeparator.height: 0)
|
||||
+ (filesPreview.visible ? filesPreview.height + filesSeparator.height: 0)
|
||||
spacing: 0
|
||||
Layout.preferredHeight: (replyPreview.visible ? replyPreview.height : 0 ) + (audioPreview.visible ? audioPreview.height : 0)
|
||||
Layout.maximumHeight: Layout.preferredHeight
|
||||
Layout.preferredHeight: fitHeight
|
||||
Layout.maximumHeight: fitHeight> maxHeight ? maxHeight : fitHeight // ?? just using maxHeight doesn't work.
|
||||
function hide(){
|
||||
}
|
||||
function addFile(path){
|
||||
filesPreview.addFile(path)
|
||||
}
|
||||
ChatReplyPreview{
|
||||
id: replyPreview
|
||||
Layout.fillWidth: true
|
||||
maxHeight: parent.maxHeight - (audioPreview.visible ? audioPreview.height + audioSeparator.height: 0)
|
||||
- (filesPreview.visible ? filesPreview.height + filesSeparator.height: 0)
|
||||
}
|
||||
Item{
|
||||
id: replySeparator
|
||||
visible: replyPreview.visible
|
||||
Layout.preferredHeight: visible ? ChatStyle.separatorHeight : 0
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
ChatAudioPreview{
|
||||
id: audioPreview
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Item{
|
||||
id: audioSeparator
|
||||
visible: audioPreview.visible
|
||||
Layout.preferredHeight: visible ? ChatStyle.separatorHeight : 0
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
ChatFilePreview{
|
||||
id: filesPreview
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Item{
|
||||
id: filesSeparator
|
||||
visible: filesPreview.visible
|
||||
Layout.preferredHeight: visible ? ChatStyle.separatorHeight : 0
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
|
@ -108,9 +108,10 @@ Item {
|
|||
|
||||
color: ChatReplyMessageStyle.replyArea.foregroundColor
|
||||
}
|
||||
ListView {
|
||||
ScrollableListView {
|
||||
id: replyMessage
|
||||
property int fitWidth : 0
|
||||
hideScrollBars: true
|
||||
anchors.top: usernameReplied.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
|
@ -130,7 +131,13 @@ Item {
|
|||
model: ContentProxyModel{
|
||||
chatMessageModel: mainItem.chatMessageModel
|
||||
}
|
||||
height: contentHeight
|
||||
Timer{// Delay to avoid binding loops
|
||||
id:delayUpdate
|
||||
interval:10
|
||||
onTriggered: replyMessage.height = replyMessage.contentHeight
|
||||
}
|
||||
onContentHeightChanged: delayUpdate.restart()
|
||||
//height: contentHeight
|
||||
|
||||
delegate: ChatContent{
|
||||
contentModel: modelData
|
||||
|
|
@ -140,6 +147,13 @@ Item {
|
|||
onFitWidthChanged:{
|
||||
replyMessage.updateWidth()
|
||||
}
|
||||
Rectangle{
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
color: ChatStyle.entry.separator.color
|
||||
height: visible ? ChatStyle.entry.separator.width : 0
|
||||
visible: (index !== (replyMessage.count - 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,8 @@ import 'Chat.js' as Logic
|
|||
Rectangle{
|
||||
id: replyPreviewBlock
|
||||
property ChatRoomModel chatRoomModel
|
||||
|
||||
Layout.preferredHeight: visible ? Math.min(messageContentsList.height + replyPreviewHeaderArea.implicitHeight + 15, parent.maxHeight) : 0
|
||||
|
||||
property int maxHeight : parent.maxHeight
|
||||
Layout.preferredHeight: visible ? Math.min(messageContentsList.height + replyPreviewHeaderArea.implicitHeight + 15, replyPreviewBlock.maxHeight) : 0
|
||||
property int leftMargin: textArea.textLeftMargin
|
||||
property int rightMargin: textArea.textRightMargin
|
||||
|
||||
|
|
@ -70,9 +69,10 @@ Rectangle{
|
|||
color: ChatStyle.replyPreview.headerTextColor
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: replyPreviewTextArea
|
||||
ScrollBar.vertical: ForceScrollBar {visible: replyPreviewTextArea.height < messageContentsList.implicitHeight}
|
||||
ScrollBar.vertical: ForceScrollBar {visible: replyPreviewTextArea.height < messageContentsList.height}
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
clip: true
|
||||
contentHeight: messageContentsList.height
|
||||
|
|
@ -93,13 +93,20 @@ Rectangle{
|
|||
delegate: ChatContent{
|
||||
contentModel: modelData
|
||||
textFont.pointSize: Units.dp * (SettingsModel.textMessageFont.pointSize - 2)
|
||||
Rectangle{
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
color: ChatStyle.entry.separator.color
|
||||
height: visible ? ChatStyle.entry.separator.width : 0
|
||||
visible: (index !== (messageContentsList.count - 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ActionButton{
|
||||
anchors.right:parent.right
|
||||
anchors.rightMargin: 14
|
||||
anchors.rightMargin: ChatStyle.rightButtonMargin
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: ChatStyle.replyPreview.closeButton.iconSize
|
||||
isCustom: true
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ TextEdit {
|
|||
property ContentModel contentModel
|
||||
property string lastTextSelected : ''
|
||||
property font customFont : SettingsModel.textMessageFont
|
||||
property int fitHeight: visible ? contentHeight + padding + 6 : 0
|
||||
property int fitHeight: visible ? contentHeight + padding + 8 : 0
|
||||
property int fitWidth: visible ? implicitWidth + 2: 0 // add 2 because there is a bug on border that lead to not fit text exactly
|
||||
|
||||
signal rightClicked()
|
||||
|
|
|
|||
|
|
@ -90,11 +90,11 @@ Item {
|
|||
}
|
||||
onGoToMessage: container.goToMessage(message)
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: messageContentsList
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
visible: count > 0
|
||||
spacing: 0
|
||||
model: ContentProxyModel{
|
||||
chatMessageModel: $chatEntry
|
||||
|
|
@ -102,14 +102,22 @@ Item {
|
|||
height: contentHeight
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
interactive: false
|
||||
delegate: ChatContent{
|
||||
contentModel: modelData
|
||||
onFitWidthChanged:{
|
||||
rectangle.updateWidth()
|
||||
delegate:
|
||||
ChatContent{
|
||||
contentModel: modelData
|
||||
onFitWidthChanged:{
|
||||
rectangle.updateWidth()
|
||||
}
|
||||
onLastTextSelectedChanged: container.lastTextSelected= lastTextSelected
|
||||
onRightClicked: chatMenu.open()
|
||||
Rectangle{
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
color: ChatStyle.entry.separator.color
|
||||
height: visible ? ChatStyle.entry.separator.width : 0
|
||||
visible: (index !== (messageContentsList.count - 1))
|
||||
}
|
||||
}
|
||||
onLastTextSelectedChanged: container.lastTextSelected= lastTextSelected
|
||||
onRightClicked: chatMenu.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
Row{
|
||||
|
|
|
|||
135
linphone-app/ui/modules/Linphone/File/FileView.qml
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import Common 1.0
|
||||
import Linphone 1.0
|
||||
import LinphoneUtils 1.0
|
||||
import LinphoneEnums 1.0
|
||||
import Linphone.Styles 1.0
|
||||
import Utils 1.0
|
||||
import Units 1.0
|
||||
import ColorsList 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
||||
Item {
|
||||
id: mainItem
|
||||
property string thumbnail
|
||||
property string name
|
||||
property bool active: true
|
||||
property real animationScale : ChatStyle.entry.message.file.animation.to
|
||||
property alias imageScale: thumbnailProvider.scale
|
||||
|
||||
signal clickOnFile()
|
||||
// ---------------------------------------------------------------------
|
||||
// Thumbnail or extension.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
Component {
|
||||
id: thumbnailImage
|
||||
|
||||
Image {
|
||||
id: thumbnailImageSource
|
||||
mipmap: SettingsModel.mipmapEnabled
|
||||
source: mainItem.thumbnail
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: extension
|
||||
|
||||
Rectangle {
|
||||
color: ChatStyle.entry.message.file.extension.background.color
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
|
||||
color: ChatStyle.entry.message.file.extension.text.color
|
||||
font.bold: true
|
||||
elide: Text.ElideRight
|
||||
text: Utils.getExtension(mainItem.name).toUpperCase()
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
id: thumbnailProvider
|
||||
|
||||
anchors.fill: parent
|
||||
//Layout.fillHeight: true
|
||||
//Layout.preferredWidth: parent.height
|
||||
|
||||
sourceComponent: (mainItem.active ? (mainItem.thumbnail ? thumbnailImage : extension ): undefined)
|
||||
|
||||
ScaleAnimator {
|
||||
id: thumbnailProviderAnimator
|
||||
|
||||
target: mainItem
|
||||
|
||||
duration: ChatStyle.entry.message.file.animation.duration
|
||||
easing.type: Easing.InOutQuad
|
||||
from: 1.0
|
||||
}
|
||||
|
||||
states: State {
|
||||
name: 'hovered'
|
||||
}
|
||||
|
||||
transitions: [
|
||||
Transition {
|
||||
from: ''
|
||||
to: 'hovered'
|
||||
|
||||
ScriptAction {
|
||||
script: {
|
||||
if (thumbnailProviderAnimator.running) {
|
||||
thumbnailProviderAnimator.running = false
|
||||
}
|
||||
|
||||
mainItem.z = 999//Constants.zPopup
|
||||
thumbnailProviderAnimator.to = mainItem.animationScale
|
||||
thumbnailProviderAnimator.running = true
|
||||
}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
from: 'hovered'
|
||||
to: ''
|
||||
|
||||
ScriptAction {
|
||||
script: {
|
||||
if (thumbnailProviderAnimator.running) {
|
||||
thumbnailProviderAnimator.running = false
|
||||
}
|
||||
|
||||
thumbnailProviderAnimator.to = 1.0
|
||||
thumbnailProviderAnimator.running = true
|
||||
mainItem.z = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
MouseArea {
|
||||
function handleMouseMove (mouse) {
|
||||
thumbnailProvider.state = Utils.pointIsInItem(this, thumbnailProvider, mouse)
|
||||
? 'hovered'
|
||||
: ''
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
clickOnFile()
|
||||
thumbnailProvider.state = ''
|
||||
}
|
||||
onExited: thumbnailProvider.state = ''
|
||||
onMouseXChanged: handleMouseMove.call(this, mouse)
|
||||
onMouseYChanged: handleMouseMove.call(this, mouse)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,54 +8,54 @@ import ColorsList 1.0
|
|||
|
||||
QtObject {
|
||||
property string sectionName : 'ChatAudioMessage'
|
||||
property int minWidth: 400
|
||||
property int emptySpace: 100
|
||||
property int minWidth: 500
|
||||
property int emptySpace: 10
|
||||
property color color: ColorsList.add(sectionName, 'q').color
|
||||
|
||||
property color backgroundColor: ColorsList.add(sectionName+'_bg', 'a').color
|
||||
|
||||
property QtObject pauseAction: QtObject {
|
||||
property int iconSize: 30
|
||||
property int iconSize: 25
|
||||
property string name : 'pause'
|
||||
property string icon : 'chat_audio_pause_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'q').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'q').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'q').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
}
|
||||
property QtObject playAction: QtObject {
|
||||
property int iconSize: 30
|
||||
property int iconSize: 25
|
||||
property string name : 'play'
|
||||
property string icon : 'chat_audio_play_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'q').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'q').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'q').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
}
|
||||
|
||||
property QtObject progressionWave: QtObject{
|
||||
property int iconSize: 30
|
||||
property int iconHeight: 40
|
||||
property int iconWidth: 250
|
||||
property int iconSize: 60
|
||||
property int iconHeight: 60
|
||||
property int iconWidth: 60
|
||||
property string name : 'progression_soundwave'
|
||||
property string icon : 'chat_audio_soundwave_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'a_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'a_h_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'a_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'a_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'a_h_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'a_p_b_fg').color
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'w_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'w_h_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'w_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'w_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'w_h_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'w_p_b_fg').color
|
||||
|
||||
property color backgroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_n', icon, 'l_n_b_bg').color
|
||||
property color backgroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_h', icon, 'l_h_b_bg').color
|
||||
property color backgroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_n', icon, 'l_h_b_bg').color
|
||||
property color backgroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_h', icon, 'l_n_b_bg').color
|
||||
property color backgroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_p', icon, 'l_p_b_bg').color
|
||||
|
||||
property color foregroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_n', icon, 'l_n_b_fg').color
|
||||
property color foregroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_h', icon, 'l_h_b_fg').color
|
||||
property color foregroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_n', icon, 'l_h_b_fg').color
|
||||
property color foregroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_h', icon, 'l_n_b_fg').color
|
||||
property color foregroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_p', icon, 'l_p_b_fg').color
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import ColorsList 1.0
|
|||
QtObject {
|
||||
property string sectionName : 'ChatAudioPreview'
|
||||
property color color: ColorsList.add(sectionName, 'q').color
|
||||
property int height: 70
|
||||
|
||||
property QtObject header: QtObject{
|
||||
property color color: ColorsList.add(sectionName+'_header', 'h').color
|
||||
property int pointSizeOffset: -3
|
||||
|
|
@ -31,51 +33,51 @@ QtObject {
|
|||
property int iconSize: 40
|
||||
property string name : 'delete'
|
||||
property string icon : 'delete_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg').color
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_h_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_n_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
}
|
||||
property QtObject stopAction: QtObject {
|
||||
property int iconSize: 30
|
||||
property string name : 'stop'
|
||||
property string icon : 'chat_audio_stop_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg').color
|
||||
property string icon : 'chat_audio_preview_stop_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_h_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_n_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
}
|
||||
property QtObject pauseAction: QtObject {
|
||||
property int iconSize: 30
|
||||
property string name : 'pause'
|
||||
property string icon : 'chat_audio_pause_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg').color
|
||||
property string icon : 'chat_audio_preview_pause_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_h_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_n_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
}
|
||||
property QtObject playAction: QtObject {
|
||||
property int iconSize: 30
|
||||
property string name : 'play'
|
||||
property string icon : 'chat_audio_play_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_bg').color
|
||||
property string icon : 'chat_audio_preview_play_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_h_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_n_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
}
|
||||
|
||||
property QtObject progressionWave: QtObject{
|
||||
property int iconSize: 30
|
||||
property int iconHeight: 40
|
||||
property int iconWidth: 250
|
||||
property int iconSize: 60
|
||||
property int iconHeight: 60
|
||||
property int iconWidth: 60
|
||||
property string name : 'progression_soundwave'
|
||||
property string icon : 'chat_audio_soundwave_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'a_n_b_bg').color
|
||||
|
|
@ -85,35 +87,37 @@ QtObject {
|
|||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'a_h_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'a_p_b_fg').color
|
||||
|
||||
property color backgroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_n', icon, 'l_n_b_bg').color
|
||||
property color backgroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_h', icon, 'l_h_b_bg').color
|
||||
property color backgroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_n', icon, 'l_h_b_bg').color
|
||||
property color backgroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_h', icon, 'l_n_b_bg').color
|
||||
property color backgroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_p', icon, 'l_p_b_bg').color
|
||||
|
||||
property color foregroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_n', icon, 'l_n_b_fg').color
|
||||
property color foregroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_h', icon, 'l_h_b_fg').color
|
||||
property color foregroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_n', icon, 'l_h_b_fg').color
|
||||
property color foregroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_h', icon, 'l_n_b_fg').color
|
||||
property color foregroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_p', icon, 'l_p_b_fg').color
|
||||
}
|
||||
|
||||
property QtObject recordingProgressionWave: QtObject{
|
||||
property int iconSize: 30
|
||||
property int iconHeight: 40
|
||||
property int iconWidth: 250
|
||||
property int iconSize: 60
|
||||
property int iconHeight: 60
|
||||
property int iconWidth: 60
|
||||
property string name : 'recording_progression_soundwave'
|
||||
property string icon : 'chat_audio_soundwave_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'r_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'r_h_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'r_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'r_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'r_h_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'r_p_b_fg').color
|
||||
|
||||
property color backgroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_n', icon, 'l_n_b_bg').color
|
||||
property color backgroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_h', icon, 'l_h_b_bg').color
|
||||
property color backgroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_p', icon, 'l_p_b_bg').color
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'l_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'l_h_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'l_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'l_h_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'l_n_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'l_p_b_fg').color
|
||||
|
||||
property color foregroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_n', icon, 'l_n_b_fg').color
|
||||
property color foregroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_h', icon, 'l_h_b_fg').color
|
||||
property color foregroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_p', icon, 'l_p_b_fg').color
|
||||
// Old color: l_n_b_bg
|
||||
property color backgroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_n', icon, 'ai').color
|
||||
property color backgroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_h', icon, 'ai').color
|
||||
property color backgroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_p', icon, 'ai').color
|
||||
|
||||
property color foregroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_n', icon, 'ai').color
|
||||
property color foregroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_h', icon, 'ai').color
|
||||
property color foregroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_p', icon, 'ai').color
|
||||
}
|
||||
|
||||
property int padding: 8
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
pragma Singleton
|
||||
import QtQml 2.2
|
||||
|
||||
import Units 1.0
|
||||
import ColorsList 1.0
|
||||
|
||||
// =============================================================================
|
||||
|
||||
QtObject {
|
||||
property string sectionName : 'ChatFilePreview'
|
||||
property int height: 160
|
||||
|
||||
property QtObject filePreview: QtObject{
|
||||
id: filePreviewObject
|
||||
property int heightMargins: 60
|
||||
property real format: 16/9
|
||||
|
||||
property string name: 'filePreview'
|
||||
property string icon: 'menu_reply_custom'
|
||||
property color backgroundColor: ColorsList.add(sectionName+'_'+name+'_bg', 'e').color
|
||||
property color headerTextColor: ColorsList.add(sectionName+'_'+name+'_header_fg', 'i').color
|
||||
property color iconColor: ColorsList.add(sectionName+'_'+name+'_header_fg', 'i').color
|
||||
property color textColor: ColorsList.add(sectionName+'_'+name+'_fg', 'd').color
|
||||
property int pointSize: Units.dp * 9
|
||||
property int headerPointSize: Units.dp * 9
|
||||
property QtObject removeButton: QtObject{
|
||||
property int iconSize: 30
|
||||
property string name : 'remove'
|
||||
property string icon : 'close_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_b_n', icon, 's_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_b_h', icon, 's_h_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_b_p', icon, 's_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_f_n', icon, 's_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_f_h', icon, 's_h_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_f_p', icon, 's_p_b_fg').color
|
||||
}
|
||||
property QtObject closeButton: QtObject{
|
||||
property int iconSize: 30
|
||||
property string name : 'close'
|
||||
property string icon : 'close_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_b_n', icon, 'l_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_b_h', icon, 'l_h_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_b_p', icon, 'l_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_f_n', icon, 'l_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_f_h', icon, 'l_h_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+filePreviewObject.name+'_'+name+'_f_p', icon, 'l_p_b_fg').color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,10 @@ QtObject {
|
|||
property string sectionName : 'Chat'
|
||||
property color color: ColorsList.add(sectionName, 'q').color
|
||||
property string copyTextIcon : 'copy_custom'
|
||||
property int rightButtonMargin: 15
|
||||
property int rightButtonSize: 30
|
||||
property int rightButtonLMargin: 10
|
||||
property int separatorHeight: 2
|
||||
|
||||
property QtObject sectionHeading: QtObject {
|
||||
property int padding: 5
|
||||
|
|
@ -45,6 +49,10 @@ QtObject {
|
|||
property color color: ColorsList.add(sectionName+'_send_border', 'f').color
|
||||
property int width: 1
|
||||
}
|
||||
property QtObject backgroundBorder: QtObject {
|
||||
property color color: ColorsList.add(sectionName+'_send_background_border', 'ag').color
|
||||
property int width: 2
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject composingText: QtObject {
|
||||
|
|
@ -64,7 +72,7 @@ QtObject {
|
|||
property int pointSize: Units.dp * 9
|
||||
property int headerPointSize: Units.dp * 9
|
||||
property QtObject closeButton: QtObject{
|
||||
property int iconSize: 30
|
||||
property int iconSize: rightButtonSize
|
||||
property string name : 'close'
|
||||
property string icon : 'close_custom'
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+replyPreviewObject.name+'_'+name+'_b_n', icon, 'l_n_b_bg').color
|
||||
|
|
@ -94,6 +102,11 @@ QtObject {
|
|||
property int lineHeight: 30
|
||||
property int metaWidth: 40
|
||||
|
||||
property QtObject separator: QtObject {
|
||||
property color color: ColorsList.add(sectionName+'_separator_border', 'g10').color
|
||||
property int width: 2
|
||||
}
|
||||
|
||||
property QtObject menu: QtObject {
|
||||
property int iconSize: 22
|
||||
property string name : 'menu'
|
||||
|
|
@ -164,7 +177,7 @@ QtObject {
|
|||
}
|
||||
|
||||
property QtObject message: QtObject {
|
||||
property int padding: 10
|
||||
property int padding: 8
|
||||
property int radius: 4
|
||||
|
||||
property QtObject extraContent: QtObject {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ singleton RequestBlockStyle 1.0 Blocks/RequestBlockStyle.qml
|
|||
singleton ChatStyle 1.0 Chat/ChatStyle.qml
|
||||
singleton ChatAudioMessageStyle 1.0 Chat/ChatAudioMessageStyle.qml
|
||||
singleton ChatAudioPreviewStyle 1.0 Chat/ChatAudioPreviewStyle.qml
|
||||
singleton ChatFilePreviewStyle 1.0 Chat/ChatFilePreviewStyle.qml
|
||||
singleton ChatForwardMessageStyle 1.0 Chat/ChatForwardMessageStyle.qml
|
||||
singleton ChatReplyMessageStyle 1.0 Chat/ChatReplyMessageStyle.qml
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Rectangle {
|
|||
property string _selectedSipAddress
|
||||
property bool showHistoryButton : true
|
||||
property bool updateSelectionModels : true
|
||||
property bool isFilterVisible: searchView.visible || filterView.visible
|
||||
property bool isFilterVisible: searchView.visible || showFilterView
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ Rectangle {
|
|||
signal showHistoryRequest()
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
property bool showFilterView : false
|
||||
color: TimelineStyle.color
|
||||
|
||||
ColumnLayout {
|
||||
|
|
@ -68,7 +68,7 @@ Rectangle {
|
|||
id:showHistory
|
||||
anchors.fill:parent
|
||||
onClicked: {
|
||||
filterView.visible = !filterView.visible
|
||||
timeline.showFilterView = !timeline.showFilterView
|
||||
}
|
||||
}
|
||||
RowLayout{
|
||||
|
|
@ -99,7 +99,7 @@ Rectangle {
|
|||
MouseArea{
|
||||
anchors.fill:parent
|
||||
onClicked:{
|
||||
filterView.visible = !filterView.visible
|
||||
timeline.showFilterView = !timeline.showFilterView
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -146,13 +146,13 @@ Rectangle {
|
|||
// Filter.
|
||||
// -------------------------------------------------------------------------
|
||||
Rectangle{
|
||||
id:filterView
|
||||
id:exhaustiveFilterView
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: filterChoices.height
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
border.color: TimelineStyle.filterField.borderColor
|
||||
border.width: 2
|
||||
visible:false
|
||||
visible: timeline.showFilterView && !SettingsModel.useMinimalTimelineFilter
|
||||
|
||||
ColumnLayout{
|
||||
id:filterChoices
|
||||
|
|
@ -234,6 +234,75 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
id:minimalFilterView
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: minimalFilterChoices.height
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
border.color: TimelineStyle.filterField.borderColor
|
||||
border.width: 2
|
||||
visible: timeline.showFilterView && SettingsModel.useMinimalTimelineFilter
|
||||
|
||||
ColumnLayout{
|
||||
id:minimalFilterChoices
|
||||
anchors.leftMargin: 20
|
||||
anchors.left:parent.left
|
||||
anchors.right:parent.right
|
||||
spacing:-4
|
||||
function getFilterFlags(){
|
||||
return securedCheckBox.getValue() | groupCheckBox.getValue() | conferenceCheckBox.getValue();
|
||||
}
|
||||
CheckBoxText {
|
||||
id: securedCheckBox
|
||||
Layout.fillWidth: true
|
||||
visible: SettingsModel.secureChatEnabled && SettingsModel.standardChatEnabled
|
||||
//: 'Secure rooms' : Filter item. Selecting it will show all secure rooms.
|
||||
text: qsTr('timelineFilterSecureRooms')
|
||||
|
||||
onClicked: {
|
||||
timeline.model.filterFlags = minimalFilterChoices.getFilterFlags()
|
||||
}
|
||||
function getValue(){
|
||||
if( checked)
|
||||
return TimelineProxyModel.SecureChatRoom
|
||||
else
|
||||
return 0
|
||||
}
|
||||
}
|
||||
CheckBoxText {
|
||||
id: groupCheckBox
|
||||
Layout.fillWidth: true
|
||||
visible: SettingsModel.secureChatEnabled || SettingsModel.standardChatEnabled
|
||||
//: 'Chat groups' : Filter item. Selecting it will show all chat groups (with more than one participant).
|
||||
text: qsTr('timelineFilterChatGroups')
|
||||
|
||||
onClicked: {
|
||||
timeline.model.filterFlags = minimalFilterChoices.getFilterFlags()
|
||||
}
|
||||
function getValue(){
|
||||
if( checked)
|
||||
return TimelineProxyModel.GroupChatRoom
|
||||
else
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
CheckBoxText {
|
||||
id: conferenceCheckBox
|
||||
Layout.fillWidth: true
|
||||
visible: false
|
||||
//: 'Conferences' : Filter item. Selecting it will show all conferences.
|
||||
text: qsTr('timelineFilterConferences')
|
||||
|
||||
onClicked: {
|
||||
timeline.model.filterFlags = minimalFilterChoices.getFilterFlags()
|
||||
}
|
||||
function getValue(){
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------
|
||||
// Search.
|
||||
// -------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ ContactDescription 1.0 Contact/ContactDescription.qml
|
|||
|
||||
SipAddressDialog 1.0 Dialog/SipAddressDialog.qml
|
||||
|
||||
FileView 1.0 File/FileView.qml
|
||||
|
||||
History 1.0 History/History.qml
|
||||
|
||||
SipAddressesMenu 1.0 Menus/SipAddressesMenu.qml
|
||||
|
|
|
|||
|
|
@ -204,11 +204,9 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
TooltipArea {
|
||||
text: !incall.call.recording
|
||||
tooltipText: !incall.call.recording
|
||||
? qsTr('startRecordingLabel')
|
||||
: qsTr('stopRecordingLabel')
|
||||
}
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
|
|
|
|||
|
|
@ -266,11 +266,9 @@ Window {
|
|||
? call.startRecording()
|
||||
: call.stopRecording()
|
||||
|
||||
TooltipArea {
|
||||
text: !recordingSwitch.recording
|
||||
tooltipText: !recordingSwitch.recording
|
||||
? qsTr('startRecordingLabel')
|
||||
: qsTr('stopRecordingLabel')
|
||||
}
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
|
|
@ -373,7 +371,7 @@ Window {
|
|||
ActionButton {
|
||||
isCustom: true
|
||||
backgroundRadius: 90
|
||||
colorSet: CallFullscreenStyle.buttons.cameraOn
|
||||
colorSet: call && call.videoEnabled ? CallStyle.buttons.cameraOn : CallStyle.buttons.cameraOff
|
||||
updating: call && call.updating
|
||||
|
||||
iconSize: CallFullscreenStyle.actionArea.iconSize
|
||||
|
|
|
|||
|
|
@ -69,25 +69,25 @@ ColumnLayout {
|
|||
text: qsTr('homeDescription')
|
||||
}
|
||||
|
||||
CheckBoxText{
|
||||
id: cguCheckBox
|
||||
Layout.topMargin: 10
|
||||
Layout.maximumWidth: infoItem.width
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: applicationVendor != '' && ConstantsCpp.CguUrl != '' && ConstantsCpp.PrivatePolicyUrl != ''
|
||||
checked: SettingsModel.cguAccepted
|
||||
onCheckedChanged: SettingsModel.cguAccepted = checked
|
||||
|
||||
//: 'I accept %1's %2terms of use%3 and %4privacy policy%5' : where %1 is the vendor name and other %n are internal keywords that encapsulate links.
|
||||
text: qsTr('homeCgu').arg(applicationVendor).arg('< a href="'+ConstantsCpp.CguUrl+'">').arg('</a>').arg('<a href="'+ConstantsCpp.PrivatePolicyUrl+'">').arg('</a>')
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Buttons.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
CheckBoxText{
|
||||
id: cguCheckBox
|
||||
Layout.bottomMargin: 10
|
||||
Layout.maximumWidth: infoItem.width
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: applicationVendor != '' && ConstantsCpp.CguUrl != '' && ConstantsCpp.PrivatePolicyUrl != ''
|
||||
checked: SettingsModel.cguAccepted
|
||||
onCheckedChanged: SettingsModel.cguAccepted = checked
|
||||
|
||||
//: 'I accept %1's %2terms of use%3 and %4privacy policy%5' : where %1 is the vendor name and other %n are internal keywords that encapsulate links.
|
||||
text: qsTr('homeCgu').arg(applicationVendor).arg('< a href="'+ConstantsCpp.CguUrl+'">').arg('</a>').arg('<a href="'+ConstantsCpp.PrivatePolicyUrl+'">').arg('</a>')
|
||||
}
|
||||
GridView {
|
||||
id: buttons
|
||||
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ ColumnLayout {
|
|||
anchors.leftMargin: 50
|
||||
anchors.topMargin: 10
|
||||
anchors.bottomMargin: 10
|
||||
visible: false
|
||||
visible: true
|
||||
|
||||
TextField {
|
||||
id:searchBar
|
||||
|
|
@ -503,14 +503,13 @@ ColumnLayout {
|
|||
width: parent.width-14
|
||||
icon: 'close_custom'
|
||||
overwriteColor: ConversationStyle.filters.iconColor
|
||||
persistentIcon: true
|
||||
showWhenEmpty: false
|
||||
//: 'Search in messages' : this is a placeholder when searching something in the timeline list
|
||||
placeholderText: qsTr('searchMessagesPlaceholder')
|
||||
|
||||
onTextChanged: searchDelay.restart()
|
||||
onIconClicked: {
|
||||
searchView.visible = false
|
||||
chatRoomProxyModel.filterText = ''
|
||||
searchView.text = ''
|
||||
}
|
||||
font.pointSize: ConversationStyle.filters.pointSize
|
||||
|
||||
|
|
|
|||
|
|
@ -222,6 +222,20 @@ TabContainer {
|
|||
}
|
||||
}
|
||||
}
|
||||
FormGroup {
|
||||
//: 'Minimal Timeline filter'
|
||||
label: qsTr('minimalTimelineFilterLabel')
|
||||
|
||||
Switch {
|
||||
checked: SettingsModel.useMinimalTimelineFilter
|
||||
|
||||
onClicked: SettingsModel.useMinimalTimelineFilter = !checked
|
||||
TooltipArea{
|
||||
//: 'Show a minimal version of what to display in timeline.' :
|
||||
text: qsTr('minimalTimelineFilterTooltip')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FormLine {
|
||||
maxItemWidth: parent.width
|
||||
|
|
|
|||
|
|
@ -113,6 +113,15 @@ QtObject {
|
|||
property color foregroundDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_d', icon, 'me_d_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
|
||||
property color backgroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_n', icon, 'me_n_b_inv_bg').color
|
||||
property color backgroundHiddenPartDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_d', icon, 'me_d_b_inv_bg').color
|
||||
property color backgroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_h', icon, 'me_h_b_inv_bg').color
|
||||
property color backgroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_p', icon, 'me_p_b_inv_bg').color
|
||||
property color foregroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_n', icon, 'me_n_b_inv_fg').color
|
||||
property color foregroundHiddenPartDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_d', icon, 'me_d_b_inv_fg').color
|
||||
property color foregroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_h', icon, 'me_h_b_inv_fg').color
|
||||
property color foregroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_p', icon, 'me_p_b_inv_fg').color
|
||||
}
|
||||
property QtObject telKeyad: QtObject {
|
||||
property int iconSize: 16
|
||||
|
|
|
|||
|
|
@ -113,6 +113,15 @@ QtObject {
|
|||
property color foregroundDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_d', icon, 'me_d_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color
|
||||
|
||||
property color backgroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_n', icon, 'me_n_b_inv_bg').color
|
||||
property color backgroundHiddenPartDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_d', icon, 'me_d_b_inv_bg').color
|
||||
property color backgroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_h', icon, 'me_h_b_inv_bg').color
|
||||
property color backgroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_p', icon, 'me_p_b_inv_bg').color
|
||||
property color foregroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_n', icon, 'me_n_b_inv_fg').color
|
||||
property color foregroundHiddenPartDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_d', icon, 'me_d_b_inv_fg').color
|
||||
property color foregroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_h', icon, 'me_h_b_inv_fg').color
|
||||
property color foregroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_p', icon, 'me_p_b_inv_fg').color
|
||||
}
|
||||
property QtObject telKeyad: QtObject {
|
||||
property int iconSize: 16
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit b2a3ebaffde438fb23c7b7d91327a35fa3a0f23d
|
||||
Subproject commit 18cd2436eda9cb72023c4727691e4a2b764966d3
|
||||