messagewebview: chatview message bar qml replacement - ui
1. New emoji picker by customizing emoji.js 2. New message bar ui (textarea, buttons, tooltips) 3. New pending files transfer container 4. Use MaterialToolTip for all PushButton Change-Id: I05d0531c65c019ced42b04668a780919c8a4fac3
|
@ -72,7 +72,8 @@ set(COMMON_SOURCES
|
|||
${SRC_DIR}/conversationlistmodelbase.cpp
|
||||
${SRC_DIR}/conversationlistmodel.cpp
|
||||
${SRC_DIR}/searchresultslistmodel.cpp
|
||||
${SRC_DIR}/calloverlaymodel.cpp)
|
||||
${SRC_DIR}/calloverlaymodel.cpp
|
||||
${SRC_DIR}/filestosendlistmodel.cpp)
|
||||
|
||||
set(COMMON_HEADERS
|
||||
${SRC_DIR}/avatarimageprovider.h
|
||||
|
@ -128,7 +129,8 @@ set(COMMON_HEADERS
|
|||
${SRC_DIR}/conversationlistmodelbase.h
|
||||
${SRC_DIR}/conversationlistmodel.h
|
||||
${SRC_DIR}/searchresultslistmodel.h
|
||||
${SRC_DIR}/calloverlaymodel.h)
|
||||
${SRC_DIR}/calloverlaymodel.h
|
||||
${SRC_DIR}/filestosendlistmodel.h)
|
||||
|
||||
set(QML_LIBS
|
||||
Qt5::Quick
|
||||
|
|
22
images/icons/emoji_black-24dp.svg
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M12,2.1c-5.4,0-9.9,4.4-9.9,9.9s4.4,9.9,9.9,9.9s9.9-4.4,9.9-9.9S17.4,2.1,12,2.1z M12,20.7c-4.8,0-8.7-3.9-8.7-8.7
|
||||
S7.2,3.3,12,3.3s8.7,3.9,8.7,8.7S16.8,20.7,12,20.7z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M7.4,13.3c-0.2,0-0.4,0.1-0.5,0.2c-0.1,0.1-0.1,0.3-0.1,0.5c0,0.1,0.1,0.3,0.2,0.4c1.4,1,3.1,1.5,4.9,1.5s3.4-0.5,4.9-1.5
|
||||
c0.1-0.1,0.2-0.2,0.3-0.4c0-0.2,0-0.3-0.1-0.4c-0.2-0.3-0.5-0.3-0.8-0.1c-1.2,0.8-2.7,1.3-4.2,1.3s-3-0.4-4.2-1.3
|
||||
C7.7,13.3,7.5,13.3,7.4,13.3z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M8,8.9c-0.4,0-0.8,0.3-0.8,0.8c0,0.4,0.3,0.8,0.8,0.8s0.8-0.3,0.8-0.8C8.8,9.2,8.5,8.9,8,8.9z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M16,8.9c-0.4,0-0.8,0.4-0.8,0.8c0,0.5,0.3,0.8,0.8,0.8c0.4,0,0.8-0.3,0.8-0.8C16.8,9.2,16.4,8.9,16,8.9z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
8
images/icons/file_black-24dp.svg
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<path d="M14.2,2.3C14,2.1,13.7,2,13.4,2H5.5C4.8,2,4.3,2.5,4.3,3.2v6.3v1.6v9.7c0,0.7,0.5,1.2,1.2,1.2h13.1c0.7,0,1.2-0.5,1.2-1.2
|
||||
V18V8.4c0-0.3-0.1-0.6-0.3-0.8L14.2,2.3z M18,7.7H14c0,0,0,0,0,0V3.7L18,7.7z M18.6,20.9C18.6,20.9,18.6,20.9,18.6,20.9l-13.1,0
|
||||
c0,0,0,0,0,0v-9.7V9.5V3.2c0,0,0,0,0,0h7.4v4.5c0,0.7,0.5,1.2,1.2,1.2h4.5v9.2V20.9z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 690 B |
Before Width: | Height: | Size: 327 B |
Before Width: | Height: | Size: 487 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"><path d="M0 0h24v24H0z" fill="none"/><path d="M6 2c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6H6zm7 7V3.5L18.5 9H13z"/></svg>
|
Before Width: | Height: | Size: 237 B |
9
images/icons/link_black-24dp.svg
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<path d="M16,5.6c-0.4,0-0.7,0.4-0.7,0.7v11.1c0,1.8-1.5,3.3-3.3,3.3s-3.3-1.5-3.3-3.3V5.6c0-1.2,1-2.1,2.1-2.1C12,3.4,13,4.4,13,5.6
|
||||
V16c0,0.5-0.4,0.9-0.9,0.9c-0.4,0-0.9-0.4-0.9-0.9V6.8c0-0.4-0.4-0.7-0.7-0.7c-0.4,0-0.7,0.3-0.7,0.7V16c0,1.2,1.1,2.3,2.3,2.3
|
||||
s2.3-1.1,2.3-2.3V5.6c0-1.9-1.6-3.6-3.6-3.6S7.2,3.6,7.2,5.6v11.7c0,2.6,2.1,4.8,4.8,4.8s4.8-2.1,4.8-4.8v-11
|
||||
C16.8,5.8,16.4,5.6,16,5.6z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 743 B |
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Message audio</title>
|
||||
<g id="Icones_Outline" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Message-audio" stroke="#000000">
|
||||
<path d="M12,2.875 C14.5197992,2.875 16.8010492,3.89635041 18.4523494,5.54765062 C20.1036496,7.19895083 21.125,9.48020083 21.125,12 L21.125,12 L21.125,21.125 L12,21.125 C9.48020083,21.125 7.19895083,20.1036496 5.54765062,18.4523494 C3.89635041,16.8010492 2.875,14.5197992 2.875,12 C2.875,9.48020083 3.89635041,7.19895083 5.54765062,5.54765062 C7.19895083,3.89635041 9.48020083,2.875 12,2.875 Z" id="Rectangle-Copy-3" stroke-width="1.75"></path>
|
||||
<g id="Group" transform="translate(9.000000, 7.000000)" fill-rule="nonzero">
|
||||
<path d="M3.2826376,0.724537696 C3.66238148,0.724537696 4.00643194,0.87901528 4.25561937,1.12820271 C4.5048068,1.37739014 4.65928439,1.7214406 4.65928439,2.10118448 L4.65928439,2.10118448 L4.65928439,5.11026918 C4.65928439,5.49001273 4.50480658,5.83406323 4.25561904,6.08325078 C4.00643165,6.33243816 3.66238135,6.48691596 3.2826376,6.48691596 C2.90289382,6.48691596 2.55884347,6.33243814 2.30965606,6.08325074 C2.0604685,5.8340632 1.90599067,5.49001272 1.90599067,5.11026918 L1.90599067,5.11026918 L1.90599067,2.10118448 C1.90599067,1.72144061 2.06046828,1.37739017 2.30965572,1.12820274 C2.55884318,0.879015295 2.90289369,0.724537696 3.2826376,0.724537696 Z" id="Path" stroke-width="1.35"></path>
|
||||
<path d="M0.277829768,3.46892297 C0.131747046,3.46666758 -0.00228293577,3.60069619 -2.6215198e-05,3.74677891 L-2.6215198e-05,5.1145366 C-2.6215198e-05,6.83681201 1.32262269,8.24623865 3.00908469,8.38435551 L3.00908469,9.35033921 L1.91487307,9.35033921 C1.76379391,9.35033921 1.64132017,9.47280884 1.64132017,9.62389211 C1.64132017,9.77497538 1.76379391,9.89744502 1.91487307,9.89744502 L4.65040212,9.89744502 C4.80148129,9.89744502 4.92395503,9.77497538 4.92395503,9.62389211 C4.92395503,9.47280884 4.80148129,9.35064011 4.65040212,9.35033921 L3.5561905,9.35033921 L3.5561905,8.38435551 C5.24265237,8.24623865 6.56529592,6.83681201 6.56529592,5.1145366 L6.56529592,3.74677891 C6.56731043,3.60225818 6.43625533,3.46933062 6.29171955,3.46933062 C6.14718377,3.46933062 6.01612321,3.60225818 6.01816665,3.74677891 L6.01816665,5.1145366 C6.01816665,6.63475216 4.80285179,7.85006565 3.2826376,7.85006565 C1.76242204,7.85006565 0.547108409,6.63475216 0.547108409,5.1145366 L0.547108409,3.74677891 C0.549351543,3.60354661 0.421062069,3.47118667 0.277829768,3.46892297 Z" id="Path" stroke-width="0.75" fill="#000000"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.7 KiB |
18
images/icons/message_audio_black-24dp.svg
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M19.1,4.9C17.2,3,14.7,2,12,2S6.8,3,4.9,4.9S2,9.3,2,12s1,5.2,2.9,7.1S9.3,22,12,22h10V12C22,9.3,21,6.8,19.1,4.9z
|
||||
M20.6,20.6H12c-2.3,0-4.4-0.9-6.1-2.5c-1.6-1.6-2.5-3.8-2.5-6.1s0.9-4.4,2.5-6.1C7.6,4.3,9.7,3.4,12,3.4s4.4,0.9,6.1,2.5
|
||||
c1.6,1.6,2.5,3.8,2.5,6.1V20.6z"/>
|
||||
<path d="M15,10.3c-0.1,0.1-0.2,0.2-0.2,0.4v1.4c0,1.4-1.1,2.5-2.5,2.5s-2.5-1.1-2.5-2.5v-1.4c0-0.1-0.1-0.3-0.2-0.4
|
||||
c-0.1-0.1-0.2-0.2-0.4-0.2l0,0c-0.2,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.2-0.2,0.4v1.4c0,1.8,1.3,3.3,3.1,3.6v0.5h-0.9
|
||||
c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5h2.8c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5h-0.9v-0.5c1.7-0.3,3.1-1.8,3.1-3.6v-1.4
|
||||
c0-0.1-0.1-0.3-0.2-0.4C15.5,10.2,15.2,10.1,15,10.3z M9.2,10.4L9.2,10.4L9.2,10.4L9.2,10.4L9.2,10.4z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M12.3,13.9c-1,0-1.8-0.8-1.8-1.8V9c0-1,0.8-1.8,1.8-1.8S14.1,8,14.1,9v3.2C14.1,13.2,13.3,13.9,12.3,13.9z M12.3,8.4
|
||||
c-0.3,0-0.6,0.2-0.6,0.6v3.2c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6V9C12.9,8.7,12.6,8.4,12.3,8.4z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Message video</title>
|
||||
<g id="Icones_Outline" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Message-video" stroke="#000000">
|
||||
<path d="M12,2.875 C14.5197992,2.875 16.8010492,3.89635041 18.4523494,5.54765062 C20.1036496,7.19895083 21.125,9.48020083 21.125,12 L21.125,12 L21.125,21.125 L12,21.125 C9.48020083,21.125 7.19895083,20.1036496 5.54765062,18.4523494 C3.89635041,16.8010492 2.875,14.5197992 2.875,12 C2.875,9.48020083 3.89635041,7.19895083 5.54765062,5.54765062 C7.19895083,3.89635041 9.48020083,2.875 12,2.875 Z" id="Rectangle-Copy-3" stroke-width="1.75"></path>
|
||||
<g id="Ico_Camera" transform="translate(7.000000, 8.000000)" stroke-width="1.5">
|
||||
<path d="M4.6832026,4.0582026 C5.29164453,3.875 5.4463271,3.94580015 5.55869578,4.05817556 C5.67108489,4.17057139 5.74188438,4.32529267 5.74188438,4.49598322 C5.74188438,4.66664052 5.67108115,4.8213337 5.55870252,4.93371234 C5.44633138,5.04608348 5.29164686,5.11688438 5.12098322,5.11688438 C4.95029879,5.11688438 4.7955881,5.04607082 4.68319586,4.93368531 C4.57081655,4.82131272 4.5,4.66663207 4.5,4.49598322 C4.5,4.32530112 4.57081281,4.17059238 4.6832026,4.0582026 Z" id="Path"></path>
|
||||
<path d="M5.8691951,0.75 L6.46662157,1.94485294 L8.96139706,1.94485294 L9.04779412,7.28860294 L0.836397059,7.375 L0.75,2.03125 L3.33117255,1.94485294 L3.92859902,0.75 L5.8691951,0.75 Z" id="Path"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.6 KiB |
20
images/icons/message_video_black-24dp.svg
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<g>
|
||||
<g id="Rectangle-Copy-3">
|
||||
<path d="M22,22H12c-2.7,0-5.2-1-7.1-2.9C3,17.2,2,14.7,2,12c0-2.7,1-5.2,2.9-7.1S9.3,2,12,2c2.7,0,5.2,1,7.1,2.9
|
||||
C21,6.8,22,9.3,22,12V22z M12,3.4c-2.3,0-4.4,0.9-6.1,2.5C4.3,7.6,3.4,9.7,3.4,12c0,2.3,0.9,4.4,2.5,6.1c1.6,1.6,3.8,2.5,6.1,2.5
|
||||
h8.6V12c0-2.3-0.9-4.4-2.5-6.1C16.4,4.3,14.3,3.4,12,3.4z"/>
|
||||
</g>
|
||||
<g id="Ico_Camera" transform="translate(7.000000, 9.000000)">
|
||||
<g id="Path">
|
||||
<path d="M7.1,7.7H0.4c-0.8,0-1.2-0.5-1.2-1V0.3c0-0.4,0.4-0.9,1.1-1l6.7,0c0.7,0,1.1,0.5,1.1,1v0.6l1.1-0.6C9.6,0,10,0,10.3,0.2
|
||||
c0.2,0.1,0.5,0.3,0.5,0.8v5c0,0.5-0.3,0.8-0.5,0.9C10,7,9.6,7,9.3,6.8L8.2,6.2v0.6C8.2,7.2,7.8,7.7,7.1,7.7z M0.5,6.4l6.4,0V5.1
|
||||
c0-0.2,0.1-0.4,0.3-0.6c0.2-0.1,0.4-0.1,0.6,0l1.6,0.9V1.6L7.9,2.5c-0.2,0.1-0.4,0.1-0.6,0C7,2.4,6.9,2.2,6.9,1.9V0.6l-6.4,0V6.4
|
||||
z M10,5.7L10,5.7C10,5.7,10,5.7,10,5.7z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Send</title>
|
||||
<g id="Icones_Outline" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Send" fill-rule="nonzero" stroke="#000000" stroke-width="1.75">
|
||||
<g id="noun_send_3383765" transform="translate(2.000000, 4.000000)">
|
||||
<path d="M1.04917102,1.91025133 L18.2901355,8.17133814 L0.960533446,15.103179 L1.66342176,9.48007246 L7.92572464,9.48007246 C8.2924137,9.48007246 8.62438833,9.33144236 8.86469071,9.09113998 C9.10499308,8.85083761 9.25362319,8.51886297 9.25362319,8.15217391 C9.25362319,7.78548485 9.10499308,7.45351022 8.86469071,7.21320784 C8.62438833,6.97290547 8.2924137,6.82427536 7.92572464,6.82427536 L7.92572464,6.82427536 L1.66342207,6.82427536 L1.04917102,1.91025133 Z" id="Path"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1,000 B |
12
images/icons/send_black-24dp.svg
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<g id="Send_Black_24dp">
|
||||
<g id="noun_send_1433498" transform="translate(2.000000, 3.000000)">
|
||||
<path id="Shape" d="M20,9c0-0.3-0.2-0.5-0.4-0.6L1.1-0.2C0.8-0.3,0.4-0.2,0.2,0s-0.3,0.6-0.1,0.9L4,9l-3.9,8.1
|
||||
C-0.1,17.4,0,17.8,0.2,18c0.2,0.2,0.6,0.3,0.9,0.2l18.5-8.5C19.8,9.6,20,9.3,20,9L20,9z M17.4,9l-15,6.9l3.2-6.5
|
||||
c0.1-0.2,0.1-0.5,0-0.7L2.4,2.1L17.4,9z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 725 B |
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Link</title>
|
||||
<g id="Icones" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Link" fill="#000000" fill-rule="nonzero" stroke="#000000" stroke-width="0.5">
|
||||
<g id="noun_attach_998912" transform="translate(11.981262, 12.084524) rotate(25.000000) translate(-11.981262, -12.084524) translate(6.981262, 2.084524)">
|
||||
<path d="M4.58333333,20 C2.05607096,20 0,17.943929 0,15.4166667 L0,3.33333333 C0,1.49536133 1.49536133,0 3.33333333,0 C5.17130533,0 6.66666667,1.49536133 6.66666667,3.33333333 L6.66666667,14.1666667 C6.66666667,15.3153483 5.73201496,16.25 4.58333333,16.25 C3.43465171,16.25 2.5,15.3153483 2.5,14.1666667 L2.5,4.56075033 C2.5,4.33064779 2.68636067,4.14408367 2.91666667,4.14408367 C3.14697267,4.14408367 3.33333333,4.33064779 3.33333333,4.56075033 L3.33333333,14.1666667 C3.33333333,14.855957 3.89404296,15.4166667 4.58333333,15.4166667 C5.27262371,15.4166667 5.83333333,14.855957 5.83333333,14.1666667 L5.83333333,3.33333333 C5.83333333,1.95475258 4.71191404,0.833333333 3.33333333,0.833333333 C1.95475262,0.833333333 0.833333333,1.95475263 0.833333333,3.33333333 L0.833333333,15.4166667 C0.833333333,17.4843343 2.51546225,19.1666667 4.58333333,19.1666667 C6.65120442,19.1666667 8.33333333,17.4843343 8.33333333,15.4166667 L8.33333333,4.04276529 C8.33333333,3.81266275 8.519694,3.62609863 8.75,3.62609863 C8.980306,3.62609863 9.16666667,3.81266275 9.16666667,4.04276529 L9.16666667,15.4166667 C9.16666667,17.943929 7.11059571,20 4.58333333,20 Z" id="Path"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.7 KiB |
9
qml.qrc
|
@ -146,5 +146,14 @@
|
|||
<file>src/commoncomponents/contextmenu/GeneralMenuSeparator.qml</file>
|
||||
<file>src/mainview/components/ParticipantOverlayButton.qml</file>
|
||||
<file>src/mainview/components/ParticipantControlLayout.qml</file>
|
||||
<file>src/mainview/components/MessageWebViewFooter.qml</file>
|
||||
<file>src/commoncomponents/emojipicker/EmojiPicker.qml</file>
|
||||
<file>src/commoncomponents/emojipicker/emojiPickerLoader.js</file>
|
||||
<file>src/commoncomponents/emojipicker/emojiPickerLoader.html</file>
|
||||
<file>src/commoncomponents/emojipicker/emoji.js</file>
|
||||
<file>src/commoncomponents/JamiTextArea.qml</file>
|
||||
<file>src/mainview/components/FilesToSendDelegate.qml</file>
|
||||
<file>src/mainview/components/MessageBar.qml</file>
|
||||
<file>src/mainview/components/FilesToSendContainer.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
<file>images/icons/ic_video_call_24px.svg</file>
|
||||
<file>images/icons/ic_videocam_off_white_24dp.png</file>
|
||||
<file>images/icons/ic_videocam_white.png</file>
|
||||
<file>images/icons/ic_voicemail_white_24dp_2x.png</file>
|
||||
<file>images/icons/ic_call_end_white_24px.svg</file>
|
||||
<file>images/icons/round-add-24px.svg</file>
|
||||
<file>images/icons/round-arrow_drop_down-24px.svg</file>
|
||||
|
@ -84,7 +83,6 @@
|
|||
<file>images/icons/round-add_a_photo-24px.svg</file>
|
||||
<file>images/icons/ic_mic_white_24dp.png</file>
|
||||
<file>images/icons/ic_play_white_24dp.png</file>
|
||||
<file>images/icons/ic_voicemail_black_24dp_2x_.png</file>
|
||||
<file>images/icons/av_icons/delete-24px.svg</file>
|
||||
<file>images/icons/av_icons/fiber_manual_record-24px.svg</file>
|
||||
<file>images/icons/av_icons/play_circle_outline-24px.svg</file>
|
||||
|
@ -99,7 +97,6 @@
|
|||
<file>images/icons/person-24px.svg</file>
|
||||
<file>images/icons/drafts-24px.svg</file>
|
||||
<file>images/icons/router-24px.svg</file>
|
||||
<file>images/icons/insert_drive_file-24dp.svg</file>
|
||||
<file>images/icons/arrow_back-white-24dp.svg</file>
|
||||
<file>images/icons/videocam-24px.svg</file>
|
||||
<file>images/icons/qr_code-24px.svg</file>
|
||||
|
@ -122,10 +119,9 @@
|
|||
<file>images/logo-jami-standard-coul-white.svg</file>
|
||||
<file>images/icons/moderator.svg</file>
|
||||
<file>images/icons/star_outline-24px.svg</file>
|
||||
<file>images/icons/send_file-24px.svg</file>
|
||||
<file>images/icons/message_video-24px.svg</file>
|
||||
<file>images/icons/message_audio-24px.svg</file>
|
||||
<file>images/icons/send-24px.svg</file>
|
||||
<file>images/icons/message_audio_black-24dp.svg</file>
|
||||
<file>images/icons/message_video_black-24dp.svg</file>
|
||||
<file>images/icons/send_black-24dp.svg</file>
|
||||
<file>images/icons/back-24px.svg</file>
|
||||
<file>images/icons/place_audiocall-24px.svg</file>
|
||||
<file>images/icons/add_people-24px.svg</file>
|
||||
|
@ -146,5 +142,8 @@
|
|||
<file>images/icons/spk_none_black_24dp.svg</file>
|
||||
<file>images/icons/more_vert-24dp.svg</file>
|
||||
<file>images/icons/chevron_left_black_24dp.svg</file>
|
||||
<file>images/icons/emoji_black-24dp.svg</file>
|
||||
<file>images/icons/link_black-24dp.svg</file>
|
||||
<file>images/icons/file_black-24dp.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
110
src/commoncomponents/JamiTextArea.qml
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Savoir-faire Linux
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
|
||||
import net.jami.Constants 1.0
|
||||
|
||||
import "../commoncomponents/contextmenu"
|
||||
|
||||
Flickable {
|
||||
id: root
|
||||
|
||||
property alias text: textArea.text
|
||||
|
||||
function insertText(text) {
|
||||
textArea.insert(textArea.cursorPosition, text)
|
||||
}
|
||||
|
||||
LineEditContextMenu {
|
||||
id: textAreaContextMenu
|
||||
|
||||
lineEditObj: textArea
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: contentHeight > height ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded
|
||||
}
|
||||
|
||||
contentWidth: width
|
||||
contentHeight: textArea.implicitHeight
|
||||
|
||||
interactive: true
|
||||
clip: true
|
||||
|
||||
function ensureVisible(r) {
|
||||
if (contentY >= r.y)
|
||||
contentY = r.y
|
||||
else if (contentY + height <= r.y + r.height)
|
||||
contentY = r.y + r.height - height
|
||||
}
|
||||
|
||||
TextArea.flickable: TextArea {
|
||||
id: textArea
|
||||
|
||||
padding: 0
|
||||
|
||||
verticalAlignment: TextEdit.AlignVCenter
|
||||
|
||||
font.pointSize: JamiTheme.textFontSize + 2
|
||||
font.hintingPreference: Font.PreferNoHinting
|
||||
|
||||
color: JamiTheme.textColor
|
||||
renderType: Text.NativeRendering
|
||||
wrapMode: TextEdit.Wrap
|
||||
overwriteMode: true
|
||||
selectByMouse: true
|
||||
selectionColor: JamiTheme.placeHolderTextFontColor
|
||||
textFormat: TextEdit.PlainText
|
||||
placeholderTextColor: JamiTheme.placeHolderTextFontColor
|
||||
|
||||
cursorDelegate: Rectangle {
|
||||
visible: textArea.cursorVisible
|
||||
color: JamiTheme.textColor
|
||||
width: 1
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
loops: Animation.Infinite
|
||||
running: visible
|
||||
|
||||
NumberAnimation {
|
||||
from: 1
|
||||
to: 0
|
||||
duration: JamiTheme.recordBlinkDuration
|
||||
}
|
||||
NumberAnimation {
|
||||
from: 0
|
||||
to: 1
|
||||
duration: JamiTheme.recordBlinkDuration
|
||||
}
|
||||
}
|
||||
}
|
||||
background: Rectangle {
|
||||
border.width: 0
|
||||
color: JamiTheme.transparentColor
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (event.button == Qt.RightButton)
|
||||
textAreaContextMenu.openMenuAt(event)
|
||||
}
|
||||
|
||||
onCursorRectangleChanged: root.ensureVisible(cursorRectangle)
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ Popup {
|
|||
|
||||
// convient access to closePolicy
|
||||
property bool autoClose: true
|
||||
property alias backgroundColor: container.color
|
||||
|
||||
onContentItemChanged: {
|
||||
if(root.contentItem !== null)
|
||||
|
@ -52,9 +53,7 @@ Popup {
|
|||
background: Rectangle {
|
||||
id: container
|
||||
|
||||
// TODO: this is the MaterialButton radius and should be part of
|
||||
// a theme.
|
||||
radius: 4
|
||||
radius: JamiTheme.modalPopupRadius
|
||||
width: root.width
|
||||
height: root.height
|
||||
}
|
||||
|
@ -66,7 +65,7 @@ Popup {
|
|||
horizontalOffset: 3.0
|
||||
verticalOffset: 3.0
|
||||
radius: container.radius * 4
|
||||
samples: 16
|
||||
samples: JamiTheme.modalPopupDropShadowSamples
|
||||
color: JamiTheme.shadowColor
|
||||
source: container
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ ItemDelegate {
|
|||
id: preferenceFilePathDialog
|
||||
|
||||
title: JamiStrings.selectFile
|
||||
folder: "file:///" + currentPath
|
||||
folder: JamiQmlUtils.qmlFilePrefix + currentPath
|
||||
|
||||
onAccepted: {
|
||||
var url = UtilsAdapter.getAbsPath(file.toString())
|
||||
|
|
|
@ -50,7 +50,7 @@ AbstractButton {
|
|||
property alias textHAlign: textContent.horizontalAlignment
|
||||
property bool buttonTextEnableElide: false
|
||||
|
||||
property string toolTipText: ""
|
||||
property alias toolTipText: toolTip.text
|
||||
|
||||
// State colors
|
||||
property string pressedColor: JamiTheme.pressedButtonColor
|
||||
|
@ -80,9 +80,14 @@ AbstractButton {
|
|||
hoverEnabled: true
|
||||
focusPolicy: Qt.TabFocus
|
||||
|
||||
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
ToolTip.visible: hovered && (toolTipText.length > 0)
|
||||
ToolTip.text: toolTipText
|
||||
|
||||
MaterialToolTip {
|
||||
id: toolTip
|
||||
|
||||
parent: root
|
||||
visible: hovered && (toolTipText.length > 0)
|
||||
delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
}
|
||||
|
||||
ResponsiveImage {
|
||||
id: image
|
||||
|
|
128
src/commoncomponents/emojipicker/EmojiPicker.qml
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Savoir-faire Linux
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtWebEngine 1.10
|
||||
import QtWebChannel 1.14
|
||||
|
||||
import net.jami.Constants 1.0
|
||||
import net.jami.Adapters 1.0
|
||||
|
||||
import "../"
|
||||
|
||||
ModalPopup {
|
||||
id: root
|
||||
|
||||
signal emojiIsPicked(string content)
|
||||
|
||||
backgroundColor: JamiTheme.transparentColor
|
||||
|
||||
function openEmojiPicker() {
|
||||
open()
|
||||
emojiPickerWebView.runJavaScript(
|
||||
"prepare_to_show(" + JamiTheme.darkTheme + ");")
|
||||
}
|
||||
|
||||
onClosed: {
|
||||
emojiPickerWebView.runJavaScript("prepare_to_hide();")
|
||||
}
|
||||
|
||||
contentItem: Rectangle {
|
||||
id: contentRect
|
||||
|
||||
implicitWidth: 400
|
||||
implicitHeight: 425
|
||||
|
||||
color: JamiTheme.transparentColor
|
||||
|
||||
QtObject {
|
||||
id: jsBridgeObject
|
||||
|
||||
// ID, under which this object will be known at chatview.js side.
|
||||
WebChannel.id: "jsbridge"
|
||||
|
||||
// Functions that are exposed, return code can be derived from js side
|
||||
// by setting callback function.
|
||||
function emojiIsPicked(arg) {
|
||||
root.emojiIsPicked(arg)
|
||||
}
|
||||
}
|
||||
|
||||
WebEngineView {
|
||||
id: emojiPickerWebView
|
||||
|
||||
anchors.fill: contentRect
|
||||
|
||||
backgroundColor: JamiTheme.transparentColor
|
||||
|
||||
settings.javascriptEnabled: true
|
||||
settings.javascriptCanOpenWindows: false
|
||||
settings.javascriptCanAccessClipboard: true
|
||||
settings.javascriptCanPaste: true
|
||||
settings.fullScreenSupportEnabled: true
|
||||
settings.allowRunningInsecureContent: true
|
||||
settings.localContentCanAccessRemoteUrls: false
|
||||
settings.localContentCanAccessFileUrls: false
|
||||
settings.errorPageEnabled: false
|
||||
settings.pluginsEnabled: false
|
||||
settings.screenCaptureEnabled: false
|
||||
settings.linksIncludedInFocusChain: false
|
||||
settings.localStorageEnabled: true
|
||||
|
||||
webChannel: emojiPickerWebViewChannel
|
||||
|
||||
onLoadingChanged: {
|
||||
if (loadRequest.status == WebEngineView.LoadSucceededStatus) {
|
||||
emojiPickerWebView.runJavaScript(
|
||||
UtilsAdapter.qStringFromFile(
|
||||
":qwebchannel.js"))
|
||||
emojiPickerWebView.runJavaScript(
|
||||
UtilsAdapter.qStringFromFile(
|
||||
":/src/commoncomponents/emojipicker/emoji.js"))
|
||||
emojiPickerWebView.runJavaScript(
|
||||
UtilsAdapter.qStringFromFile(
|
||||
":/src/commoncomponents/emojipicker/emojiPickerLoader.js"))
|
||||
emojiPickerWebView.runJavaScript(
|
||||
"init_emoji_picker(" + JamiTheme.darkTheme + ");")
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
profile.cachePath = UtilsAdapter.getCachePath()
|
||||
profile.persistentStoragePath = UtilsAdapter.getCachePath()
|
||||
profile.persistentCookiesPolicy = WebEngineProfile.NoPersistentCookies
|
||||
profile.httpCacheType = WebEngineProfile.NoCache
|
||||
profile.httpUserAgent = JamiStrings.httpUserAgentName
|
||||
|
||||
emojiPickerWebView.loadHtml(
|
||||
UtilsAdapter.qStringFromFile(
|
||||
":/src/commoncomponents/emojipicker/emojiPickerLoader.html"),
|
||||
":/src/commoncomponents/emojipicker/emojiPickerLoader.html")
|
||||
emojiPickerWebView.url
|
||||
= "qrc:/src/commoncomponents/emojipicker/emojiPickerLoader.html"
|
||||
}
|
||||
}
|
||||
|
||||
// Provide WebChannel by registering jsBridgeObject.
|
||||
WebChannel {
|
||||
id: emojiPickerWebViewChannel
|
||||
registeredObjects: [jsBridgeObject]
|
||||
}
|
||||
}
|
||||
}
|
19
src/commoncomponents/emojipicker/emoji.js
Normal file
7
src/commoncomponents/emojipicker/emojiPickerLoader.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body style="height: 100%; width: 100%; margin: 0; padding: 0%; overflow: hidden;"></body>
|
||||
</html>
|
47
src/commoncomponents/emojipicker/emojiPickerLoader.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
"use strict"
|
||||
|
||||
var emojiPicker = undefined
|
||||
|
||||
new QWebChannel(qt.webChannelTransport, function (channel) {
|
||||
window.jsbridge = channel.objects.jsbridge
|
||||
})
|
||||
|
||||
/* exported init_emoji_picker */
|
||||
function init_emoji_picker(dark) {
|
||||
emojiPicker = new EmojiButton({
|
||||
theme: dark ? "dark" : "light"
|
||||
})
|
||||
emojiPicker.on("emoji", selection => {
|
||||
window.jsbridge.emojiIsPicked(selection.emoji)
|
||||
})
|
||||
}
|
||||
|
||||
/* exported prepare_to_show */
|
||||
function prepare_to_show(dark) {
|
||||
emojiPicker.setTheme(dark ? "dark" : "light")
|
||||
|
||||
if (emojiPicker.hideInProgress) {
|
||||
setTimeout(() => prepare_to_show(), 100)
|
||||
return
|
||||
}
|
||||
|
||||
emojiPicker.pickerVisible = true
|
||||
emojiPicker.wrapper.style.display = 'block'
|
||||
|
||||
emojiPicker.focusTrap.activate()
|
||||
|
||||
emojiPicker.wrapper.style.height = '100%'
|
||||
emojiPicker.wrapper.style.width = '100%'
|
||||
|
||||
setTimeout(() => {
|
||||
emojiPicker.addEventListeners()
|
||||
emojiPicker.setInitialFocus()
|
||||
})
|
||||
|
||||
emojiPicker.emojiArea.reset()
|
||||
}
|
||||
|
||||
/* exported prepare_to_hide */
|
||||
function prepare_to_hide() {
|
||||
emojiPicker.hidePicker()
|
||||
}
|
|
@ -24,6 +24,8 @@ import QtQuick 2.14
|
|||
import net.jami.Adapters 1.0
|
||||
|
||||
Item {
|
||||
property string qmlFilePrefix: "file:/"
|
||||
|
||||
readonly property string mainViewLoadPath: "qrc:/src/mainview/MainView.qml"
|
||||
readonly property string wizardViewLoadPath: "qrc:/src/wizardview/WizardView.qml"
|
||||
readonly property string base64StringTitle: "data:image/png;base64,"
|
||||
|
|
|
@ -487,4 +487,12 @@ Item {
|
|||
property string isSwarm: qsTr("Is swarm:")
|
||||
property string trueStr: qsTr("True")
|
||||
property string falseStr: qsTr("False")
|
||||
|
||||
// Message view
|
||||
property string addEmoji: qsTr("Add emoji")
|
||||
property string sendFile: qsTr("Send file")
|
||||
property string leaveAudioMessage: qsTr("Leave audio message")
|
||||
property string leaveVideoMessage: qsTr("Leave video message")
|
||||
property string send: qsTr("Send")
|
||||
property string remove: qsTr("Remove")
|
||||
}
|
||||
|
|
|
@ -158,6 +158,10 @@ Item {
|
|||
property color previewImageBackgroundColor: whiteColor
|
||||
property color previewCardContainerColor : darkTheme ? blackColor : whiteColor
|
||||
property color previewUrlColor : darkTheme ? "#eeeeee" : "#333"
|
||||
property color messageWebViewFooterButtonImageColor: darkTheme ? "#838383" : "#656565"
|
||||
|
||||
// Files To Send Container
|
||||
property color removeFileButtonColor: Qt.rgba(96, 95, 97, 0.5)
|
||||
|
||||
// Font.
|
||||
property color faddedFontColor: darkTheme? "#c0c0c0" : "#a0a0a0"
|
||||
|
@ -245,7 +249,31 @@ Item {
|
|||
property real lineEditContextMenuItemsWidth: 100
|
||||
property real lineEditContextMenuSeparatorsHeight: 2
|
||||
|
||||
// main application spec
|
||||
// Modal Popup
|
||||
property real modalPopupRadius: 4
|
||||
property real modalPopupDropShadowSamples: 16
|
||||
|
||||
// MessageWebView
|
||||
property real messageWebViewHeaderPreferredHeight: 64
|
||||
property real messageWebViewFooterPreferredHeight: 50
|
||||
property real messageWebViewFooterMaximumHeight: 230
|
||||
property real messageWebViewFooterRowSpacing: 1
|
||||
property real messageWebViewFooterButtonSize: 36
|
||||
property real messageWebViewFooterButtonIconSize: 48
|
||||
property real messageWebViewFooterButtonRadius: 5
|
||||
property real messageWebViewFooterFileContainerPreferredHeight: 150
|
||||
property real messageWebViewFooterTextAreaMaximumHeight: 80
|
||||
|
||||
// MessageWebView File Transfer Container
|
||||
property real filesToSendContainerSpacing: 5
|
||||
property real filesToSendContainerPadding: 10
|
||||
property real filesToSendDelegateWidth: 100
|
||||
property real filesToSendDelegateHeight: 100
|
||||
property real filesToSendDelegateRadius: 7
|
||||
property real filesToSendDelegateButtonSize: 16
|
||||
property real filesToSendDelegateFontPointSize: textFontSize + 2
|
||||
|
||||
// Main application spec
|
||||
property real mainViewMinWidth: 300
|
||||
property real mainViewMinHeight: 400
|
||||
|
||||
|
|
106
src/filestosendlistmodel.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (C) 2021 by Savoir-faire Linux
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "filestosendlistmodel.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QImageReader>
|
||||
|
||||
FilesToSendListModel::FilesToSendListModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
{}
|
||||
|
||||
int
|
||||
FilesToSendListModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
return pendingFiles_.size();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray>
|
||||
FilesToSendListModel::roleNames() const
|
||||
{
|
||||
using namespace FilesToSend;
|
||||
QHash<int, QByteArray> roles;
|
||||
#define X(role) roles[role] = #role;
|
||||
FS_ROLES
|
||||
#undef X
|
||||
return roles;
|
||||
}
|
||||
|
||||
Q_INVOKABLE void
|
||||
FilesToSendListModel::addToPending(QString filePath)
|
||||
{
|
||||
auto fileInfo = QFileInfo(filePath);
|
||||
if (!fileInfo.exists())
|
||||
return;
|
||||
|
||||
// QImageReader will treat .gz file (Jami archive) as svgz image format
|
||||
// so decideFormatFromContent is needed
|
||||
bool isImage = false;
|
||||
QImageReader reader;
|
||||
reader.setDecideFormatFromContent(true);
|
||||
reader.setFileName(filePath);
|
||||
|
||||
if (!reader.read().isNull())
|
||||
isImage = true;
|
||||
|
||||
beginInsertRows(QModelIndex(), pendingFiles_.size(), pendingFiles_.size());
|
||||
auto item = FilesToSend::Item(filePath, fileInfo.fileName(), isImage, fileInfo.size());
|
||||
pendingFiles_.append(item);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void
|
||||
FilesToSendListModel::removeFromPending(int index)
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), index, index);
|
||||
pendingFiles_.removeAt(index);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
Q_INVOKABLE void
|
||||
FilesToSendListModel::flush()
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), 0, pendingFiles_.size() - 1);
|
||||
pendingFiles_.clear();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
QVariant
|
||||
FilesToSendListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
using namespace FilesToSend;
|
||||
|
||||
auto item = pendingFiles_.at(index.row());
|
||||
|
||||
switch (role) {
|
||||
case Role::FileName:
|
||||
return QVariant(item.fileName);
|
||||
case Role::FilePath:
|
||||
return QVariant(item.filePath);
|
||||
case Role::FileSize:
|
||||
return QVariant(Utils::humanFileSize(item.fileSizeInByte));
|
||||
case Role::IsImage:
|
||||
return QVariant(item.isImage);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
72
src/filestosendlistmodel.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2021 by Savoir-faire Linux
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
|
||||
#define FS_ROLES \
|
||||
X(FileName) \
|
||||
X(FilePath) \
|
||||
X(FileSize) \
|
||||
X(IsImage)
|
||||
|
||||
namespace FilesToSend {
|
||||
Q_NAMESPACE
|
||||
enum Role {
|
||||
DummyRole = Qt::UserRole + 1,
|
||||
#define X(role) role,
|
||||
FS_ROLES
|
||||
#undef X
|
||||
};
|
||||
Q_ENUM_NS(Role)
|
||||
|
||||
struct Item
|
||||
{
|
||||
Item(QString filePath, QString fileName, bool isImage, qint64 fileSizeInByte)
|
||||
: filePath(filePath)
|
||||
, fileName(fileName)
|
||||
, isImage(isImage)
|
||||
, fileSizeInByte(fileSizeInByte)
|
||||
{}
|
||||
|
||||
QString filePath;
|
||||
QString fileName;
|
||||
bool isImage;
|
||||
qint64 fileSizeInByte;
|
||||
};
|
||||
} // namespace FilesToSend
|
||||
|
||||
class FilesToSendListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FilesToSendListModel(QObject* parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE void addToPending(QString filePath);
|
||||
Q_INVOKABLE void removeFromPending(int index);
|
||||
Q_INVOKABLE void flush();
|
||||
|
||||
private:
|
||||
QList<FilesToSend::Item> pendingFiles_;
|
||||
};
|
81
src/mainview/components/FilesToSendContainer.qml
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Savoir-faire Linux
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import net.jami.Models 1.0
|
||||
import net.jami.Constants 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property alias filesToSendListModel: repeater.model
|
||||
property alias filesToSendCount: repeater.count
|
||||
|
||||
color: JamiTheme.messageOutBgColor
|
||||
|
||||
ScrollView {
|
||||
id: filesToSendContainerScrollView
|
||||
|
||||
anchors.fill: root
|
||||
|
||||
contentHeight: root.height
|
||||
contentWidth: filesToSendContainerRow.width
|
||||
|
||||
ScrollBar.horizontal.visible: {
|
||||
var ratio = filesToSendContainerRow.width / root.width
|
||||
return ratio > 1
|
||||
}
|
||||
ScrollBar.horizontal.contentItem: Rectangle {
|
||||
implicitHeight: 5
|
||||
radius: width / 2
|
||||
color: filesToSendContainerScrollView.ScrollBar.horizontal.pressed ?
|
||||
JamiTheme.darkGreyColor : JamiTheme.whiteColor
|
||||
}
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
||||
|
||||
Row {
|
||||
id: filesToSendContainerRow
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
spacing: JamiTheme.filesToSendContainerSpacing
|
||||
padding: JamiTheme.filesToSendContainerPadding
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
|
||||
delegate: FilesToSendDelegate {
|
||||
anchors.verticalCenter: filesToSendContainerRow.verticalCenter
|
||||
|
||||
width: JamiTheme.filesToSendDelegateWidth
|
||||
height: JamiTheme.filesToSendDelegateHeight
|
||||
|
||||
onRemoveFileButtonClicked: {
|
||||
filesToSendListModel.removeFromPending(index)
|
||||
}
|
||||
}
|
||||
model: FilesToSendListModel {
|
||||
id: filesToSendListModel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
133
src/mainview/components/FilesToSendDelegate.qml
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Savoir-faire Linux
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtGraphicalEffects 1.14
|
||||
|
||||
import net.jami.Constants 1.0
|
||||
import net.jami.Models 1.0
|
||||
|
||||
import "../../commoncomponents"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property real margin: 5
|
||||
|
||||
signal removeFileButtonClicked(int index)
|
||||
|
||||
radius: JamiTheme.filesToSendDelegateRadius
|
||||
|
||||
color: JamiTheme.messageInBgColor
|
||||
|
||||
ColumnLayout {
|
||||
id: delegateFileWrapperColumnLayout
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
spacing: 0
|
||||
|
||||
visible: !IsImage
|
||||
|
||||
ResponsiveImage {
|
||||
id: fileIcon
|
||||
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||
Layout.topMargin: margin
|
||||
Layout.leftMargin: margin
|
||||
|
||||
visible: !IsImage
|
||||
|
||||
source: "qrc:/images/icons/file_black-24dp.svg"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: fileName
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
Layout.leftMargin: margin
|
||||
Layout.preferredWidth: root.width - margin * 2
|
||||
|
||||
visible: !IsImage
|
||||
|
||||
font.pointSize: JamiTheme.filesToSendDelegateFontPointSize
|
||||
|
||||
text: FileName
|
||||
elide: Text.ElideMiddle
|
||||
}
|
||||
|
||||
Text {
|
||||
id: fileSize
|
||||
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
Layout.leftMargin: margin
|
||||
Layout.bottomMargin: margin
|
||||
Layout.preferredWidth: root.width - margin * 2
|
||||
|
||||
visible: !IsImage
|
||||
|
||||
font.pointSize: JamiTheme.filesToSendDelegateFontPointSize
|
||||
|
||||
text: FileSize
|
||||
elide: Text.ElideMiddle
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedImage {
|
||||
id: name
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
asynchronous: true
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
source: IsImage ? JamiQmlUtils.qmlFilePrefix + FilePath : ""
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Rectangle {
|
||||
width: root.width
|
||||
height: root.height
|
||||
radius: JamiTheme.filesToSendDelegateRadius
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PushButton {
|
||||
id: removeFileButton
|
||||
|
||||
anchors.right: root.right
|
||||
anchors.rightMargin: -margin
|
||||
anchors.top: root.top
|
||||
anchors.topMargin: -margin
|
||||
|
||||
radius: margin
|
||||
preferredSize: JamiTheme.filesToSendDelegateButtonSize
|
||||
|
||||
toolTipText: JamiStrings.remove
|
||||
|
||||
source: "qrc:/images/icons/cross_black_24dp.svg"
|
||||
|
||||
normalColor: JamiTheme.removeFileButtonColor
|
||||
hoveredColor: JamiTheme.lightGrey_
|
||||
imageColor: JamiTheme.textColor
|
||||
|
||||
onClicked: root.removeFileButtonClicked(index)
|
||||
}
|
||||
}
|
198
src/mainview/components/MessageBar.qml
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Savoir-faire Linux
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import net.jami.Adapters 1.0
|
||||
import net.jami.Constants 1.0
|
||||
|
||||
import "../../commoncomponents"
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
property var textAreaObj: textArea
|
||||
property real marginSize: 10
|
||||
|
||||
signal sendFileButtonClicked
|
||||
signal audioRecordMessageButtonClicked
|
||||
signal videoRecordMessageButtonClicked
|
||||
signal emojiButtonClicked
|
||||
|
||||
spacing: JamiTheme.messageWebViewFooterRowSpacing
|
||||
|
||||
PushButton {
|
||||
id: sendFileButton
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.leftMargin: marginSize
|
||||
Layout.preferredWidth: JamiTheme.messageWebViewFooterButtonSize
|
||||
Layout.preferredHeight: JamiTheme.messageWebViewFooterButtonSize
|
||||
|
||||
radius: JamiTheme.messageWebViewFooterButtonRadius
|
||||
preferredSize: JamiTheme.messageWebViewFooterButtonIconSize - 6
|
||||
|
||||
toolTipText: JamiStrings.sendFile
|
||||
|
||||
source: "qrc:/images/icons/link_black-24dp.svg"
|
||||
|
||||
normalColor: JamiTheme.primaryBackgroundColor
|
||||
imageColor: JamiTheme.messageWebViewFooterButtonImageColor
|
||||
|
||||
onClicked: root.sendFileButtonClicked()
|
||||
}
|
||||
|
||||
PushButton {
|
||||
id: audioRecordMessageButton
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredWidth: JamiTheme.messageWebViewFooterButtonSize
|
||||
Layout.preferredHeight: JamiTheme.messageWebViewFooterButtonSize
|
||||
|
||||
radius: JamiTheme.messageWebViewFooterButtonRadius
|
||||
preferredSize: JamiTheme.messageWebViewFooterButtonIconSize
|
||||
|
||||
toolTipText: JamiStrings.leaveAudioMessage
|
||||
|
||||
source: "qrc:/images/icons/message_audio_black-24dp.svg"
|
||||
|
||||
normalColor: JamiTheme.primaryBackgroundColor
|
||||
imageColor: JamiTheme.messageWebViewFooterButtonImageColor
|
||||
|
||||
onClicked: root.audioRecordMessageButtonClicked()
|
||||
}
|
||||
|
||||
PushButton {
|
||||
id: videoRecordMessageButton
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredWidth: JamiTheme.messageWebViewFooterButtonSize
|
||||
Layout.preferredHeight: JamiTheme.messageWebViewFooterButtonSize
|
||||
|
||||
radius: JamiTheme.messageWebViewFooterButtonRadius
|
||||
preferredSize: JamiTheme.messageWebViewFooterButtonIconSize
|
||||
|
||||
toolTipText: JamiStrings.leaveVideoMessage
|
||||
|
||||
source: "qrc:/images/icons/message_video_black-24dp.svg"
|
||||
|
||||
normalColor: JamiTheme.primaryBackgroundColor
|
||||
imageColor: JamiTheme.messageWebViewFooterButtonImageColor
|
||||
|
||||
onClicked: root.videoRecordMessageButtonClicked()
|
||||
}
|
||||
|
||||
JamiTextArea {
|
||||
id: textArea
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: marginSize / 2
|
||||
Layout.preferredHeight: {
|
||||
return JamiTheme.messageWebViewFooterPreferredHeight
|
||||
> contentHeight ? JamiTheme.messageWebViewFooterPreferredHeight : contentHeight
|
||||
}
|
||||
Layout.maximumHeight: JamiTheme.messageWebViewFooterTextAreaMaximumHeight
|
||||
- marginSize / 2
|
||||
|
||||
onTextChanged: {
|
||||
if (text) {
|
||||
sendMessageButton.visible = true
|
||||
sendMessageButton.state = "buttonFadeOut"
|
||||
} else
|
||||
sendMessageButton.state = "buttonFadeIn"
|
||||
}
|
||||
}
|
||||
|
||||
PushButton {
|
||||
id: emojiButton
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.rightMargin: sendMessageButton.visible ? 0 : marginSize
|
||||
Layout.preferredWidth: JamiTheme.messageWebViewFooterButtonSize
|
||||
Layout.preferredHeight: JamiTheme.messageWebViewFooterButtonSize
|
||||
|
||||
radius: JamiTheme.messageWebViewFooterButtonRadius
|
||||
preferredSize: JamiTheme.messageWebViewFooterButtonIconSize
|
||||
|
||||
toolTipText: JamiStrings.addEmoji
|
||||
|
||||
source: "qrc:/images/icons/emoji_black-24dp.svg"
|
||||
|
||||
normalColor: JamiTheme.primaryBackgroundColor
|
||||
imageColor: JamiTheme.messageWebViewFooterButtonImageColor
|
||||
|
||||
onClicked: root.emojiButtonClicked()
|
||||
}
|
||||
|
||||
PushButton {
|
||||
id: sendMessageButton
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.rightMargin: visible ? marginSize : 0
|
||||
Layout.preferredWidth: JamiTheme.messageWebViewFooterButtonSize
|
||||
Layout.preferredHeight: JamiTheme.messageWebViewFooterButtonSize
|
||||
|
||||
radius: JamiTheme.messageWebViewFooterButtonRadius
|
||||
preferredSize: JamiTheme.messageWebViewFooterButtonIconSize - 6
|
||||
|
||||
toolTipText: JamiStrings.send
|
||||
|
||||
source: "qrc:/images/icons/send_black-24dp.svg"
|
||||
|
||||
normalColor: JamiTheme.primaryBackgroundColor
|
||||
imageColor: JamiTheme.messageWebViewFooterButtonImageColor
|
||||
|
||||
opacity: 0
|
||||
visible: false
|
||||
states: [
|
||||
State {
|
||||
name: "buttonFadeIn"
|
||||
PropertyChanges {
|
||||
target: sendMessageButton
|
||||
opacity: 0
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "buttonFadeOut"
|
||||
PropertyChanges {
|
||||
target: sendMessageButton
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
]
|
||||
transitions: Transition {
|
||||
NumberAnimation {
|
||||
properties: "opacity"
|
||||
easing.type: Easing.InOutQuad
|
||||
duration: 300
|
||||
}
|
||||
}
|
||||
|
||||
onOpacityChanged: {
|
||||
if (opacity === 0)
|
||||
visible = false
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,11 +30,8 @@ import "../../commoncomponents"
|
|||
import "../js/pluginhandlerpickercreation.js" as PluginHandlerPickerCreation
|
||||
|
||||
Rectangle {
|
||||
id: messageWebViewRect
|
||||
id: root
|
||||
|
||||
color: JamiTheme.backgroundColor
|
||||
|
||||
property int messageWebViewHeaderPreferredHeight: 64
|
||||
property string headerUserAliasLabelText: ""
|
||||
property string headerUserUserNameLabelText: ""
|
||||
property bool jsLoaded: false
|
||||
|
@ -69,13 +66,6 @@ Rectangle {
|
|||
messageWebViewHeader.resetBackToWelcomeViewButtonSource(reset)
|
||||
}
|
||||
|
||||
function setFilePathsToSend(filePaths) {
|
||||
for (var index = 0; index < filePaths.length; ++index) {
|
||||
var path = UtilsAdapter.getAbsPath(filePaths[index])
|
||||
MessagesAdapter.setNewMessagesContent(path)
|
||||
}
|
||||
}
|
||||
|
||||
function updateChatviewTheme() {
|
||||
var theme = 'setTheme("\
|
||||
--svg-invert-percentage:' + JamiTheme.invertPercentageInDecimal + ';\
|
||||
|
@ -107,6 +97,8 @@ Rectangle {
|
|||
messageWebView.runJavaScript(theme);
|
||||
}
|
||||
|
||||
color: JamiTheme.primaryBackgroundColor
|
||||
|
||||
Connections {
|
||||
target: JamiTheme
|
||||
|
||||
|
@ -115,50 +107,6 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
JamiFileDialog {
|
||||
id: jamiFileDialog
|
||||
|
||||
mode: JamiFileDialog.Mode.OpenFiles
|
||||
|
||||
onAccepted: setFilePathsToSend(jamiFileDialog.files)
|
||||
}
|
||||
|
||||
MessageWebViewHeader {
|
||||
|
||||
DropArea{
|
||||
anchors.fill: parent
|
||||
onDropped: setFilePathsToSend(drop.urls)
|
||||
}
|
||||
|
||||
id: messageWebViewHeader
|
||||
|
||||
anchors.top: messageWebViewRect.top
|
||||
anchors.left: messageWebViewRect.left
|
||||
|
||||
width: messageWebViewRect.width
|
||||
height: messageWebViewHeaderPreferredHeight
|
||||
|
||||
userAliasLabelText: headerUserAliasLabelText
|
||||
userUserNameLabelText: headerUserUserNameLabelText
|
||||
|
||||
onBackClicked: {
|
||||
MessagesAdapter.updateDraft()
|
||||
mainView.showWelcomeView()
|
||||
}
|
||||
|
||||
onNeedToHideConversationInCall: {
|
||||
messageWebViewRect.needToHideConversationInCall()
|
||||
}
|
||||
|
||||
onPluginSelector : {
|
||||
// Create plugin handler picker - PLUGINS
|
||||
PluginHandlerPickerCreation.createPluginHandlerPickerObjects(messageWebViewRect, false)
|
||||
PluginHandlerPickerCreation.calculateCurrentGeo(
|
||||
messageWebViewRect.width / 2, messageWebViewRect.height / 2)
|
||||
PluginHandlerPickerCreation.openPluginHandlerPicker()
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: jsBridgeObject
|
||||
|
||||
|
@ -203,10 +151,6 @@ Rectangle {
|
|||
MessagesAdapter.sendFile(arg)
|
||||
}
|
||||
|
||||
function selectFile() {
|
||||
jamiFileDialog.open()
|
||||
}
|
||||
|
||||
function acceptInvitation() {
|
||||
MessagesAdapter.acceptInvitation()
|
||||
}
|
||||
|
@ -220,11 +164,11 @@ Rectangle {
|
|||
}
|
||||
|
||||
function emitMessagesCleared() {
|
||||
messageWebViewRect.messagesCleared()
|
||||
root.messagesCleared()
|
||||
}
|
||||
|
||||
function emitMessagesLoaded() {
|
||||
messageWebViewRect.messagesLoaded()
|
||||
root.messagesLoaded()
|
||||
}
|
||||
|
||||
function copyToDownloads(interactionId, displayName) {
|
||||
|
@ -244,7 +188,7 @@ Rectangle {
|
|||
}
|
||||
|
||||
function saveSendMessageContent(arg) {
|
||||
messageWebViewRect.sendMessageContentSaved(arg)
|
||||
root.sendMessageContentSaved(arg)
|
||||
}
|
||||
|
||||
function onComposing(isComposing) {
|
||||
|
@ -260,104 +204,152 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
WebEngineView {
|
||||
id: messageWebView
|
||||
|
||||
anchors.top: messageWebViewHeader.bottom
|
||||
anchors.topMargin: 1
|
||||
anchors.left: messageWebViewRect.left
|
||||
|
||||
width: messageWebViewRect.width
|
||||
height: messageWebViewRect.height - messageWebViewHeaderPreferredHeight
|
||||
|
||||
backgroundColor: "transparent"
|
||||
|
||||
settings.javascriptEnabled: true
|
||||
settings.javascriptCanOpenWindows: true
|
||||
settings.javascriptCanAccessClipboard: true
|
||||
settings.javascriptCanPaste: true
|
||||
settings.fullScreenSupportEnabled: true
|
||||
settings.allowRunningInsecureContent: true
|
||||
settings.localContentCanAccessRemoteUrls: true
|
||||
settings.localContentCanAccessFileUrls: true
|
||||
settings.errorPageEnabled: false
|
||||
settings.pluginsEnabled: false
|
||||
settings.screenCaptureEnabled: false
|
||||
settings.linksIncludedInFocusChain: false
|
||||
settings.localStorageEnabled: true
|
||||
|
||||
webChannel: messageWebViewChannel
|
||||
|
||||
DropArea{
|
||||
anchors.fill: parent
|
||||
onDropped: setFilePathsToSend(drop.urls)
|
||||
}
|
||||
|
||||
onNavigationRequested: {
|
||||
if(request.navigationType === WebEngineView.LinkClickedNavigation) {
|
||||
MessagesAdapter.openUrl(request.url)
|
||||
request.action = WebEngineView.IgnoreRequest
|
||||
}
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
if (loadRequest.status == WebEngineView.LoadSucceededStatus) {
|
||||
messageWebView.runJavaScript(UtilsAdapter.getStyleSheet(
|
||||
"chatcss",
|
||||
UtilsAdapter.qStringFromFile(
|
||||
":/chatview.css")))
|
||||
messageWebView.runJavaScript(UtilsAdapter.getStyleSheet(
|
||||
"chatwin",
|
||||
UtilsAdapter.qStringFromFile(
|
||||
":/chatview-qt.css")))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/linkify.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/linkify-html.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/linkify-string.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/qwebchannel.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/jed.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/emoji.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/previewInfo.js"))
|
||||
messageWebView.runJavaScript(
|
||||
UtilsAdapter.qStringFromFile(":/chatview.js"),
|
||||
function() {
|
||||
messageWebView.runJavaScript("init_i18n();")
|
||||
MessagesAdapter.setDisplayLinks()
|
||||
updateChatviewTheme()
|
||||
messageWebView.runJavaScript("displayNavbar(false);")
|
||||
jsLoaded = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onContextMenuRequested: {
|
||||
var needContextMenu = request.selectedText.length || request.isContentEditable
|
||||
if (!needContextMenu)
|
||||
request.accepted = true
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
profile.cachePath = UtilsAdapter.getCachePath()
|
||||
profile.persistentStoragePath = UtilsAdapter.getCachePath()
|
||||
profile.persistentCookiesPolicy = WebEngineProfile.NoPersistentCookies
|
||||
profile.httpCacheType = WebEngineProfile.NoCache
|
||||
profile.httpUserAgent = JamiStrings.httpUserAgentName
|
||||
|
||||
messageWebView.loadHtml(UtilsAdapter.qStringFromFile(
|
||||
":/chatview.html"), ":/chatview.html")
|
||||
messageWebView.url = "qrc:/chatview.html"
|
||||
}
|
||||
}
|
||||
|
||||
// Provide WebChannel by registering jsBridgeObject.
|
||||
WebChannel {
|
||||
id: messageWebViewChannel
|
||||
registeredObjects: [jsBridgeObject]
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: root
|
||||
|
||||
spacing: 0
|
||||
|
||||
MessageWebViewHeader {
|
||||
id: messageWebViewHeader
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: JamiTheme.messageWebViewHeaderPreferredHeight
|
||||
Layout.maximumHeight: JamiTheme.messageWebViewHeaderPreferredHeight
|
||||
|
||||
userAliasLabelText: headerUserAliasLabelText
|
||||
userUserNameLabelText: headerUserUserNameLabelText
|
||||
|
||||
DropArea{
|
||||
anchors.fill: parent
|
||||
//onDropped: setFilePathsToSend(drop.urls)
|
||||
}
|
||||
|
||||
onBackClicked: {
|
||||
MessagesAdapter.updateDraft()
|
||||
mainView.showWelcomeView()
|
||||
}
|
||||
|
||||
onNeedToHideConversationInCall: {
|
||||
root.needToHideConversationInCall()
|
||||
}
|
||||
|
||||
onPluginSelector : {
|
||||
// Create plugin handler picker - PLUGINS
|
||||
PluginHandlerPickerCreation.createPluginHandlerPickerObjects(root, false)
|
||||
PluginHandlerPickerCreation.calculateCurrentGeo(root.width / 2, root.height / 2)
|
||||
PluginHandlerPickerCreation.openPluginHandlerPicker()
|
||||
}
|
||||
}
|
||||
|
||||
WebEngineView {
|
||||
id: messageWebView
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.topMargin: messageWebViewHeader.hairLineSize
|
||||
Layout.bottomMargin: messageWebViewFooter.hairLineSize
|
||||
|
||||
backgroundColor: "transparent"
|
||||
|
||||
settings.javascriptEnabled: true
|
||||
settings.javascriptCanOpenWindows: true
|
||||
settings.javascriptCanAccessClipboard: true
|
||||
settings.javascriptCanPaste: true
|
||||
settings.fullScreenSupportEnabled: true
|
||||
settings.allowRunningInsecureContent: true
|
||||
settings.localContentCanAccessRemoteUrls: true
|
||||
settings.localContentCanAccessFileUrls: true
|
||||
settings.errorPageEnabled: false
|
||||
settings.pluginsEnabled: false
|
||||
settings.screenCaptureEnabled: false
|
||||
settings.linksIncludedInFocusChain: false
|
||||
settings.localStorageEnabled: true
|
||||
|
||||
webChannel: messageWebViewChannel
|
||||
|
||||
DropArea{
|
||||
anchors.fill: parent
|
||||
//onDropped: setFilePathsToSend(drop.urls)
|
||||
}
|
||||
|
||||
onNavigationRequested: {
|
||||
if(request.navigationType === WebEngineView.LinkClickedNavigation) {
|
||||
MessagesAdapter.openUrl(request.url)
|
||||
request.action = WebEngineView.IgnoreRequest
|
||||
}
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
if (loadRequest.status == WebEngineView.LoadSucceededStatus) {
|
||||
messageWebView.runJavaScript(UtilsAdapter.getStyleSheet(
|
||||
"chatcss",
|
||||
UtilsAdapter.qStringFromFile(
|
||||
":/chatview.css")))
|
||||
messageWebView.runJavaScript(UtilsAdapter.getStyleSheet(
|
||||
"chatwin",
|
||||
UtilsAdapter.qStringFromFile(
|
||||
":/chatview-qt.css")))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/linkify.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/linkify-html.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/linkify-string.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/qwebchannel.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/jed.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/emoji.js"))
|
||||
messageWebView.runJavaScript(UtilsAdapter.qStringFromFile(
|
||||
":/previewInfo.js"))
|
||||
messageWebView.runJavaScript(
|
||||
UtilsAdapter.qStringFromFile(":/chatview.js"),
|
||||
function() {
|
||||
messageWebView.runJavaScript("init_i18n();")
|
||||
MessagesAdapter.setDisplayLinks()
|
||||
updateChatviewTheme()
|
||||
messageWebView.runJavaScript("displayNavbar(false);")
|
||||
messageWebView.runJavaScript("hideMessageBar(true);")
|
||||
jsLoaded = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onContextMenuRequested: {
|
||||
var needContextMenu = request.selectedText.length || request.isContentEditable
|
||||
if (!needContextMenu)
|
||||
request.accepted = true
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
profile.cachePath = UtilsAdapter.getCachePath()
|
||||
profile.persistentStoragePath = UtilsAdapter.getCachePath()
|
||||
profile.persistentCookiesPolicy = WebEngineProfile.NoPersistentCookies
|
||||
profile.httpCacheType = WebEngineProfile.NoCache
|
||||
profile.httpUserAgent = JamiStrings.httpUserAgentName
|
||||
|
||||
messageWebView.loadHtml(UtilsAdapter.qStringFromFile(
|
||||
":/chatview.html"), ":/chatview.html")
|
||||
messageWebView.url = "qrc:/chatview.html"
|
||||
}
|
||||
}
|
||||
|
||||
MessageWebViewFooter {
|
||||
id: messageWebViewFooter
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: implicitHeight
|
||||
Layout.maximumHeight: JamiTheme.messageWebViewFooterMaximumHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
98
src/mainview/components/MessageWebViewFooter.qml
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Savoir-faire Linux
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import net.jami.Models 1.0
|
||||
import net.jami.Constants 1.0
|
||||
import net.jami.Adapters 1.0
|
||||
|
||||
import "../../commoncomponents"
|
||||
import "../../commoncomponents/emojipicker"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property real hairLineSize: 1
|
||||
|
||||
function setFilePathsToSend(filePaths) {
|
||||
for (var index = 0; index < filePaths.length; ++index) {
|
||||
var path = UtilsAdapter.getAbsPath(filePaths[index])
|
||||
dataTransferSendContainer.filesToSendListModel.addToPending(path)
|
||||
}
|
||||
}
|
||||
|
||||
implicitHeight: footerColumnLayout.implicitHeight
|
||||
|
||||
color: JamiTheme.primaryBackgroundColor
|
||||
|
||||
EmojiPicker {
|
||||
id: emojiPicker
|
||||
|
||||
onEmojiIsPicked: messageBar.textAreaObj.insertText(content)
|
||||
}
|
||||
|
||||
JamiFileDialog {
|
||||
id: jamiFileDialog
|
||||
|
||||
mode: JamiFileDialog.Mode.OpenFiles
|
||||
|
||||
onAccepted: setFilePathsToSend(jamiFileDialog.files)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: footerColumnLayout
|
||||
|
||||
anchors.centerIn: root
|
||||
|
||||
width: root.width
|
||||
|
||||
spacing: 0
|
||||
|
||||
MessageBar {
|
||||
id: messageBar
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: implicitHeight
|
||||
|
||||
onEmojiButtonClicked: emojiPicker.openEmojiPicker()
|
||||
onSendFileButtonClicked: jamiFileDialog.open()
|
||||
}
|
||||
|
||||
FilesToSendContainer {
|
||||
id: dataTransferSendContainer
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: filesToSendCount ?
|
||||
JamiTheme.messageWebViewFooterFileContainerPreferredHeight : 0
|
||||
}
|
||||
}
|
||||
|
||||
CustomBorder {
|
||||
commonBorder: false
|
||||
lBorderwidth: 0
|
||||
rBorderwidth: 0
|
||||
tBorderwidth: hairLineSize
|
||||
bBorderwidth: 0
|
||||
borderColor: JamiTheme.tabbarBorderColor
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ import "../../commoncomponents"
|
|||
Rectangle {
|
||||
id: messagingHeaderRect
|
||||
|
||||
property real hairLineSize: 1
|
||||
property string userAliasLabelText
|
||||
property string userUserNameLabelText
|
||||
property string backToWelcomeViewButtonSource: "qrc:/images/icons/back-24px.svg"
|
||||
|
@ -229,7 +230,7 @@ Rectangle {
|
|||
lBorderwidth: 0
|
||||
rBorderwidth: 0
|
||||
tBorderwidth: 0
|
||||
bBorderwidth: 1
|
||||
bBorderwidth: hairLineSize
|
||||
borderColor: JamiTheme.tabbarBorderColor
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "deviceitemlistmodel.h"
|
||||
#include "smartlistmodel.h"
|
||||
#include "conversationlistmodelbase.h"
|
||||
#include "filestosendlistmodel.h"
|
||||
|
||||
#include "appsettingsmanager.h"
|
||||
#include "distantrenderer.h"
|
||||
|
@ -105,6 +106,7 @@ registerTypes()
|
|||
QML_REGISTERTYPE(NS_MODELS, VideoFormatResolutionModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, VideoFormatFpsModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, PluginListPreferenceModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, FilesToSendListModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, SmartListModel);
|
||||
|
||||
// Roles & type enums for models
|
||||
|
|
|
@ -820,7 +820,7 @@ Utils::humanFileSize(qint64 fileSize)
|
|||
if (abs(fileSizeF) < thresh) {
|
||||
return QString::number(fileSizeF) + " B";
|
||||
}
|
||||
QString units[] = {"kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
|
||||
QString units[] = {"KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
|
||||
int unit_position = -1;
|
||||
do {
|
||||
fileSizeF /= thresh;
|
||||
|
|