diff --git a/CHANGELOG.md b/CHANGELOG.md
index a241abd4d..b2e0b0717 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/linphone-app/CMakeLists.txt b/linphone-app/CMakeLists.txt
index 68867c1eb..fc3118677 100644
--- a/linphone-app/CMakeLists.txt
+++ b/linphone-app/CMakeLists.txt
@@ -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
diff --git a/linphone-app/assets/images/chat_audio_pause_custom.svg b/linphone-app/assets/images/chat_audio_pause_custom.svg
index e6b1d6996..8b5393cf8 100644
--- a/linphone-app/assets/images/chat_audio_pause_custom.svg
+++ b/linphone-app/assets/images/chat_audio_pause_custom.svg
@@ -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" />
-
-
-
-
-
+
diff --git a/linphone-app/assets/images/chat_audio_play_custom.svg b/linphone-app/assets/images/chat_audio_play_custom.svg
index 34dfe5c4c..b8376fb5e 100644
--- a/linphone-app/assets/images/chat_audio_play_custom.svg
+++ b/linphone-app/assets/images/chat_audio_play_custom.svg
@@ -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">
+ id="defs18" />
+ inkscape:current-layer="g8" />
+ id="g12">
-
+ id="g10">
+
+
+
+
+
diff --git a/linphone-app/assets/images/chat_audio_preview_pause_custom.svg b/linphone-app/assets/images/chat_audio_preview_pause_custom.svg
new file mode 100644
index 000000000..e6b1d6996
--- /dev/null
+++ b/linphone-app/assets/images/chat_audio_preview_pause_custom.svg
@@ -0,0 +1,47 @@
+
+
diff --git a/linphone-app/assets/images/chat_audio_preview_play_custom.svg b/linphone-app/assets/images/chat_audio_preview_play_custom.svg
new file mode 100644
index 000000000..34dfe5c4c
--- /dev/null
+++ b/linphone-app/assets/images/chat_audio_preview_play_custom.svg
@@ -0,0 +1,47 @@
+
+
diff --git a/linphone-app/assets/images/chat_audio_stop_custom.svg b/linphone-app/assets/images/chat_audio_preview_stop_custom.svg
similarity index 100%
rename from linphone-app/assets/images/chat_audio_stop_custom.svg
rename to linphone-app/assets/images/chat_audio_preview_stop_custom.svg
diff --git a/linphone-app/assets/images/chat_audio_soundwave_custom.svg b/linphone-app/assets/images/chat_audio_soundwave_custom.svg
index 773208494..eefa978f1 100644
--- a/linphone-app/assets/images/chat_audio_soundwave_custom.svg
+++ b/linphone-app/assets/images/chat_audio_soundwave_custom.svg
@@ -1,12 +1,12 @@
+ 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" />
+ transform="matrix(0.5,0,0,0.66666667,0,10)">
+ 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" />
diff --git a/linphone-app/assets/images/menu_copy_text_custom.svg b/linphone-app/assets/images/menu_copy_text_custom.svg
index ad5a13053..6498ca958 100644
--- a/linphone-app/assets/images/menu_copy_text_custom.svg
+++ b/linphone-app/assets/images/menu_copy_text_custom.svg
@@ -2,18 +2,19 @@
diff --git a/linphone-app/assets/images/send_custom.svg b/linphone-app/assets/images/send_custom.svg
index 79c8416cd..63038ee36 100644
--- a/linphone-app/assets/images/send_custom.svg
+++ b/linphone-app/assets/images/send_custom.svg
@@ -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)">
'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.
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).
+
+ minimalTimelineFilterLabel
+ 'Minimal Timeline filter'
+ Minimal Timeline filter
+
+
+ minimalTimelineFilterTooltip
+ 'Show a minimal version of what to display in timeline.' :
+ Show a minimal version of what to display in timeline.
+
SettingsVideo
@@ -2833,6 +2843,11 @@ Click here: <a href="%1">%1</a>
'No Ephemerals' : Filter item. Selecting it will hide all chat rooms where the ephemeral mode has been enabled.
Without ephemerals
+
+ timelineFilterConferences
+ 'Conferences' : Filter item. Selecting it will show all conferences.
+ Conferences
+
UseAppSipAccount
diff --git a/linphone-app/resources.qrc b/linphone-app/resources.qrc
index 40c729121..61ffa4d41 100644
--- a/linphone-app/resources.qrc
+++ b/linphone-app/resources.qrc
@@ -33,7 +33,9 @@
assets/images/chat_audio_pause_custom.svg
assets/images/chat_audio_play_custom.svg
assets/images/chat_audio_soundwave_custom.svg
- assets/images/chat_audio_stop_custom.svg
+ assets/images/chat_audio_preview_pause_custom.svg
+ assets/images/chat_audio_preview_play_custom.svg
+ assets/images/chat_audio_preview_stop_custom.svg
assets/images/chat_count.svg
assets/images/chat_delivered.svg
assets/images/chat_error.svg
@@ -281,6 +283,7 @@
ui/modules/Linphone/Chat/ChatAudioMessage.qml
ui/modules/Linphone/Chat/ChatAudioPreview.qml
ui/modules/Linphone/Chat/ChatFileMessage.qml
+ ui/modules/Linphone/Chat/ChatFilePreview.qml
ui/modules/Linphone/Chat/ChatForwardMessage.qml
ui/modules/Linphone/Chat/ChatMessagePreview.qml
ui/modules/Linphone/Chat/ChatReplyMessage.qml
@@ -301,6 +304,7 @@
ui/modules/Linphone/Contact/Contact.qml
ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml
ui/modules/Linphone/Dialog/SipAddressDialog.qml
+ ui/modules/Linphone/File/FileView.qml
ui/modules/Linphone/History/History.qml
ui/modules/Linphone/History/History.js
ui/modules/Linphone/History/Event.qml
@@ -327,6 +331,7 @@
ui/modules/Linphone/Styles/Chat/ChatStyle.qml
ui/modules/Linphone/Styles/Chat/ChatAudioMessageStyle.qml
ui/modules/Linphone/Styles/Chat/ChatAudioPreviewStyle.qml
+ ui/modules/Linphone/Styles/Chat/ChatFilePreviewStyle.qml
ui/modules/Linphone/Styles/Chat/ChatForwardMessageStyle.qml
ui/modules/Linphone/Styles/Chat/ChatReplyMessageStyle.qml
ui/modules/Linphone/Styles/Codecs/CodecsViewerStyle.qml
diff --git a/linphone-app/src/components/chat-events/ChatMessageModel.cpp b/linphone-app/src/components/chat-events/ChatMessageModel.cpp
index 7f8eddfe9..1d40c2ff5 100644
--- a/linphone-app/src/components/chat-events/ChatMessageModel.cpp
+++ b/linphone-app/src/components/chat-events/ChatMessageModel.cpp
@@ -120,33 +120,36 @@ QString ChatMessageModel::AppDataManager::toString(){
}
ChatMessageModel::ChatMessageModel ( std::shared_ptr chatMessage, QObject * parent) : ChatEvent(ChatRoomModel::EntryType::MessageEntry, parent) {
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it
- mParticipantImdnStateListModel = std::make_shared(chatMessage);
- mChatMessageListener = std::make_shared(this, parent);
- mChatMessage = chatMessage;
+ if(chatMessage){
+ mParticipantImdnStateListModel = std::make_shared(chatMessage);
+ mChatMessageListener = std::make_shared(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(parent), &ChatRoomModel::removeEntry);
+
+ std::list> 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(parent), &ChatRoomModel::removeEntry);
-
- std::list> contents = chatMessage->getContents();
- QString txt;
- for(auto content : contents){
- if(content->isText())
- txt += content->getUtf8Text().c_str();
- }
- mContent = txt;
mContentListModel = std::make_shared(this);
}
ChatMessageModel::~ChatMessageModel(){
- mChatMessage->removeListener(mChatMessageListener);
+ if(mChatMessage)
+ mChatMessage->removeListener(mChatMessageListener);
}
std::shared_ptr ChatMessageModel::create(std::shared_ptr chatMessage, QObject * parent){
auto model = std::make_shared(chatMessage, parent);
@@ -163,7 +166,7 @@ std::shared_ptr 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 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 &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);
diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp
index 975351d85..4642fc9bc 100644
--- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp
+++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp
@@ -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 _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 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 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){
diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.hpp b/linphone-app/src/components/chat-room/ChatRoomModel.hpp
index 9079da4a3..0379089f2 100644
--- a/linphone-app/src/components/chat-room/ChatRoomModel.hpp
+++ b/linphone-app/src/components/chat-room/ChatRoomModel.hpp
@@ -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 create(std::shared_ptr chatRoom);
ChatRoomModel (std::shared_ptr chatRoom, QObject * parent = nullptr);
~ChatRoomModel ();
@@ -202,6 +200,7 @@ public:
std::shared_ptr getChatRoom();
QList 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 ();
diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp
index 7eb98792f..fe2a6bc4d 100644
--- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp
+++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.cpp
@@ -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 *)
diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp
index f25bff3ce..ed0b32221 100644
--- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp
+++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp
@@ -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);
diff --git a/linphone-app/src/components/chat/ChatModel.cpp b/linphone-app/src/components/chat/ChatModel.cpp
new file mode 100644
index 000000000..b3377a105
--- /dev/null
+++ b/linphone-app/src/components/chat/ChatModel.cpp
@@ -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 .
+ */
+
+#include "ChatModel.hpp"
+
+#include
+#include
+#include
+#include
+
+#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(nullptr);
+}
+
+std::shared_ptr ChatModel::getContentListModel() const {
+ return mContents;
+}
+
+void ChatModel::clear() {
+ mContents->clear();
+}
\ No newline at end of file
diff --git a/linphone-app/src/components/chat/ChatModel.hpp b/linphone-app/src/components/chat/ChatModel.hpp
new file mode 100644
index 000000000..5197ccf7f
--- /dev/null
+++ b/linphone-app/src/components/chat/ChatModel.hpp
@@ -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 .
+ */
+
+// Used to store data between chats
+
+#ifndef CHAT_MODEL_H_
+#define CHAT_MODEL_H_
+
+#include
+// =============================================================================
+#include
+#include
+#include
+class ContentListModel;
+
+class ChatModel : public QObject{
+ Q_OBJECT
+public:
+ ChatModel(QObject * parent = nullptr);
+
+// Getters
+ std::shared_ptr getContentListModel() const;
+
+// Tools
+ Q_INVOKABLE void clear();
+
+private:
+ std::shared_ptr mContents;
+};
+
+#endif
diff --git a/linphone-app/src/components/content/ContentListModel.cpp b/linphone-app/src/components/content/ContentListModel.cpp
index 304aa03e5..cd22115c0 100644
--- a/linphone-app/src/components/content/ContentListModel.cpp
+++ b/linphone-app/src/components/content/ContentListModel.cpp
@@ -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> contents = message->getChatMessage()->getContents() ;
- for(auto content : contents){
- auto contentModel = std::make_shared(content, message);
- connect(this, &ContentListModel::updateTransferDataRequested, contentModel.get(), &ContentModel::updateTransferData);
- mList << contentModel;
+ mParent = message;
+ if(message){
+ std::list> contents = message->getChatMessage()->getContents() ;
+ for(auto content : contents){
+ auto contentModel = std::make_shared(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 ContentListModel::add(std::shared_ptr content){
+ int row = mList.count();
+ auto contentModel = std::make_shared(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 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 ContentListModel::getContentModel(std::shared_ptr content){
for(auto c : mList)
if(c->getContent() == content)
@@ -95,6 +161,11 @@ std::shared_ptr ContentListModel::getContentModel(std::shared_ptr<
}
return nullptr;
}
+
+QList> ContentListModel::getContents(){
+ return mList;
+}
+
void ContentListModel::updateContent(std::shared_ptr oldContent, std::shared_ptr newContent){
int row = 0;
for(auto content = mList.begin() ; content != mList.end() ; ++content, ++row){
diff --git a/linphone-app/src/components/content/ContentListModel.hpp b/linphone-app/src/components/content/ContentListModel.hpp
index e5821dc93..6ed96b002 100644
--- a/linphone-app/src/components/content/ContentListModel.hpp
+++ b/linphone-app/src/components/content/ContentListModel.hpp
@@ -43,8 +43,15 @@ public:
virtual QHash roleNames () const override;
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ std::shared_ptr add(std::shared_ptr content);
+ void addFile(const QString& path);
+ Q_INVOKABLE void remove(ContentModel * model);
+
+ void clear();
std::shared_ptr getContentModel(std::shared_ptr content);// Return the contentModel by checking Content, or if it is the same file.
+ QList> getContents();
+
void updateContent(std::shared_ptr oldContent, std::shared_ptr 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> mList;
+ ChatMessageModel * mParent;
};
diff --git a/linphone-app/src/components/content/ContentModel.cpp b/linphone-app/src/components/content/ContentModel.cpp
index d8bdff3ea..d82f4ef58 100644
--- a/linphone-app/src/components/content/ContentModel.cpp
+++ b/linphone-app/src/components/content/ContentModel.cpp
@@ -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 content, ChatMessageModel* chatModel){
+ContentModel::ContentModel(std::shared_ptr 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::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()))
);
diff --git a/linphone-app/src/components/content/ContentModel.hpp b/linphone-app/src/components/content/ContentModel.hpp
index 3029be813..d379a70ce 100644
--- a/linphone-app/src/components/content/ContentModel.hpp
+++ b/linphone-app/src/components/content/ContentModel.hpp
@@ -27,7 +27,8 @@
#include
#include
#include
-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 mContent;
ChatMessageModel* mChatMessageModel;
+ ChatMessageModel::AppDataManager mAppData; // Used if there is no Chat Message model set.
};
Q_DECLARE_METATYPE(std::shared_ptr)
diff --git a/linphone-app/src/components/content/ContentProxyModel.cpp b/linphone-app/src/components/content/ContentProxyModel.cpp
index 1cdd3c099..9ac520d92 100644
--- a/linphone-app/src/components/content/ContentProxyModel.cpp
+++ b/linphone-app/src/components/content/ContentProxyModel.cpp
@@ -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(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();
const ContentModel *contentB = sourceModel()->data(right).value();
- 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(sourceModel())->remove(model);
+}
+
+void ContentProxyModel::clear(){
+ dynamic_cast(sourceModel())->clear();
+}
\ No newline at end of file
diff --git a/linphone-app/src/components/content/ContentProxyModel.hpp b/linphone-app/src/components/content/ContentProxyModel.hpp
index 9bb9b2cdc..25a029aaf 100644
--- a/linphone-app/src/components/content/ContentProxyModel.hpp
+++ b/linphone-app/src/components/content/ContentProxyModel.hpp
@@ -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 mContens;
+ std::shared_ptr mContents;
};
diff --git a/linphone-app/src/components/core/CoreManager.cpp b/linphone-app/src/components/core/CoreManager.cpp
index 099cef8b5..9b6be783c 100644
--- a/linphone-app/src/components/core/CoreManager.cpp
+++ b/linphone-app/src/components/core/CoreManager.cpp
@@ -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);
diff --git a/linphone-app/src/components/core/CoreManager.hpp b/linphone-app/src/components/core/CoreManager.hpp
index 541759053..c219588d6 100644
--- a/linphone-app/src/components/core/CoreManager.hpp
+++ b/linphone-app/src/components/core/CoreManager.hpp
@@ -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;
diff --git a/linphone-app/src/components/other/colors/ColorListModel.hpp b/linphone-app/src/components/other/colors/ColorListModel.hpp
index 4cb3daa24..4529d9597 100644
--- a/linphone-app/src/components/other/colors/ColorListModel.hpp
+++ b/linphone-app/src/components/other/colors/ColorListModel.hpp
@@ -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")
//--------------------------------------------------------------------------------------------------------------------
/*
diff --git a/linphone-app/src/components/settings/SettingsModel.cpp b/linphone-app/src/components/settings/SettingsModel.cpp
index 8860231d4..9f1c51a7b 100644
--- a/linphone-app/src/components/settings/SettingsModel.cpp
+++ b/linphone-app/src/components/settings/SettingsModel.cpp
@@ -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.
// =============================================================================
diff --git a/linphone-app/src/components/settings/SettingsModel.hpp b/linphone-app/src/components/settings/SettingsModel.hpp
index d6f4139c3..9db273962 100644
--- a/linphone-app/src/components/settings/SettingsModel.hpp
+++ b/linphone-app/src/components/settings/SettingsModel.hpp
@@ -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();
diff --git a/linphone-app/src/components/sound-player/SoundPlayer.cpp b/linphone-app/src/components/sound-player/SoundPlayer.cpp
index 2beedeb90..fae3b9806 100644
--- a/linphone-app/src/components/sound-player/SoundPlayer.cpp
+++ b/linphone-app/src/components/sound-player/SoundPlayer.cpp
@@ -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);
diff --git a/linphone-app/src/components/timeline/TimelineProxyModel.cpp b/linphone-app/src/components/timeline/TimelineProxyModel.cpp
index f70e149ec..9d0825f5d 100644
--- a/linphone-app/src/components/timeline/TimelineProxyModel.cpp
+++ b/linphone-app/src/components/timeline/TimelineProxyModel.cpp
@@ -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();
const TimelineModel* b = sourceModel()->data(right).value();
-
- 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);
}
diff --git a/linphone-app/ui/modules/Common/Form/DroppableTextArea.qml b/linphone-app/ui/modules/Common/Form/DroppableTextArea.qml
index 5837a211f..14e802e8e 100644
--- a/linphone-app/ui/modules/Common/Form/DroppableTextArea.qml
+++ b/linphone-app/ui/modules/Common/Form/DroppableTextArea.qml
@@ -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
diff --git a/linphone-app/ui/modules/Common/Form/Fields/TextField.qml b/linphone-app/ui/modules/Common/Form/Fields/TextField.qml
index 47b90fe18..239160499 100644
--- a/linphone-app/ui/modules/Common/Form/Fields/TextField.qml
+++ b/linphone-app/ui/modules/Common/Form/Fields/TextField.qml
@@ -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()
diff --git a/linphone-app/ui/modules/Common/Indicators/MediaProgressBar.qml b/linphone-app/ui/modules/Common/Indicators/MediaProgressBar.qml
index c640b3616..89a70b7cc 100644
--- a/linphone-app/ui/modules/Common/Indicators/MediaProgressBar.qml
+++ b/linphone-app/ui/modules/Common/Indicators/MediaProgressBar.qml
@@ -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)
}
}
}
diff --git a/linphone-app/ui/modules/Common/Styles/Form/DroppableTextAreaStyle.qml b/linphone-app/ui/modules/Common/Styles/Form/DroppableTextAreaStyle.qml
index fad890de4..d72a4d0d1 100644
--- a/linphone-app/ui/modules/Common/Styles/Form/DroppableTextAreaStyle.qml
+++ b/linphone-app/ui/modules/Common/Styles/Form/DroppableTextAreaStyle.qml
@@ -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
}
diff --git a/linphone-app/ui/modules/Common/Styles/Indicators/MediaProgressBarStyle.qml b/linphone-app/ui/modules/Common/Styles/Indicators/MediaProgressBarStyle.qml
index 6ebbb6af1..9417b2d68 100644
--- a/linphone-app/ui/modules/Common/Styles/Indicators/MediaProgressBarStyle.qml
+++ b/linphone-app/ui/modules/Common/Styles/Indicators/MediaProgressBarStyle.qml
@@ -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
diff --git a/linphone-app/ui/modules/Common/View/ScrollableListView.qml b/linphone-app/ui/modules/Common/View/ScrollableListView.qml
index 33faf5f0a..1825036b1 100644
--- a/linphone-app/ui/modules/Common/View/ScrollableListView.qml
+++ b/linphone-app/ui/modules/Common/View/ScrollableListView.qml
@@ -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 =>
diff --git a/linphone-app/ui/modules/Linphone/Chat/Chat.js b/linphone-app/ui/modules/Linphone/Chat/Chat.js
index b5070780e..15075bc2c 100644
--- a/linphone-app/ui/modules/Linphone/Chat/Chat.js
+++ b/linphone-app/ui/modules/Linphone/Chat/Chat.js
@@ -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) {
diff --git a/linphone-app/ui/modules/Linphone/Chat/Chat.qml b/linphone-app/ui/modules/Linphone/Chat/Chat.qml
index a9c97f39a..ded7b7121 100644
--- a/linphone-app/ui/modules/Linphone/Chat/Chat.qml
+++ b/linphone-app/ui/modules/Linphone/Chat/Chat.qml
@@ -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
}
diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatAudioMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatAudioMessage.qml
index b304b6690..05fd3d44c 100644
--- a/linphone-app/ui/modules/Linphone/Chat/ChatAudioMessage.qml
+++ b/linphone-app/ui/modules/Linphone/Chat/ChatAudioMessage.qml
@@ -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
diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatAudioPreview.qml b/linphone-app/ui/modules/Linphone/Chat/ChatAudioPreview.qml
index 74ad98f4e..bc57cf5f8 100644
--- a/linphone-app/ui/modules/Linphone/Chat/ChatAudioPreview.qml
+++ b/linphone-app/ui/modules/Linphone/Chat/ChatAudioPreview.qml
@@ -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
diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatContent.qml b/linphone-app/ui/modules/Linphone/Chat/ChatContent.qml
index 7a8b90cb6..5b1ba13ff 100644
--- a/linphone-app/ui/modules/Linphone/Chat/ChatContent.qml
+++ b/linphone-app/ui/modules/Linphone/Chat/ChatContent.qml
@@ -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
diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatFileMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatFileMessage.qml
index 54e77b09c..7b5c0fc5c 100644
--- a/linphone-app/ui/modules/Linphone/Chat/ChatFileMessage.qml
+++ b/linphone-app/ui/modules/Linphone/Chat/ChatFileMessage.qml
@@ -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
diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatFilePreview.qml b/linphone-app/ui/modules/Linphone/Chat/ChatFilePreview.qml
new file mode 100644
index 000000000..bba5b330e
--- /dev/null
+++ b/linphone-app/ui/modules/Linphone/Chat/ChatFilePreview.qml
@@ -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()
+ }
+ }
+}
\ No newline at end of file
diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatMessagePreview.qml b/linphone-app/ui/modules/Linphone/Chat/ChatMessagePreview.qml
index d4e3ac716..46e9c1d13 100644
--- a/linphone-app/ui/modules/Linphone/Chat/ChatMessagePreview.qml
+++ b/linphone-app/ui/modules/Linphone/Chat/ChatMessagePreview.qml
@@ -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
+ }
}
\ No newline at end of file
diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatReplyMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatReplyMessage.qml
index 02577f5a9..5768e5988 100644
--- a/linphone-app/ui/modules/Linphone/Chat/ChatReplyMessage.qml
+++ b/linphone-app/ui/modules/Linphone/Chat/ChatReplyMessage.qml
@@ -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))
+ }
}
}
}
diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatReplyPreview.qml b/linphone-app/ui/modules/Linphone/Chat/ChatReplyPreview.qml
index 6449e509d..98f39aac1 100644
--- a/linphone-app/ui/modules/Linphone/Chat/ChatReplyPreview.qml
+++ b/linphone-app/ui/modules/Linphone/Chat/ChatReplyPreview.qml
@@ -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
diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatTextMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatTextMessage.qml
index d11fdd34e..0d66906e0 100644
--- a/linphone-app/ui/modules/Linphone/Chat/ChatTextMessage.qml
+++ b/linphone-app/ui/modules/Linphone/Chat/ChatTextMessage.qml
@@ -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()
diff --git a/linphone-app/ui/modules/Linphone/Chat/Message.qml b/linphone-app/ui/modules/Linphone/Chat/Message.qml
index 522f35e28..96bbe341c 100644
--- a/linphone-app/ui/modules/Linphone/Chat/Message.qml
+++ b/linphone-app/ui/modules/Linphone/Chat/Message.qml
@@ -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{
diff --git a/linphone-app/ui/modules/Linphone/File/FileView.qml b/linphone-app/ui/modules/Linphone/File/FileView.qml
new file mode 100644
index 000000000..4a5e5607a
--- /dev/null
+++ b/linphone-app/ui/modules/Linphone/File/FileView.qml
@@ -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)
+ }
+}
\ No newline at end of file
diff --git a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatAudioMessageStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatAudioMessageStyle.qml
index a2d7eac2e..585733b78 100644
--- a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatAudioMessageStyle.qml
+++ b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatAudioMessageStyle.qml
@@ -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
}
diff --git a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatAudioPreviewStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatAudioPreviewStyle.qml
index f27727b2b..e5eef4945 100644
--- a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatAudioPreviewStyle.qml
+++ b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatAudioPreviewStyle.qml
@@ -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
diff --git a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatFilePreviewStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatFilePreviewStyle.qml
new file mode 100644
index 000000000..52813ca85
--- /dev/null
+++ b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatFilePreviewStyle.qml
@@ -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
+ }
+ }
+}
diff --git a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml
index 1523a51f5..dfacfa2a3 100644
--- a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml
+++ b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml
@@ -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 {
diff --git a/linphone-app/ui/modules/Linphone/Styles/qmldir b/linphone-app/ui/modules/Linphone/Styles/qmldir
index b853636b9..b0d90c152 100644
--- a/linphone-app/ui/modules/Linphone/Styles/qmldir
+++ b/linphone-app/ui/modules/Linphone/Styles/qmldir
@@ -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
diff --git a/linphone-app/ui/modules/Linphone/Timeline/Timeline.qml b/linphone-app/ui/modules/Linphone/Timeline/Timeline.qml
index d6c682040..0bfc21755 100644
--- a/linphone-app/ui/modules/Linphone/Timeline/Timeline.qml
+++ b/linphone-app/ui/modules/Linphone/Timeline/Timeline.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.
// -------------------------------------------------------------------------
diff --git a/linphone-app/ui/modules/Linphone/qmldir b/linphone-app/ui/modules/Linphone/qmldir
index 3f216954d..d9f533348 100644
--- a/linphone-app/ui/modules/Linphone/qmldir
+++ b/linphone-app/ui/modules/Linphone/qmldir
@@ -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
diff --git a/linphone-app/ui/views/App/Calls/Incall.qml b/linphone-app/ui/views/App/Calls/Incall.qml
index 1af7b86d0..99f2f1c4e 100644
--- a/linphone-app/ui/views/App/Calls/Incall.qml
+++ b/linphone-app/ui/views/App/Calls/Incall.qml
@@ -204,11 +204,9 @@ Rectangle {
}
}
- TooltipArea {
- text: !incall.call.recording
+ tooltipText: !incall.call.recording
? qsTr('startRecordingLabel')
: qsTr('stopRecordingLabel')
- }
}
ActionButton {
diff --git a/linphone-app/ui/views/App/Calls/IncallFullscreenWindow.qml b/linphone-app/ui/views/App/Calls/IncallFullscreenWindow.qml
index b51531020..a7d467c62 100644
--- a/linphone-app/ui/views/App/Calls/IncallFullscreenWindow.qml
+++ b/linphone-app/ui/views/App/Calls/IncallFullscreenWindow.qml
@@ -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
diff --git a/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml b/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml
index 21e3e8d0e..17b5bf90d 100644
--- a/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml
+++ b/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml
@@ -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('').arg('').arg('')
- }
+
}
}
// ---------------------------------------------------------------------------
// 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('').arg('').arg('')
+ }
GridView {
id: buttons
diff --git a/linphone-app/ui/views/App/Main/Conversation.qml b/linphone-app/ui/views/App/Main/Conversation.qml
index 35aa10d5e..4c2ddbc5e 100644
--- a/linphone-app/ui/views/App/Main/Conversation.qml
+++ b/linphone-app/ui/views/App/Main/Conversation.qml
@@ -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
diff --git a/linphone-app/ui/views/App/Settings/SettingsUi.qml b/linphone-app/ui/views/App/Settings/SettingsUi.qml
index e3204b480..060f0820b 100644
--- a/linphone-app/ui/views/App/Settings/SettingsUi.qml
+++ b/linphone-app/ui/views/App/Settings/SettingsUi.qml
@@ -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
diff --git a/linphone-app/ui/views/App/Styles/Calls/CallFullscreenStyle.qml b/linphone-app/ui/views/App/Styles/Calls/CallFullscreenStyle.qml
index 4bc8bdef8..10d4d7c3b 100644
--- a/linphone-app/ui/views/App/Styles/Calls/CallFullscreenStyle.qml
+++ b/linphone-app/ui/views/App/Styles/Calls/CallFullscreenStyle.qml
@@ -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
diff --git a/linphone-app/ui/views/App/Styles/Calls/CallStyle.qml b/linphone-app/ui/views/App/Styles/Calls/CallStyle.qml
index 2ebce71fb..fd99f9932 100644
--- a/linphone-app/ui/views/App/Styles/Calls/CallStyle.qml
+++ b/linphone-app/ui/views/App/Styles/Calls/CallStyle.qml
@@ -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
diff --git a/linphone-sdk b/linphone-sdk
index b2a3ebaff..18cd2436e 160000
--- a/linphone-sdk
+++ b/linphone-sdk
@@ -1 +1 @@
-Subproject commit b2a3ebaffde438fb23c7b7d91327a35fa3a0f23d
+Subproject commit 18cd2436eda9cb72023c4727691e4a2b764966d3