mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-31 10:59:23 +00:00
New chat layout :
- Split content type to be filtered by proxy lists. - Add a message in notification when receiving a conference invitation. - Change chat bubbles colors to match mobile application. - Change date display on messages to remove sections. It allows to be more coherent when sorting messages. - Change Chat Layout : outgoing messages to right, incoming messages to left. - Change bubble design to be squared when grouped. - Group messages on 1 second away from previous (and same sender). - Add a background color with radius to files in reply messages. - Make color corners on reply. - Fix filename to 2 lines in file download icon. - Add a background color on conference invitations. - Change conference title from bold to normal on invitations. - Rework chat message content layout to be used with grids and lists : files are now displayed in grid. - Remove cyclic dependencies with reply design (which was recursivly linked with ChatContent). - Fix center layouts that were not bind to the correct one. - Align pictures to center. - Fix hidden admin usernames in participant view.
This commit is contained in:
parent
6604d2874b
commit
4532e278ac
46 changed files with 776 additions and 466 deletions
|
|
@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- OAuth2 connection to retrieve remote provisioning (Experimental and not usable without configuration).
|
||||
- Add/View contact from a message.
|
||||
- Mute option for each chatrooms.
|
||||
- New Chat Layout.
|
||||
|
||||
## 5.0.11 - undefined
|
||||
|
||||
|
|
|
|||
|
|
@ -2215,6 +2215,11 @@ Klik her: <a href="%1">%1</a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2215,6 +2215,11 @@ Klicken Sie hier: <a href="%1">%1</a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2215,6 +2215,11 @@ Click here: <a href="%1">%1</a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation>New messages received!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation>Conference invitation received!</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2215,6 +2215,11 @@ Haga clic aquí: <a href="%1">%1 </a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2215,6 +2215,11 @@ Cliquez ici : <a href="%1">%1</a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation>Nouveaux messages arrivés !</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2202,6 +2202,11 @@ Kattintson ide: <a href="%1">%1</a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2215,6 +2215,11 @@ Clicca: <a href="%1">%1</a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation>E' stato ricevuto un nuovo messaggio!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2202,6 +2202,11 @@
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2228,6 +2228,11 @@ Spustelėkite čia: <a href="%1">%1</a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2215,6 +2215,11 @@ Clique aqui: <a href="%1">%1 </a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2228,6 +2228,11 @@
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation>Получены новые сообщения!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2215,6 +2215,11 @@ Klicka här: <a href="%1">%1</a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2202,6 +2202,11 @@ Buraya tıklayın: <a href="%1">%1</a>
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2228,6 +2228,11 @@
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -2202,6 +2202,11 @@
|
|||
<extracomment>'New messages received!' Notification that warn the user of new messages.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>newConferenceInvitation</source>
|
||||
<extracomment>'Conference invitation received!' : Notification about receiving an invitation to a conference.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>OnlineInstallerDialog</name>
|
||||
|
|
|
|||
|
|
@ -331,6 +331,7 @@
|
|||
<file>ui/modules/Linphone/Chat/Chat.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatContent.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatDeliveries.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatFullContent.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatMenu.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatAudioMessage.qml</file>
|
||||
<file>ui/modules/Linphone/Chat/ChatAudioPreview.qml</file>
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ QString ChatRoomProxyModel::gCachedText;
|
|||
|
||||
// =============================================================================
|
||||
|
||||
ChatRoomProxyModel::ChatRoomProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
|
||||
ChatRoomProxyModel::ChatRoomProxyModel (QObject *parent) : SortFilterProxyModel(parent) {
|
||||
mMarkAsReadEnabled = true;
|
||||
|
||||
mDeleteSourceModel= false;
|
||||
App *app = App::getInstance();
|
||||
QObject::connect(app->getMainWindow(), &QWindow::activeChanged, this, [this]() {
|
||||
handleIsActiveChanged(App::getInstance()->getMainWindow());
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#ifndef CHAT_ROOM_PROXY_MODEL_H_
|
||||
#define CHAT_ROOM_PROXY_MODEL_H_
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include "app/proxyModel/SortFilterProxyModel.hpp"
|
||||
|
||||
#include "ChatRoomModel.hpp"
|
||||
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
class QWindow;
|
||||
|
||||
class ChatRoomProxyModel : public QSortFilterProxyModel {
|
||||
class ChatRoomProxyModel : public SortFilterProxyModel {
|
||||
class ChatRoomModelFilter;
|
||||
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -63,9 +63,25 @@ bool ContentProxyModel::filterAcceptsRow (
|
|||
int sourceRow,
|
||||
const QModelIndex &sourceParent
|
||||
) const {
|
||||
Q_UNUSED(sourceRow)
|
||||
Q_UNUSED(sourceParent)
|
||||
return true;
|
||||
|
||||
bool show = false;
|
||||
|
||||
if (mFilter == FilterContentType::All)
|
||||
show = true;
|
||||
else{
|
||||
QModelIndex index = sourceModel()->index(sourceRow, 0, QModelIndex());
|
||||
auto contentModel = sourceModel()->data(index).value<ContentModel*>();
|
||||
|
||||
if( mFilter == FilterContentType::Text && contentModel->isText())
|
||||
show = true;
|
||||
else if( mFilter == FilterContentType::Voice && contentModel->isVoiceRecording())
|
||||
show = true;
|
||||
else if( mFilter == FilterContentType::Conference && contentModel->getConferenceInfoModel())
|
||||
show = true;
|
||||
else if( mFilter == FilterContentType::File && !contentModel->isIcalendar() && (contentModel->isFile() || contentModel->isFileTransfer()|| contentModel->isFileEncrypted()) && !contentModel->isVoiceRecording() )
|
||||
show = true;
|
||||
}
|
||||
return show;
|
||||
}
|
||||
|
||||
bool ContentProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
|
||||
|
|
@ -98,4 +114,15 @@ void ContentProxyModel::remove(ContentModel * model){
|
|||
|
||||
void ContentProxyModel::clear(){
|
||||
qobject_cast<ContentListModel*>(sourceModel())->clear();
|
||||
}
|
||||
|
||||
ContentProxyModel::FilterContentType ContentProxyModel::getFilter() const{
|
||||
return mFilter;
|
||||
}
|
||||
void ContentProxyModel::setFilter(const FilterContentType& contentType){
|
||||
if(contentType != mFilter){
|
||||
mFilter = contentType;
|
||||
emit filterChanged();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
|
@ -39,10 +39,24 @@ class ContentProxyModel : public QSortFilterProxyModel {
|
|||
public:
|
||||
ContentProxyModel (QObject *parent = nullptr);
|
||||
Q_PROPERTY(ChatMessageModel * chatMessageModel READ getChatMessageModel WRITE setChatMessageModel NOTIFY chatMessageModelChanged)
|
||||
Q_PROPERTY(FilterContentType filter READ getFilter WRITE setFilter NOTIFY filterChanged)
|
||||
|
||||
enum FilterContentType {
|
||||
All,
|
||||
File,
|
||||
Text,
|
||||
Voice,
|
||||
Conference,
|
||||
Unknown
|
||||
};
|
||||
Q_ENUM(FilterContentType)
|
||||
|
||||
ChatMessageModel * getChatMessageModel() const;
|
||||
|
||||
|
||||
void setChatMessageModel(ChatMessageModel * message);
|
||||
FilterContentType getFilter() const;
|
||||
void setFilter(const FilterContentType& contentType);
|
||||
Q_INVOKABLE void setContentListModel(ContentListModel * model);
|
||||
Q_INVOKABLE void addFile(const QString& path);
|
||||
Q_INVOKABLE void remove(ContentModel * model);
|
||||
|
|
@ -50,13 +64,14 @@ public:
|
|||
|
||||
signals:
|
||||
void chatMessageModelChanged();
|
||||
void filterChanged();
|
||||
|
||||
protected:
|
||||
virtual bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
virtual bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
|
||||
|
||||
std::shared_ptr<ContentListModel> mContents;
|
||||
|
||||
FilterContentType mFilter = All;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -288,6 +288,9 @@ void Notifier::notifyReceivedMessages (const list<shared_ptr<linphone::ChatMessa
|
|||
}
|
||||
}else
|
||||
txt = tr("newFileMessage");
|
||||
if(txt.isEmpty() && message->hasConferenceInvitationContent())
|
||||
//: 'Conference invitation received!' : Notification about receiving an invitation to a conference.
|
||||
txt = tr("newConferenceInvitation");
|
||||
}else
|
||||
//: 'New messages received!' Notification that warn the user of new messages.
|
||||
txt = tr("newChatRoomMessages");
|
||||
|
|
|
|||
|
|
@ -76,8 +76,14 @@ class ColorListModel : public ProxyListModel {
|
|||
ADD_COLOR("n", "#A1A1A1", "Primary color for pressed button")
|
||||
ADD_COLOR("o", "#D0D8DE", "Primary color for disabled button")
|
||||
|
||||
ADD_COLOR("outgoing_bg","#F3F3F3","Outgoing message background")
|
||||
ADD_COLOR("incoming_bg","#D0D8DE","Incoming message background")
|
||||
ADD_COLOR("outgoing_bg","#FFEEE5","Outgoing message background")
|
||||
ADD_COLOR("incoming_bg","#F3F3F3","Incoming message background")
|
||||
|
||||
ADD_COLOR("outgoing_reply_mark_bg","#FF9E67","Outgoing reply message mark background")
|
||||
ADD_COLOR("incoming_reply_mark_bg","#9B9B9B","Incoming reply message mark background")
|
||||
|
||||
ADD_COLOR("reply_file_bg","#F4F4F4","File icon background in reply")
|
||||
ADD_COLOR("extension_file_border","#DEDEDE","File icon border in reply")
|
||||
|
||||
ADD_COLOR("primary_accept", "#9ECD1D", "Primary color for accepting button")
|
||||
|
||||
|
|
|
|||
|
|
@ -125,8 +125,8 @@ QString Utils::toTimeString(QDateTime date, const QString& format){
|
|||
return getOffsettedUTC(date).toString(format);
|
||||
}
|
||||
|
||||
QString Utils::toDateString(QDateTime date){
|
||||
return getOffsettedUTC(date).toString("yyyy/MM/dd");
|
||||
QString Utils::toDateString(QDateTime date, const QString& format){
|
||||
return getOffsettedUTC(date).toString(format);
|
||||
}
|
||||
|
||||
QString Utils::getDisplayName(const QString& address){
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public:
|
|||
static QDateTime getOffsettedUTC(const QDateTime& date);
|
||||
Q_INVOKABLE static QString toDateTimeString(QDateTime date);
|
||||
Q_INVOKABLE static QString toTimeString(QDateTime date, const QString& format = "hh:mm:ss");
|
||||
Q_INVOKABLE static QString toDateString(QDateTime date);
|
||||
Q_INVOKABLE static QString toDateString(QDateTime date, const QString& format = "yyyy/MM/dd");
|
||||
Q_INVOKABLE static QString getDisplayName(const QString& address);
|
||||
Q_INVOKABLE static QString getInitials(const QString& username); // Support UTF32
|
||||
Q_INVOKABLE static QString toString(const LinphoneEnums::TunnelMode& mode);
|
||||
|
|
|
|||
|
|
@ -97,13 +97,7 @@ Rectangle {
|
|||
container.proxyModel.loadMoreEntriesAsync()
|
||||
}
|
||||
}
|
||||
section {
|
||||
criteria: ViewSection.FullString
|
||||
delegate: sectionHeading
|
||||
property: '$sectionDate'
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Component.onCompleted: Logic.initView()
|
||||
onMovementStarted: {Logic.handleMovementStarted(); chat.isMoving = true}
|
||||
onMovementEnded: {Logic.handleMovementEnded(); chat.isMoving = false}
|
||||
|
|
@ -124,47 +118,6 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Heading.
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Component {
|
||||
id: sectionHeading
|
||||
|
||||
Item {
|
||||
implicitHeight: container.height + ChatStyle.sectionHeading.bottomMargin
|
||||
width: parent.width
|
||||
clip: false
|
||||
Borders {
|
||||
id: container
|
||||
|
||||
borderColor: ChatStyle.sectionHeading.border.colorModel.color
|
||||
bottomWidth: ChatStyle.sectionHeading.border.width
|
||||
implicitHeight: text.contentHeight +
|
||||
ChatStyle.sectionHeading.padding * 2 +
|
||||
ChatStyle.sectionHeading.border.width * 2
|
||||
topWidth: ChatStyle.sectionHeading.border.width
|
||||
width: parent.width
|
||||
|
||||
Text {
|
||||
id: text
|
||||
|
||||
anchors.fill: parent
|
||||
color: ChatStyle.sectionHeading.text.colorModel.color
|
||||
font {
|
||||
bold: true
|
||||
pointSize: ChatStyle.sectionHeading.text.pointSize
|
||||
capitalization: Font.Capitalize
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
text: new Date(section).toLocaleDateString(App.locale)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Message/Event renderer.
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
@ -174,7 +127,22 @@ Rectangle {
|
|||
property bool isNotice : $chatEntry.type === ChatRoomModel.NoticeEntry
|
||||
property bool isCall : $chatEntry.type === ChatRoomModel.CallEntry
|
||||
property bool isMessage : $chatEntry.type === ChatRoomModel.MessageEntry
|
||||
property var previousItem : proxyModel.count > 0 && index >0 ? proxyModel.getAt(index-1) : null
|
||||
property var nextItem : proxyModel.count > 0 ? proxyModel.getAt(index+1) : null // bind to count
|
||||
property bool displayDate: !Utils.equalDate(new Date($chatEntry.timestamp), new Date())
|
||||
property bool isTopGrouped: isGrouped(entry.previousItem, $chatEntry) || false
|
||||
property bool isBottomGrouped: isGrouped($chatEntry, entry.nextItem) || false
|
||||
|
||||
onIsBottomGroupedChanged: if(loader.item) loader.item.isBottomGrouped = isBottomGrouped
|
||||
onIsTopGroupedChanged: if(loader.item) loader.item.isTopGrouped = isTopGrouped
|
||||
|
||||
function isGrouped(item1, item2){
|
||||
return item1 && item2 //Have a previous entry
|
||||
&& item1.type == ChatRoomModel.MessageEntry // Previous entry is a message
|
||||
&& item2.type == ChatRoomModel.MessageEntry // Previous entry is a message
|
||||
&& item2.fromSipAddress == item1.fromSipAddress // Same user
|
||||
&& Math.abs((new Date(item2.timestamp)).getTime() - (new Date(item1.timestamp)).getTime())/1000 < 60
|
||||
}
|
||||
function isHoverEntry () {
|
||||
return mouseArea.containsMouse
|
||||
}
|
||||
|
|
@ -182,23 +150,13 @@ Rectangle {
|
|||
function removeEntry () {
|
||||
proxyModel.removeRow(index)
|
||||
}
|
||||
|
||||
anchors {
|
||||
left: parent ? parent.left : undefined
|
||||
leftMargin: isNotice?0:ChatStyle.entry.leftMargin
|
||||
right: parent ? parent.right : undefined
|
||||
|
||||
rightMargin: isNotice?0:ChatStyle.entry.deleteIconSize +
|
||||
ChatStyle.entry.message.extraContent.spacing +
|
||||
ChatStyle.entry.message.extraContent.rightMargin +
|
||||
ChatStyle.entry.message.extraContent.leftMargin +
|
||||
ChatStyle.entry.message.outgoing.areaSize
|
||||
}
|
||||
|
||||
color: ChatStyle.colorModel.color
|
||||
implicitHeight: layout.height + ChatStyle.entry.bottomMargin
|
||||
implicitHeight: layout.height + (entry.isBottomGrouped? 1 : ChatStyle.entry.bottomMargin)
|
||||
|
||||
width: chat.contentWidth // Fill all space
|
||||
clip: false
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
MouseArea {
|
||||
|
|
@ -208,51 +166,37 @@ Rectangle {
|
|||
hoverEnabled: true
|
||||
implicitHeight: layout.height
|
||||
width: parent.width + parent.anchors.rightMargin
|
||||
anchors.top: parent.top
|
||||
//anchors.topMargin: (entry.isTopGrouped? 1 : ChatStyle.entry.bottomMargin)
|
||||
clip: false
|
||||
acceptedButtons: Qt.NoButton
|
||||
onContainsMouseChanged: if(loader.item) loader.item.isHovering = containsMouse
|
||||
ColumnLayout{
|
||||
id: layout
|
||||
spacing: 0
|
||||
width: entry.width
|
||||
Text{
|
||||
id:authorName
|
||||
Layout.leftMargin: timeDisplay.width + 10
|
||||
RowLayout{
|
||||
id: headerLayout
|
||||
Layout.fillWidth: true
|
||||
text : $chatEntry.fromDisplayName ? $chatEntry.fromDisplayName : ''
|
||||
property var previousItem : {
|
||||
if(index >0)
|
||||
return proxyModel.getAt(index-1)
|
||||
else
|
||||
return null
|
||||
}
|
||||
|
||||
color: ChatStyle.entry.event.text.colorModel.color
|
||||
font.pointSize: ChatStyle.entry.event.text.pointSize
|
||||
visible: isMessage
|
||||
&& $chatEntry != undefined
|
||||
&& !$chatEntry.isOutgoing // Only outgoing
|
||||
&& (!previousItem //No previous entry
|
||||
|| previousItem.type != ChatRoomModel.MessageEntry // Previous entry is a message
|
||||
|| previousItem.fromSipAddress != $chatEntry.fromSipAddress // Different user
|
||||
|| (new Date(previousItem.timestamp)).setHours(0, 0, 0, 0) != (new Date($chatEntry.timestamp)).setHours(0, 0, 0, 0) // Same day == section
|
||||
)
|
||||
}
|
||||
RowLayout {
|
||||
|
||||
spacing: 0
|
||||
width: entry.width
|
||||
|
||||
Layout.alignment: Qt.AlignTop | ($chatEntry.isOutgoing ? Qt.AlignRight : Qt.AlignLeft)
|
||||
Layout.leftMargin: ChatStyle.entry.metaWidth// + ChatStyle.entry.message.extraContent.spacing
|
||||
Layout.rightMargin: ChatStyle.entry.message.outgoing.areaSize
|
||||
spacing:0
|
||||
// Display time.
|
||||
visible: !entry.isTopGrouped
|
||||
Text {
|
||||
id:timeDisplay
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.preferredHeight: ChatStyle.entry.lineHeight
|
||||
Layout.preferredWidth: ChatStyle.entry.time.width
|
||||
Layout.alignment: Qt.AlignTop | ($chatEntry.isOutgoing ? Qt.AlignRight : Qt.AlignLeft)
|
||||
Layout.preferredHeight: implicitHeight// ChatStyle.entry.lineHeight
|
||||
//Layout.preferredWidth: ChatStyle.entry.time.width
|
||||
|
||||
color: ChatStyle.entry.event.text.colorModel.color
|
||||
font.pointSize: ChatStyle.entry.time.pointSize
|
||||
|
||||
text: UtilsCpp.toTimeString($chatEntry.timestamp, 'hh:mm')
|
||||
property bool displayYear: entry.displayDate && (new Date($chatEntry.timestamp)).getFullYear() != (new Date()).getFullYear()
|
||||
text: $chatEntry
|
||||
? (entry.displayDate ? UtilsCpp.toDateString($chatEntry.timestamp, (displayYear ? 'yyyy/':'') + 'MM/dd') + ' ' : '')
|
||||
+ UtilsCpp.toTimeString($chatEntry.timestamp, 'hh:mm') + (authorName.visible ? ' - ' : '')
|
||||
: ''
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
|
|
@ -261,65 +205,85 @@ Rectangle {
|
|||
}
|
||||
visible:!isNotice
|
||||
}
|
||||
|
||||
// Display content.
|
||||
Loader {
|
||||
id: loader
|
||||
height: (item !== null && typeof(item)!== 'undefined')? item.height: 0
|
||||
Layout.fillWidth: true
|
||||
source: Logic.getComponentFromEntry($chatEntry)
|
||||
property int loaderIndex: 0 // index of loader from remaining loaders
|
||||
property int remainingIndex : loaderIndex % ((chat.remainingLoadersCount) / chat.syncLoaderBatch) != 0 // Check loader index to remaining loader.
|
||||
onRemainingIndexChanged: if( remainingIndex == 0 && asynchronous) asynchronous = false
|
||||
asynchronous: true
|
||||
z:1
|
||||
|
||||
onStatusChanged: if( status == Loader.Ready) {
|
||||
remainingIndex = -1 // overwrite to remove signal changed. That way, there is no more binding loops.
|
||||
--chat.remainingLoadersCount // Loader is ready: remove one from remaining count.
|
||||
}
|
||||
Text{
|
||||
id:authorName
|
||||
//Layout.leftMargin: timeDisplay.width + ChatStyle.entry.metaWidth + ChatStyle.entry.message.extraContent.spacing
|
||||
property var displayName: $chatEntry.fromDisplayName ? $chatEntry.fromDisplayName : $chatEntry.name
|
||||
text : displayName != undefined ? displayName : ''
|
||||
|
||||
Component.onCompleted: loaderIndex = ++chat.remainingLoadersCount // on new Loader : one more remaining
|
||||
Component.onDestruction: if( status != Loader.Ready) --chat.remainingLoadersCount // Remove remaining count if not loaded
|
||||
color: ChatStyle.entry.event.text.colorModel.color
|
||||
font.pointSize: ChatStyle.entry.event.text.pointSize
|
||||
visible: isMessage
|
||||
&& $chatEntry != undefined
|
||||
&& !$chatEntry.isOutgoing // Only outgoing
|
||||
&& (!entry.previousItem //No previous entry
|
||||
|| entry.previousItem.type != ChatRoomModel.MessageEntry // Previous entry is a message
|
||||
|| entry.previousItem.fromSipAddress != $chatEntry.fromSipAddress // Different user
|
||||
|| (new Date(entry.previousItem.timestamp)).setHours(0, 0, 0, 0) != (new Date($chatEntry.timestamp)).setHours(0, 0, 0, 0) // Same day == section
|
||||
)
|
||||
}
|
||||
}
|
||||
// Display content.
|
||||
Loader {
|
||||
id: loader
|
||||
height: (item !== null && typeof(item)!== 'undefined')? item.height: 0
|
||||
Layout.fillWidth: true
|
||||
source: Logic.getComponentFromEntry($chatEntry)
|
||||
property int loaderIndex: 0 // index of loader from remaining loaders
|
||||
property int remainingIndex : loaderIndex % ((chat.remainingLoadersCount) / chat.syncLoaderBatch) != 0 // Check loader index to remaining loader.
|
||||
onRemainingIndexChanged: if( remainingIndex == 0 && asynchronous) asynchronous = false
|
||||
asynchronous: true
|
||||
z:1
|
||||
|
||||
onStatusChanged: if( status == Loader.Ready) {
|
||||
loader.item.isTopGrouped = entry.isTopGrouped
|
||||
loader.item.isBottomGrouped = entry.isBottomGrouped
|
||||
remainingIndex = -1 // overwrite to remove signal changed. That way, there is no more binding loops.
|
||||
--chat.remainingLoadersCount // Loader is ready: remove one from remaining count.
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
loaderIndex = ++chat.remainingLoadersCount // on new Loader : one more remaining
|
||||
}
|
||||
Component.onDestruction: if( status != Loader.Ready) --chat.remainingLoadersCount // Remove remaining count if not loaded
|
||||
}
|
||||
|
||||
Connections{
|
||||
target: loader.item
|
||||
ignoreUnknownSignals: true
|
||||
//: "Copied to clipboard" : when a user copy a text from the menu, this message show up.
|
||||
onCopyAllDone: container.noticeBannerText = qsTr("allTextCopied")
|
||||
//: "Selection copied to clipboard" : when a user copy a text from the menu, this message show up.
|
||||
onCopySelectionDone: container.noticeBannerText = qsTr("selectedTextCopied")
|
||||
onReplyClicked: {
|
||||
proxyModel.chatRoomModel.reply = $chatEntry
|
||||
}
|
||||
onForwardClicked:{
|
||||
window.attachVirtualWindow(Qt.resolvedUrl('../Dialog/SipAddressDialog.qml')
|
||||
//: 'Choose where to forward the message' : Dialog title for choosing where to forward the current message.
|
||||
, {title: qsTr('forwardDialogTitle'),
|
||||
addressSelectedCallback: function (sipAddress) {
|
||||
var chat = CallsListModel.createChatRoom( '', proxyModel.chatRoomModel.haveEncryption, [sipAddress], false )
|
||||
if(chat){
|
||||
chat.chatRoomModel.forwardMessage($chatEntry)
|
||||
TimelineListModel.select(chat.chatRoomModel)
|
||||
}
|
||||
},
|
||||
chatRoomSelectedCallback: function (chatRoomModel){
|
||||
if(chatRoomModel){
|
||||
chatRoomModel.forwardMessage($chatEntry)
|
||||
TimelineListModel.select(chatRoomModel)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Connections{
|
||||
target: loader.item
|
||||
ignoreUnknownSignals: true
|
||||
//: "Copied to clipboard" : when a user copy a text from the menu, this message show up.
|
||||
onCopyAllDone: container.noticeBannerText = qsTr("allTextCopied")
|
||||
//: "Selection copied to clipboard" : when a user copy a text from the menu, this message show up.
|
||||
onCopySelectionDone: container.noticeBannerText = qsTr("selectedTextCopied")
|
||||
onReplyClicked: {
|
||||
proxyModel.chatRoomModel.reply = $chatEntry
|
||||
}
|
||||
onForwardClicked:{
|
||||
window.attachVirtualWindow(Qt.resolvedUrl('../Dialog/SipAddressDialog.qml')
|
||||
//: 'Choose where to forward the message' : Dialog title for choosing where to forward the current message.
|
||||
, {title: qsTr('forwardDialogTitle'),
|
||||
addressSelectedCallback: function (sipAddress) {
|
||||
var chat = CallsListModel.createChatRoom( '', proxyModel.chatRoomModel.haveEncryption, [sipAddress], false )
|
||||
if(chat){
|
||||
chat.chatRoomModel.forwardMessage($chatEntry)
|
||||
TimelineListModel.select(chat.chatRoomModel)
|
||||
}
|
||||
},
|
||||
chatRoomSelectedCallback: function (chatRoomModel){
|
||||
if(chatRoomModel){
|
||||
chatRoomModel.forwardMessage($chatEntry)
|
||||
TimelineListModel.select(chatRoomModel)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onGoToMessage:{
|
||||
container.goToMessage(message) // sometimes, there is no access to chat id (maybe because of cleaning component while loading new items). Use a global intermediate.
|
||||
}
|
||||
onConferenceIcsCopied: container.noticeBannerText = qsTr('conferencesCopiedICS')
|
||||
onAddContactClicked: container.addContactClicked(contactAddress)
|
||||
onViewContactClicked: container.viewContactClicked(contactAddress)
|
||||
onGoToMessage:{
|
||||
container.goToMessage(message) // sometimes, there is no access to chat id (maybe because of cleaning component while loading new items). Use a global intermediate.
|
||||
}
|
||||
onConferenceIcsCopied: container.noticeBannerText = qsTr('conferencesCopiedICS')
|
||||
onAddContactClicked: container.addContactClicked(contactAddress)
|
||||
onViewContactClicked: container.viewContactClicked(contactAddress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ import 'Message.js' as Logic
|
|||
Loader{
|
||||
id: mainItem
|
||||
property ContentModel contentModel
|
||||
property int maxWidth : parent.width
|
||||
property int fitWidth: active ? Math.max(maxWidth - ChatAudioMessageStyle.emptySpace, ChatAudioMessageStyle.minWidth) : 0
|
||||
property int availableWidth : parent.width
|
||||
property int fitWidth: active ? Math.max(availableWidth - ChatAudioMessageStyle.emptySpace, ChatAudioMessageStyle.minWidth) : 0
|
||||
property int fitHeight: active ? 60 : 0
|
||||
|
||||
property font customFont : SettingsModel.textMessageFont
|
||||
|
|
@ -49,7 +49,7 @@ Loader{
|
|||
property bool isPlaying : vocalPlayer.item && vocalPlayer.item.playbackState === SoundPlayer.PlayingState
|
||||
onIsPlayingChanged: isPlaying ? mediaProgressBar.resume() : mediaProgressBar.stop()
|
||||
|
||||
width: maxWidth < 0 || maxWidth > fitWidth ? fitWidth : maxWidth
|
||||
width: availableWidth < 0 || availableWidth > fitWidth ? fitWidth : availableWidth
|
||||
height: mainItem.fitHeight
|
||||
|
||||
clip: false
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ Loader{
|
|||
id: mainItem
|
||||
property ContentModel contentModel
|
||||
property ConferenceInfoModel conferenceInfoModel: contentModel ? contentModel.conferenceInfoModel : null
|
||||
property int maxWidth : parent.width
|
||||
property int availableWidth : parent.width
|
||||
property int fitHeight: active && item ? item.fitHeight : 0
|
||||
property int fitWidth: active && item ? maxWidth/2 + ChatCalendarMessageStyle.widthMargin*2 : 0
|
||||
property int fitWidth: active && item ? availableWidth/2 + ChatCalendarMessageStyle.widthMargin*2 : 0
|
||||
property bool containsMouse: false
|
||||
property int gotoButtonMode: -1 //-1: hide, 0:goto, 1:MoreInfo
|
||||
property bool isExpanded : false
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ Loader{
|
|||
id: mainItem
|
||||
property ContentModel contentModel
|
||||
property ConferenceInfoModel conferenceInfoModel: contentModel ? contentModel.conferenceInfoModel : null
|
||||
property int maxWidth : parent.width
|
||||
property int availableWidth : parent.width
|
||||
property int fitHeight: active && item ? item.fitHeight : 0 // + (isExpanded? 200 : 0): 0
|
||||
property int fitWidth: active && item ? Math.min(maxWidth > 0 ? maxWidth : 9999999, item.fitWidth + ChatCalendarMessageStyle.widthMargin*2) : 0
|
||||
property int fitWidth: active && item ? Math.min(availableWidth > 0 ? availableWidth : 9999999, item.fitWidth + ChatCalendarMessageStyle.widthMargin*2) : 0
|
||||
property bool containsMouse: false
|
||||
property int gotoButtonMode: -1 //-1: hide, 0:goto, 1:MoreInfo
|
||||
property bool isExpanded : false
|
||||
|
|
@ -56,7 +56,12 @@ Loader{
|
|||
|
||||
hoverEnabled: true
|
||||
onClicked: CallsListModel.prepareConferenceCall(mainItem.conferenceInfoModel)
|
||||
onHoveredChanged: mainItem.containsMouse = loadedItem.containsMouse
|
||||
onHoveredChanged: mainItem.containsMouse = loadedItem.containsMouse
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
color: ChatCalendarMessageStyle.backgroundColor.normal.color
|
||||
radius: 5
|
||||
}
|
||||
|
||||
ColumnLayout{
|
||||
id: layout
|
||||
|
|
@ -104,7 +109,6 @@ Loader{
|
|||
elide: Text.ElideRight
|
||||
color: ChatCalendarMessageStyle.subject.colorModel.color
|
||||
font.pointSize: ChatCalendarMessageStyle.subject.pointSize
|
||||
font.weight: Font.Bold
|
||||
text: mainItem.conferenceInfoModel.subject
|
||||
}
|
||||
RowLayout {
|
||||
|
|
|
|||
|
|
@ -16,58 +16,199 @@ import LinphoneEnums 1.0
|
|||
import ColorsList 1.0
|
||||
|
||||
// =============================================================================
|
||||
Column{
|
||||
// Simple content display without reply and forward. These modules need to be splitted because of cyclic dependencies.
|
||||
// See ChatFullContent
|
||||
|
||||
Loader{// Use of Loader because of Repeater (items cannot be loaded dynamically)
|
||||
id: mainItem
|
||||
property ContentModel contentModel
|
||||
property ChatMessageModel chatMessageModel: null
|
||||
property int availableWidth //const
|
||||
property int fileWidth: ChatStyle.entry.message.file.height * 4 / 3 + 2*ChatStyle.entry.message.file.margins
|
||||
|
||||
property int fitHeight: calendarMessage.fitHeight + message.fitHeight + fileMessage.fitHeight + audioMessage.fitHeight
|
||||
property int fitWidth: calendarMessage.fitWidth + message.fitWidth + fileMessage.fitWidth + audioMessage.fitWidth
|
||||
property color backgroundColor
|
||||
property string lastTextSelected
|
||||
property alias textColor: message.color
|
||||
property alias textFont: message.font
|
||||
property alias fileIsHovering: fileMessage.isHovering
|
||||
// Readonly
|
||||
property int bestWidth: Math.min(availableWidth, Math.max(filesBestWidth, conferencesBestWidth, textsBestWidth, voicesBestWidth))
|
||||
property int filesBestWidth: 0
|
||||
property int filesCount: 0
|
||||
property int conferencesCount: 0
|
||||
property int conferencesBestWidth: 0
|
||||
property int textsBestWidth: 0
|
||||
property int textsCount: 0
|
||||
property int voicesBestWidth: 0
|
||||
property int voicesCount: 0
|
||||
|
||||
signal isFileHoveringChanged(bool isFileHovering)
|
||||
signal lastTextSelectedChanged(string lastTextSelected)
|
||||
signal rightClicked()
|
||||
signal conferenceIcsCopied()
|
||||
|
||||
property int maxWidth
|
||||
height: fitHeight
|
||||
anchors.left: parent ? parent.left : undefined
|
||||
anchors.right: parent ? parent.right : undefined
|
||||
property bool useTextColor: false
|
||||
property color textColor
|
||||
|
||||
spacing: 0
|
||||
property int fileBorderWidth : 0
|
||||
property color fileBackgroundColor: ChatStyle.entry.message.file.extension.background.colorModel.color
|
||||
property int fileBackgroundRadius: ChatStyle.entry.message.file.extension.radius
|
||||
|
||||
property bool isOutgoing : contentModel && contentModel.chatMessageModel && (contentModel.chatMessageModel.isOutgoing || contentModel.chatMessageModel.state == LinphoneEnums.ChatMessageStateIdle);
|
||||
z: message.visible ? 0 : 1
|
||||
ChatConferenceInvitationMessage{
|
||||
id: calendarMessage
|
||||
contentModel: mainItem.contentModel
|
||||
width: parent.width
|
||||
maxWidth: mainItem.maxWidth
|
||||
gotoButtonMode: 1
|
||||
onExpandToggle: isExpanded=!isExpanded
|
||||
height: fitHeight
|
||||
z: 1
|
||||
onConferenceIcsCopied:mainItem.conferenceIcsCopied()
|
||||
}
|
||||
ChatAudioMessage{
|
||||
id: audioMessage
|
||||
contentModel: mainItem.contentModel
|
||||
visible: contentModel
|
||||
z: 1
|
||||
}
|
||||
ChatFileMessage{
|
||||
id: fileMessage
|
||||
contentModel: mainItem.contentModel
|
||||
width: parent.width
|
||||
z: 2
|
||||
}
|
||||
ChatTextMessage {
|
||||
id: message
|
||||
contentModel: mainItem.contentModel
|
||||
onLastTextSelectedChanged: mainItem.lastTextSelected = lastTextSelected
|
||||
color: isOutgoing ? ChatStyle.entry.message.outgoing.text.colorModel.color : ChatStyle.entry.message.incoming.text.colorModel.color
|
||||
onRightClicked: mainItem.rightClicked()
|
||||
active: chatMessageModel
|
||||
|
||||
sourceComponent: Component{
|
||||
Column{
|
||||
id: mainComponent
|
||||
spacing: 0
|
||||
function updateFilesBestWidth(){
|
||||
var newBestWidth = 0
|
||||
var count = 0
|
||||
for(var child in messageFilesList.children) {
|
||||
var item = messageFilesList.children[child]
|
||||
if(item){
|
||||
var a = item.fitWidth
|
||||
if(a) {
|
||||
++count
|
||||
newBestWidth = Math.max(newBestWidth,a)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(count > 1){
|
||||
newBestWidth = Math.max(newBestWidth, mainItem.fileWidth*count)
|
||||
}
|
||||
mainItem.filesCount = count
|
||||
mainItem.filesBestWidth = newBestWidth
|
||||
}
|
||||
function updateListBestWidth(listView){
|
||||
var newBestWidth = 0
|
||||
var count = 0
|
||||
for(var child in listView.contentItem.children) {
|
||||
var a = listView.contentItem.children[child].fitWidth
|
||||
if(a) {
|
||||
++count
|
||||
newBestWidth = Math.max(newBestWidth,a)
|
||||
}
|
||||
}
|
||||
return [count, newBestWidth];
|
||||
}
|
||||
ListView {
|
||||
id: messagesVoicesList
|
||||
width: parent.width
|
||||
visible: count > 0
|
||||
spacing: 0
|
||||
clip: false
|
||||
model: ContentProxyModel{
|
||||
filter: ContentProxyModel.ContentType.Voice
|
||||
chatMessageModel: mainItem.chatMessageModel
|
||||
}
|
||||
height: contentHeight
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
interactive: false
|
||||
function updateBestWidth(){
|
||||
var newWidth = mainComponent.updateListBestWidth(messagesVoicesList)
|
||||
mainItem.voicesCount = newWidth[0]
|
||||
mainItem.voicesBestWidth = newWidth[1]
|
||||
}
|
||||
delegate: ChatAudioMessage{
|
||||
id: audioMessage
|
||||
contentModel: $modelData
|
||||
visible: contentModel
|
||||
z: 1
|
||||
Component.onCompleted: messagesVoicesList.updateBestWidth()
|
||||
}
|
||||
Component.onCompleted: messagesVoicesList.updateBestWidth
|
||||
}
|
||||
// CONFERENCE
|
||||
ListView {
|
||||
id: messagesConferencesList
|
||||
width: parent.width
|
||||
visible: count > 0
|
||||
spacing: 0
|
||||
clip: false
|
||||
model: ContentProxyModel{
|
||||
filter: ContentProxyModel.ContentType.Conference
|
||||
chatMessageModel: mainItem.chatMessageModel
|
||||
}
|
||||
height: contentHeight
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
interactive: false
|
||||
function updateBestWidth(){
|
||||
var newWidth = mainComponent.updateListBestWidth(messagesConferencesList)
|
||||
mainItem.conferencesCount = newWidth[0]
|
||||
mainItem.conferencesBestWidth = newWidth[1]
|
||||
}
|
||||
Component.onCompleted: messagesConferencesList.updateBestWidth()
|
||||
delegate: ChatConferenceInvitationMessage{
|
||||
id: calendarMessage
|
||||
contentModel: $modelData
|
||||
width: parent.width
|
||||
availableWidth: mainItem.availableWidth
|
||||
gotoButtonMode: 1
|
||||
onExpandToggle: isExpanded=!isExpanded
|
||||
height: fitHeight
|
||||
z: 1
|
||||
onConferenceIcsCopied:mainItem.conferenceIcsCopied()
|
||||
onFitWidthChanged: messagesConferencesList.updateBestWidth()
|
||||
Component.onCompleted: messagesConferencesList.updateBestWidth()
|
||||
}
|
||||
}
|
||||
// FILES
|
||||
GridLayout {
|
||||
id: messageFilesList
|
||||
property alias count: repeater.count
|
||||
visible: count > 0
|
||||
clip: false
|
||||
|
||||
property int availableSection: mainItem.availableWidth / mainItem.fileWidth
|
||||
property int bestFitSection: mainItem.bestWidth / mainItem.fileWidth
|
||||
columns: Math.max(1, Math.min(availableSection , bestFitSection))
|
||||
columnSpacing: 0
|
||||
rowSpacing: 0
|
||||
width: parent.width
|
||||
Repeater{
|
||||
id: repeater
|
||||
model: ContentProxyModel{
|
||||
filter: ContentProxyModel.ContentType.File
|
||||
chatMessageModel: mainItem.chatMessageModel
|
||||
}
|
||||
ChatFileMessage{
|
||||
contentModel: $modelData
|
||||
onIsHoveringChanged: mainItem.isFileHoveringChanged(isHovering)
|
||||
borderWidth: mainItem.fileBorderWidth
|
||||
backgroundColor: mainItem.fileBackgroundColor
|
||||
backgroundRadius: mainItem.fileBackgroundRadius
|
||||
Component.onCompleted: mainComponent.updateFilesBestWidth()
|
||||
}
|
||||
}
|
||||
}
|
||||
// TEXTS
|
||||
ListView {
|
||||
id: messagesTextsList
|
||||
width: parent.width
|
||||
visible: count > 0
|
||||
spacing: 0
|
||||
clip: false
|
||||
model: ContentProxyModel{
|
||||
filter: ContentProxyModel.ContentType.Text
|
||||
chatMessageModel: mainItem.chatMessageModel
|
||||
}
|
||||
height: contentHeight
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
interactive: false
|
||||
function updateBestWidth(){
|
||||
var newWidth = mainComponent.updateListBestWidth(messagesTextsList)
|
||||
mainItem.textsCount = newWidth[0]
|
||||
mainItem.textsBestWidth = newWidth[1]
|
||||
}
|
||||
Component.onCompleted: messagesTextsList.updateBestWidth()
|
||||
delegate:
|
||||
ChatTextMessage {
|
||||
contentModel: $modelData
|
||||
onLastTextSelectedChanged: mainItem.lastTextSelectedChanged(lastTextSelected)
|
||||
color: mainItem.useTextColor
|
||||
? mainItem.textColor
|
||||
: $modelData.isOutgoing
|
||||
? ChatStyle.entry.message.outgoing.text.colorModel.color
|
||||
: ChatStyle.entry.message.incoming.text.colorModel.color
|
||||
onRightClicked: mainItem.rightClicked()
|
||||
onFitWidthChanged: messagesTextsList.updateBestWidth()
|
||||
Component.onCompleted: messagesTextsList.updateBestWidth()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,11 +19,21 @@ Row {
|
|||
property ChatMessageModel chatMessageModel: contentModel && contentModel.chatMessageModel
|
||||
property ContentModel contentModel
|
||||
property bool isOutgoing : chatMessageModel && ( chatMessageModel.isOutgoing || chatMessageModel.state == LinphoneEnums.ChatMessageStateIdle);
|
||||
property int fitWidth: visible ? Math.max( Math.max((thumbnailProvider.sourceComponent == extension ? thumbnailProvider.item.fitWidth : 0)
|
||||
property int fitHeight: ChatStyle.entry.message.file.height
|
||||
property int fitWidth: ChatStyle.entry.message.file.height * 4 / 3 + 2*ChatStyle.entry.message.file.margins
|
||||
property int borderWidth : 0
|
||||
property color backgroundColor: ChatStyle.entry.message.file.extension.background.colorModel.color
|
||||
property int backgroundRadius: ChatStyle.entry.message.file.extension.radius
|
||||
/*
|
||||
property int fitWidth: visible
|
||||
? Math.max( Math.max((thumbnailProvider.sourceComponent == extension
|
||||
? thumbnailProvider.item.fitWidth
|
||||
: 0)
|
||||
, thumbnailProvider.width + 3*ChatStyle.entry.message.file.margins)
|
||||
, Math.max(ChatStyle.entry.message.file.width, ChatStyle.entry.message.outgoing.areaSize)) : 0
|
||||
, Math.max(ChatStyle.entry.message.file.width, ChatStyle.entry.message.outgoing.areaSize))
|
||||
: 0
|
||||
property int fitHeight: visible ? rectangle.height : 0
|
||||
|
||||
*/
|
||||
property bool isAnimatedImage : mainRow.contentModel && mainRow.contentModel.wasDownloaded && UtilsCpp.isAnimatedImage(mainRow.contentModel.filePath)
|
||||
property bool haveThumbnail: mainRow.contentModel && mainRow.contentModel.thumbnail
|
||||
property bool isHovering: thumbnailProvider.state == 'hovered'
|
||||
|
|
@ -32,7 +42,8 @@ Row {
|
|||
signal copySelectionDone()
|
||||
signal forwardClicked()
|
||||
height: fitHeight
|
||||
visible: contentModel && !contentModel.isIcalendar() && (contentModel.isFile() || contentModel.isFileTransfer()) && !contentModel.isVoiceRecording()
|
||||
width: fitWidth
|
||||
visible: true
|
||||
// ---------------------------------------------------------------------------
|
||||
// File message.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -56,15 +67,14 @@ Row {
|
|||
property string thumbnail : mainRow.contentModel ? mainRow.contentModel.thumbnail : ''
|
||||
color: 'transparent'
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.leftMargin: ChatStyle.entry.message.file.margins
|
||||
anchors.topMargin: ChatStyle.entry.message.file.margins
|
||||
height: 2*ChatStyle.entry.message.file.margins + (mainRow.isAnimatedImage ? ChatStyle.entry.message.file.heightbetter
|
||||
: thumbnailProvider.sourceComponent == extension ? thumbnailProvider.item.fitHeight
|
||||
: ChatStyle.entry.message.file.height
|
||||
height: 2*ChatStyle.entry.message.file.margins + (mainRow.isAnimatedImage
|
||||
? ChatStyle.entry.message.file.heightbetter
|
||||
: thumbnailProvider.sourceComponent == extension
|
||||
? ChatStyle.entry.message.file.height
|
||||
: ChatStyle.entry.message.file.height
|
||||
)
|
||||
width: mainRow.width
|
||||
|
||||
radius: ChatStyle.entry.message.radius
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
|
@ -77,12 +87,14 @@ Row {
|
|||
Image {
|
||||
id: thumbnailImageSource
|
||||
property real scaleAnimatorTo : ChatStyle.entry.message.file.animation.thumbnailTo
|
||||
anchors.centerIn: parent
|
||||
mipmap: SettingsModel.mipmapEnabled
|
||||
source: mainRow.contentModel.thumbnail
|
||||
autoTransform: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
height: ChatStyle.entry.message.file.height
|
||||
width: height*4/3
|
||||
|
||||
Loader{
|
||||
anchors.fill: parent
|
||||
sourceComponent: Image{// Better quality on zoom
|
||||
|
|
@ -117,14 +129,18 @@ Row {
|
|||
|
||||
Rectangle {
|
||||
property int fitWidth: Math.max(downloadText.implicitWidth, Math.max(fileName.visible ? fileName.implicitWidth : 0, fileIcon.iconSize)) + 20
|
||||
property int fitHeight: fileIcon.iconSize + (fileName.visible ? fileName.implicitHeight + ChatStyle.entry.message.file.spacing : 0 )
|
||||
+ (downloadText.visible? downloadText.implicitHeight + ChatStyle.entry.message.file.spacing : 0) + 2*ChatStyle.entry.message.file.margins
|
||||
//property int fitHeight: fileIcon.iconSize + (fileName.visible ? fileName.implicitHeight + ChatStyle.entry.message.file.spacing : 0 )
|
||||
// + (downloadText.visible? downloadText.implicitHeight + ChatStyle.entry.message.file.spacing : 0) + 2*ChatStyle.entry.message.file.margins
|
||||
property real scaleAnimatorTo : ChatStyle.entry.message.file.animation.to
|
||||
|
||||
height: fitHeight
|
||||
width: fitWidth
|
||||
color: ChatStyle.entry.message.file.extension.background.colorModel.color
|
||||
radius: ChatStyle.entry.message.file.extension.radius
|
||||
anchors.centerIn: parent
|
||||
height: ChatStyle.entry.message.file.height
|
||||
width: height*4/3
|
||||
color: mainRow.backgroundColor
|
||||
radius: mainRow.backgroundRadius
|
||||
border.width: mainRow.borderWidth
|
||||
border.color: ChatStyle.entry.message.file.extension.background.borderColorModel.color
|
||||
|
||||
ColumnLayout{
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: ChatStyle.entry.message.file.margins
|
||||
|
|
@ -135,6 +151,8 @@ Row {
|
|||
Layout.alignment: Qt.AlignCenter
|
||||
icon: extensionText.text != '' ? ChatStyle.entry.message.file.extension.icon : ChatStyle.entry.message.file.extension.unknownIcon
|
||||
iconSize: ChatStyle.entry.message.file.extension.iconSize
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: iconSize
|
||||
Layout.preferredWidth: iconSize
|
||||
Text {
|
||||
|
|
@ -176,10 +194,10 @@ Row {
|
|||
visible: mainRow.contentModel && !mainRow.isAnimatedImage && !mainRow.haveThumbnail
|
||||
|
||||
color: ChatStyle.entry.message.file.extension.text.colorModel.color
|
||||
elide: Text.ElideRight
|
||||
font.pointSize: ChatStyle.entry.message.file.name.pointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
horizontalAlignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
maximumLineCount: 2
|
||||
|
||||
text: (mainRow.contentModel ? mainRow.contentModel.name : '')
|
||||
}
|
||||
|
|
@ -187,7 +205,7 @@ Row {
|
|||
id: downloadText
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredHeight: visible ? ChatStyle.entry.message.file.download.height : 0
|
||||
Layout.preferredHeight: visible ? contentHeight : 0
|
||||
//: 'Cancel' : Message link to cancel a transfer (upload/download)
|
||||
text: mainRow.contentModel ? rectangle.isTransferring ? qsTr('fileTransferCancel')
|
||||
//: 'Download' : Message link to download a file
|
||||
|
|
@ -197,8 +215,8 @@ Row {
|
|||
font.pointSize: ChatStyle.entry.message.file.download.pointSize
|
||||
color:ChatStyle.entry.message.file.extension.text.colorModel.color
|
||||
visible: (mainRow.contentModel? (!mainItem.isOutgoing && !mainRow.contentModel.wasDownloaded) || rectangle.isTransferring : false)
|
||||
horizontalAlignment: Qt.AlignCenter
|
||||
verticalAlignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -206,7 +224,7 @@ Row {
|
|||
}
|
||||
Loader {
|
||||
id: thumbnailProvider
|
||||
|
||||
anchors.centerIn: parent
|
||||
sourceComponent: (mainRow.contentModel ?
|
||||
(mainRow.isAnimatedImage ? animatedImage
|
||||
: (mainRow.haveThumbnail ? thumbnailImage : extension )
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ import 'Message.js' as Logic
|
|||
Item {
|
||||
id: mainItem
|
||||
property ChatMessageModel mainChatMessageModel
|
||||
property int maxWidth : parent.width
|
||||
property int availableWidth : parent.width
|
||||
property int fitWidth: visible ? headerArea.fitWidth + 7 + ChatForwardMessageStyle.padding * 2 : 0
|
||||
property int fitHeight: visible ? icon.height : 0
|
||||
property int fitHeight: visible ? icon.height + 5 : 0
|
||||
property font customFont : SettingsModel.textMessageFont
|
||||
|
||||
visible: mainChatMessageModel && mainChatMessageModel.isForward
|
||||
width: maxWidth > fitWidth ? fitWidth : maxWidth
|
||||
width: availableWidth > fitWidth ? fitWidth : availableWidth
|
||||
height: fitHeight
|
||||
|
||||
ColumnLayout{
|
||||
|
|
|
|||
66
linphone-app/ui/modules/Linphone/Chat/ChatFullContent.qml
Normal file
66
linphone-app/ui/modules/Linphone/Chat/ChatFullContent.qml
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import Clipboard 1.0
|
||||
import Common 1.0
|
||||
import Linphone 1.0
|
||||
|
||||
import Common.Styles 1.0
|
||||
import Linphone.Styles 1.0
|
||||
import TextToSpeech 1.0
|
||||
import Utils 1.0
|
||||
import Units 1.0
|
||||
import UtilsCpp 1.0
|
||||
import LinphoneEnums 1.0
|
||||
|
||||
import ColorsList 1.0
|
||||
|
||||
// =============================================================================
|
||||
// Full content display with reply and forward. These modules need to be splitted because of cyclic dependencies.
|
||||
// See ChatContent
|
||||
|
||||
Column{
|
||||
id: mainItem
|
||||
property ChatMessageModel chatMessageModel: null
|
||||
property int availableWidth //const
|
||||
|
||||
// Readonly
|
||||
property int bestWidth: Math.min(availableWidth, Math.max(forwardMessage.fitWidth, replyMessage.fitWidth, chatContent.bestWidth ))
|
||||
property alias filesBestWidth: chatContent.filesBestWidth
|
||||
property alias filesCount: chatContent.filesCount
|
||||
property alias textsBestWidth: chatContent.textsBestWidth
|
||||
property alias textsCount: chatContent.textsCount
|
||||
|
||||
signal isFileHoveringChanged(bool isFileHovering)
|
||||
signal lastTextSelectedChanged(string lastTextSelected)
|
||||
signal rightClicked()
|
||||
signal conferenceIcsCopied()
|
||||
signal goToMessage(var message)
|
||||
|
||||
spacing: 0
|
||||
ChatForwardMessage{
|
||||
id: forwardMessage
|
||||
mainChatMessageModel: mainItem.chatMessageModel
|
||||
visible: mainChatMessageModel && mainChatMessageModel.isForward
|
||||
availableWidth: mainItem.availableWidth
|
||||
}
|
||||
ChatReplyMessage{
|
||||
id: replyMessage
|
||||
z: 1
|
||||
mainChatMessageModel: mainItem.chatMessageModel
|
||||
visible: mainChatMessageModel && mainChatMessageModel.isReply
|
||||
availableWidth: mainItem.availableWidth
|
||||
onGoToMessage: mainItem.goToMessage(message)
|
||||
}
|
||||
ChatContent{
|
||||
id: chatContent
|
||||
chatMessageModel: mainItem.chatMessageModel
|
||||
availableWidth: mainItem.availableWidth
|
||||
width: parent.width
|
||||
|
||||
onIsFileHoveringChanged: mainItem.isFileHoveringChanged(isFileHovering)
|
||||
onLastTextSelectedChanged: mainItem.lastTextSelectedChanged(lastTextSelected)
|
||||
onRightClicked: mainItem.rightClicked()
|
||||
onConferenceIcsCopied: mainItem.conferenceIcsCopied()
|
||||
}
|
||||
}
|
||||
|
|
@ -23,16 +23,18 @@ Item {
|
|||
id: mainItem
|
||||
property ChatMessageModel chatMessageModel
|
||||
property ChatMessageModel mainChatMessageModel
|
||||
property int maxWidth : parent.width
|
||||
property int availableWidth : parent.width
|
||||
property int headerHeight: ChatReplyMessageStyle.header.replyIcon.iconSize
|
||||
property int replyHeight: (chatMessageModel ? replyMessage.height + usernameReplied.implicitHeight + ChatStyle.entry.message.padding * 3 + 3 : 0)
|
||||
property int fitWidth: visible ? Math.max(usernameReplied.implicitWidth + replyMessage.fitWidth , headerArea.fitWidth) + 7 + ChatReplyMessageStyle.padding * 2 : 0
|
||||
//property int replyHeight: (chatMessageModel ? replyMessage.height + usernameReplied.implicitHeight + ChatStyle.entry.message.padding * 3 + 3 : 0)
|
||||
//property int fitWidth: visible ? Math.max(usernameReplied.implicitWidth + replyMessage.fitWidth , headerArea.fitWidth) + 7 + ChatReplyMessageStyle.padding * 2 : 0
|
||||
property int replyHeight: (chatMessageModel ? chatContent.height + usernameReplied.implicitHeight + ChatStyle.entry.message.padding * 3 + 3 : 0)
|
||||
property int fitWidth: visible ? Math.max(usernameReplied.implicitWidth, chatContent.bestWidth , headerArea.fitWidth) + 7 + ChatReplyMessageStyle.padding * 2 : 0
|
||||
property int fitHeight: visible ? headerHeight + replyHeight : 0
|
||||
|
||||
property font customFont : SettingsModel.textMessageFont
|
||||
|
||||
visible: mainChatMessageModel && mainChatMessageModel.isReply
|
||||
width: maxWidth < 0 || maxWidth > fitWidth ? fitWidth : maxWidth
|
||||
width: availableWidth < 0 || availableWidth > fitWidth ? fitWidth : availableWidth
|
||||
height: fitHeight
|
||||
onMainChatMessageModelChanged: if( mainChatMessageModel && mainChatMessageModel.replyChatMessageModel) chatMessageModel = mainChatMessageModel.replyChatMessageModel
|
||||
|
||||
|
|
@ -80,15 +82,25 @@ Item {
|
|||
Layout.bottomMargin: ChatStyle.entry.message.padding
|
||||
Layout.leftMargin: 10
|
||||
Layout.rightMargin: 10
|
||||
clip: true
|
||||
Rectangle{
|
||||
id: colorBar
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: 7
|
||||
width: 15
|
||||
radius: 8
|
||||
color: chatMessageModel && chatMessageModel.isOutgoing ? ChatReplyMessageStyle.replyArea.outgoingMarkColor.color : ChatReplyMessageStyle.replyArea.incomingMarkColor.color
|
||||
Rectangle{
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: 5
|
||||
color: ChatReplyMessageStyle.replyArea.backgroundColor.color
|
||||
}
|
||||
}
|
||||
|
||||
radius: 5
|
||||
radius: 8
|
||||
color: ChatReplyMessageStyle.replyArea.backgroundColor.color
|
||||
visible: chatMessageModel != undefined
|
||||
Text{
|
||||
|
|
@ -98,7 +110,6 @@ Item {
|
|||
anchors.right: parent.right
|
||||
anchors.topMargin: 3
|
||||
|
||||
|
||||
leftPadding: 2 * ChatStyle.entry.message.padding
|
||||
|
||||
text: mainChatMessageModel && mainChatMessageModel.fromDisplayNameReplyMessage
|
||||
|
|
@ -108,48 +119,20 @@ Item {
|
|||
|
||||
color: ChatReplyMessageStyle.replyArea.foregroundColor.color
|
||||
}
|
||||
ScrollableListView {
|
||||
id: replyMessage
|
||||
property int fitWidth : 0
|
||||
hideScrollBars: true
|
||||
ChatContent{
|
||||
id: chatContent
|
||||
anchors.top: usernameReplied.bottom
|
||||
anchors.left: parent.left
|
||||
chatMessageModel: mainItem.chatMessageModel
|
||||
availableWidth: mainItem.availableWidth
|
||||
anchors.left: colorBar.right
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 3
|
||||
anchors.leftMargin: 5
|
||||
interactive: false
|
||||
clip: false
|
||||
useTextColor: true
|
||||
textColor: ChatReplyMessageStyle.replyArea.foregroundColor.color
|
||||
|
||||
function updateWidth(){
|
||||
var maxWidth = 0
|
||||
for(var child in replyMessage.contentItem.children) {
|
||||
var a = replyMessage.contentItem.children[child].fitWidth
|
||||
if(a)
|
||||
maxWidth = Math.max(maxWidth,a)
|
||||
}
|
||||
fitWidth = maxWidth
|
||||
}
|
||||
|
||||
model: ContentProxyModel{
|
||||
chatMessageModel: mainItem.chatMessageModel
|
||||
}
|
||||
|
||||
onContentHeightChanged: Qt.callLater( function(){replyMessage.height = replyMessage.contentHeight})
|
||||
|
||||
delegate: ChatContent{
|
||||
contentModel: $modelData
|
||||
textColor: ChatReplyMessageStyle.replyArea.foregroundColor.color
|
||||
onFitWidthChanged:{
|
||||
replyMessage.updateWidth()
|
||||
}
|
||||
Rectangle{
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
color: ChatStyle.entry.separator.colorModel.color
|
||||
height: visible ? ChatStyle.entry.separator.width : 0
|
||||
visible: (index !== (replyMessage.count - 1))
|
||||
}
|
||||
}
|
||||
fileBackgroundRadius:5
|
||||
fileBackgroundColor: ChatReplyMessageStyle.replyArea.fileBackgroundColor.color
|
||||
fileBorderWidth:1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@ import 'Chat.js' as Logic
|
|||
Rectangle{
|
||||
id: replyPreviewBlock
|
||||
property ChatRoomModel chatRoomModel
|
||||
property ChatMessageModel replyModel: chatRoomModel ? chatRoomModel.reply : null
|
||||
property int maxHeight : parent.maxHeight
|
||||
Layout.preferredHeight: visible ? Math.min(messageContentsList.height + replyPreviewHeaderArea.implicitHeight + 15, replyPreviewBlock.maxHeight) : 0
|
||||
Layout.preferredHeight: visible ? Math.min(messageContents.height + replyPreviewHeaderArea.implicitHeight + 15, replyPreviewBlock.maxHeight) : 0
|
||||
property int leftMargin: 10
|
||||
property int rightMargin: 10
|
||||
|
||||
|
|
@ -71,33 +72,19 @@ Rectangle{
|
|||
|
||||
Flickable {
|
||||
id: replyPreviewTextArea
|
||||
ScrollBar.vertical: ForceScrollBar {visible: replyPreviewTextArea.height < messageContentsList.height}
|
||||
ScrollBar.vertical: ForceScrollBar {visible: replyPreviewTextArea.height < messageContents.height}
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
contentHeight: messageContentsList.height
|
||||
contentHeight: messageContents.height
|
||||
contentWidth: width - ScrollBar.vertical.width
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
clip: true
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
ListView {
|
||||
id: messageContentsList
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
model: ContentProxyModel{
|
||||
chatMessageModel: replyPreviewBlock.chatRoomModel && replyPreviewBlock.chatRoomModel.reply
|
||||
}
|
||||
height: contentHeight
|
||||
clip: true
|
||||
delegate: ChatContent{
|
||||
contentModel: $modelData
|
||||
Rectangle{
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
color: ChatStyle.entry.separator.colorModel.color
|
||||
height: visible ? ChatStyle.entry.separator.width : 0
|
||||
visible: (index !== (messageContentsList.count - 1))
|
||||
}
|
||||
}
|
||||
ChatContent{
|
||||
id: messageContents
|
||||
width: replyPreviewTextArea.contentWidth
|
||||
chatMessageModel: replyPreviewBlock.replyModel
|
||||
availableWidth: parent.width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ TextEdit {
|
|||
property ContentModel contentModel
|
||||
property string lastTextSelected : ''
|
||||
property font customFont : SettingsModel.textMessageFont
|
||||
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
|
||||
property int fitHeight: contentHeight + padding + 8
|
||||
property int fitWidth: implicitWidth + 2 // add 2 because there is a bug on border that lead to not fit text exactly
|
||||
|
||||
signal rightClicked()
|
||||
|
||||
|
|
@ -32,8 +32,8 @@ TextEdit {
|
|||
property int removeWarningFromBindingLoop : implicitWidth // Just a dummy variable to remove meaningless binding loop on implicitWidth
|
||||
|
||||
height: fitHeight
|
||||
width: parent.width
|
||||
visible: contentModel && contentModel.isText()
|
||||
width: parent && parent.width || 1
|
||||
visible: contentModel// && contentModel.isText()
|
||||
clip: false
|
||||
padding: ChatStyle.entry.message.padding
|
||||
textMargin: 0
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ Row {
|
|||
id: mainItem
|
||||
property QtObject iconData
|
||||
property string translation
|
||||
property bool isHovering : false
|
||||
property bool isTopGrouped: false
|
||||
property bool isBottomGrouped: false
|
||||
Component.onCompleted: {
|
||||
if ($chatEntry.status == LinphoneEnums.CallStatusSuccess) {
|
||||
if(!$chatEntry.isStart){
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ RowLayout {
|
|||
|
||||
Layout.fillWidth: true
|
||||
|
||||
property alias isHovering: message.isHovering
|
||||
property alias isTopGrouped: message.isTopGrouped
|
||||
property alias isBottomGrouped: message.isBottomGrouped
|
||||
|
||||
signal copyAllDone()
|
||||
signal copySelectionDone()
|
||||
signal replyClicked()
|
||||
|
|
@ -66,16 +70,17 @@ RowLayout {
|
|||
Message {
|
||||
id: message
|
||||
|
||||
onCopyAllDone: parent.copyAllDone()
|
||||
onCopySelectionDone: parent.copySelectionDone()
|
||||
onReplyClicked: parent.replyClicked()
|
||||
onForwardClicked: parent.forwardClicked()
|
||||
onGoToMessage: parent.goToMessage(message)
|
||||
onConferenceIcsCopied: parent.conferenceIcsCopied()
|
||||
onAddContactClicked: parent.addContactClicked(contactAddress)
|
||||
onViewContactClicked: parent.viewContactClicked(contactAddress)
|
||||
onCopyAllDone: mainRow.copyAllDone()
|
||||
onCopySelectionDone: mainRow.copySelectionDone()
|
||||
onReplyClicked: mainRow.replyClicked()
|
||||
onForwardClicked: mainRow.forwardClicked()
|
||||
onGoToMessage: mainRow.goToMessage(message)
|
||||
onConferenceIcsCopied: mainRow.conferenceIcsCopied()
|
||||
onAddContactClicked: mainRow.addContactClicked(contactAddress)
|
||||
onViewContactClicked: mainRow.viewContactClicked(contactAddress)
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 10
|
||||
|
||||
// Not a style. Workaround to avoid a 0 width.
|
||||
// Arbitrary value.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQml.Models 2.15
|
||||
|
||||
import Clipboard 1.0
|
||||
import Common 1.0
|
||||
|
|
@ -16,6 +17,7 @@ import LinphoneEnums 1.0
|
|||
import ColorsList 1.0
|
||||
|
||||
import 'Message.js' as Logic
|
||||
import 'qrc:/ui/scripts/Utils/utils.js' as Utils
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
@ -25,8 +27,10 @@ Item {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
property alias backgroundColorModel: rectangle.colorModel
|
||||
|
||||
property bool isHovering : false
|
||||
default property alias _content: content.data
|
||||
property bool isTopGrouped: false
|
||||
property bool isBottomGrouped: false
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -41,94 +45,52 @@ Item {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
property string lastTextSelected
|
||||
implicitHeight: (deliveryLayout.visible? deliveryLayout.height : 0) +(ephemeralTimerRow.visible? 16 : 0) + messageData.height
|
||||
|
||||
implicitHeight: (deliveryLayout.visible? deliveryLayout.height : 0) +(ephemeralTimerRow.visible? 16 : 0) + chatContent.height
|
||||
Rectangle {
|
||||
id: rectangle
|
||||
property int maxWidth: parent.width
|
||||
property int dataWidth: maxWidth
|
||||
property int availableWidth: parent.width
|
||||
property bool ephemeral : $chatEntry.isEphemeral
|
||||
property var colorModel:{'color': 'transparent'}
|
||||
function updateWidth(){
|
||||
var maxWidth = Math.max(forwardMessage.fitWidth, replyMessage.fitWidth)
|
||||
for(var child in messageContentsList.contentItem.children) {
|
||||
var a = messageContentsList.contentItem.children[child].fitWidth
|
||||
if(a)
|
||||
maxWidth = Math.max(maxWidth,a)
|
||||
}
|
||||
rectangle.dataWidth = maxWidth
|
||||
}
|
||||
|
||||
anchors.left: !$chatEntry.isOutgoing ? parent.left : undefined
|
||||
anchors.right: $chatEntry.isOutgoing ? parent.right : undefined
|
||||
|
||||
height: parent.height - (deliveryLayout.visible? deliveryLayout.height : 0)
|
||||
radius: ChatStyle.entry.message.radius
|
||||
clip: false
|
||||
color: colorModel.color
|
||||
width: (
|
||||
ephemeralTimerRow.visible && dataWidth < ephemeralTimerRow.width + 2*ChatStyle.entry.message.padding
|
||||
width: (//implicitWidth
|
||||
ephemeralTimerRow.visible && (chatContent.bestWidth < ephemeralTimerRow.width + 2*ChatStyle.entry.message.padding)
|
||||
? ephemeralTimerRow.width + 2*ChatStyle.entry.message.padding
|
||||
: Math.min(dataWidth, maxWidth)
|
||||
: Math.min(chatContent.bestWidth, availableWidth)
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Message.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Column{
|
||||
id: messageData
|
||||
Rectangle{
|
||||
visible: container.isTopGrouped || container.isBottomGrouped
|
||||
color: parent.color
|
||||
anchors.left: !$chatEntry.isOutgoing ? parent.left : undefined
|
||||
anchors.right: $chatEntry.isOutgoing ? parent.right : undefined
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.topMargin: container.isTopGrouped ? 0 : parent.radius
|
||||
anchors.bottomMargin: container.isBottomGrouped ? 0 : parent.radius
|
||||
width: parent.radius
|
||||
}
|
||||
ChatFullContent{
|
||||
id: chatContent
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
spacing: 0
|
||||
ChatForwardMessage{
|
||||
id: forwardMessage
|
||||
mainChatMessageModel: $chatEntry
|
||||
visible: $chatEntry.isForward
|
||||
maxWidth: container.width
|
||||
onFitWidthChanged:{
|
||||
rectangle.updateWidth()
|
||||
}
|
||||
}
|
||||
ChatReplyMessage{
|
||||
id: replyMessage
|
||||
z: 1
|
||||
mainChatMessageModel: $chatEntry
|
||||
visible: $chatEntry.isReply
|
||||
maxWidth: container.width
|
||||
onFitWidthChanged:{
|
||||
rectangle.updateWidth()
|
||||
}
|
||||
onGoToMessage: container.goToMessage(message)
|
||||
}
|
||||
ListView {
|
||||
id: messageContentsList
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
visible: count > 0
|
||||
spacing: 0
|
||||
clip: false
|
||||
model: ContentProxyModel{
|
||||
chatMessageModel: $chatEntry
|
||||
}
|
||||
height: contentHeight
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
interactive: false
|
||||
delegate:
|
||||
ChatContent{
|
||||
maxWidth: container.width
|
||||
contentModel: $modelData
|
||||
onFitWidthChanged:{
|
||||
rectangle.updateWidth()
|
||||
}
|
||||
onLastTextSelectedChanged: container.lastTextSelected= lastTextSelected
|
||||
onRightClicked: chatMenu.open()
|
||||
onConferenceIcsCopied: container.conferenceIcsCopied()
|
||||
onFileIsHoveringChanged: menuButton.visible = !fileIsHovering
|
||||
Rectangle{
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
color: ChatStyle.entry.separator.colorModel.color
|
||||
height: visible ? ChatStyle.entry.separator.width : 0
|
||||
visible: (index !== (messageContentsList.count - 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
chatMessageModel: $chatEntry
|
||||
availableWidth: rectangle.availableWidth
|
||||
onLastTextSelectedChanged: container.lastTextSelected= lastTextSelected
|
||||
onGoToMessage: container.goToMessage(message)
|
||||
onRightClicked: chatMenu.open()
|
||||
onConferenceIcsCopied: container.conferenceIcsCopied()
|
||||
onIsFileHoveringChanged: menuButton.visible = !isFileHovering
|
||||
}
|
||||
Row{
|
||||
id:ephemeralTimerRow
|
||||
|
|
@ -158,7 +120,6 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Extra content.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -168,8 +129,10 @@ Item {
|
|||
|
||||
anchors {
|
||||
left: rectangle.right
|
||||
bottom: rectangle.bottom
|
||||
leftMargin: ChatStyle.entry.message.extraContent.leftMargin
|
||||
}
|
||||
|
||||
}
|
||||
ChatDeliveries{
|
||||
id: deliveryLayout
|
||||
|
|
@ -193,7 +156,7 @@ Item {
|
|||
backgroundRadius: 8
|
||||
|
||||
colorSet : ChatStyle.entry.menu
|
||||
visible: isHoverEntry()
|
||||
visible: container.isHovering
|
||||
|
||||
onClicked: chatMenu.open()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ RowLayout{
|
|||
property color eventColor : (isError ? ChatStyle.entry.event.notice.errorColor.color
|
||||
: ( isImportant ? ChatStyle.entry.event.notice.importantColor.color
|
||||
: ChatStyle.entry.event.notice.colorModel.color ))
|
||||
property bool isHovering : false
|
||||
property bool isTopGrouped: false
|
||||
property bool isBottomGrouped: false
|
||||
|
||||
Layout.preferredHeight: ChatStyle.entry.lineHeight
|
||||
spacing: ChatStyle.entry.message.extraContent.spacing
|
||||
|
|
|
|||
|
|
@ -11,9 +11,15 @@ import Utils 1.0
|
|||
// =============================================================================
|
||||
|
||||
Item {
|
||||
id: mainItem
|
||||
implicitHeight: message.height
|
||||
//width: parent.width
|
||||
Layout.fillWidth: true
|
||||
//onWidthChanged: console.log(width)
|
||||
|
||||
property alias isHovering: message.isHovering
|
||||
property alias isTopGrouped: message.isTopGrouped
|
||||
property alias isBottomGrouped: message.isBottomGrouped
|
||||
|
||||
signal copyAllDone()
|
||||
signal copySelectionDone()
|
||||
|
|
@ -23,64 +29,91 @@ Item {
|
|||
signal conferenceIcsCopied()
|
||||
signal addContactClicked(string contactAddress)
|
||||
signal viewContactClicked(string contactAddress)
|
||||
|
||||
Message {
|
||||
id: message
|
||||
|
||||
onCopyAllDone: parent.copyAllDone()
|
||||
onCopySelectionDone: parent.copySelectionDone()
|
||||
onReplyClicked: parent.replyClicked()
|
||||
onForwardClicked: parent.forwardClicked()
|
||||
onGoToMessage: parent.goToMessage(message)
|
||||
onConferenceIcsCopied: parent.conferenceIcsCopied()
|
||||
onAddContactClicked: parent.addContactClicked(contactAddress)
|
||||
onViewContactClicked: parent.viewContactClicked(contactAddress)
|
||||
|
||||
RowLayout{
|
||||
/*
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: ChatStyle.entry.metaWidth
|
||||
right: parent.right
|
||||
left: parent.left
|
||||
//leftMargin: ChatStyle.entry.metaWidth
|
||||
right: parent.right
|
||||
}
|
||||
*/
|
||||
//width: parent.width
|
||||
anchors.fill: parent
|
||||
//onWidthChanged: console.log(width)
|
||||
spacing: 0
|
||||
//spacing: ChatStyle.entry.message.extraContent.spacing
|
||||
Message {
|
||||
id: message
|
||||
|
||||
onCopyAllDone: mainItem.copyAllDone()
|
||||
onCopySelectionDone: mainItem.copySelectionDone()
|
||||
onReplyClicked: mainItem.replyClicked()
|
||||
onForwardClicked: mainItem.forwardClicked()
|
||||
onGoToMessage: mainItem.goToMessage(message)
|
||||
onConferenceIcsCopied: mainItem.conferenceIcsCopied()
|
||||
onAddContactClicked: mainItem.addContactClicked(contactAddress)
|
||||
onViewContactClicked: mainItem.viewContactClicked(contactAddress)
|
||||
/*
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: ChatStyle.entry.metaWidth
|
||||
right: parent.right
|
||||
}*/
|
||||
backgroundColorModel: ChatStyle.entry.message.outgoing.backgroundColor
|
||||
Layout.fillWidth: true
|
||||
//Layout.fillHeight: true
|
||||
Layout.leftMargin: 10
|
||||
//onImplicitHeightChanged: Layout.preferredHeight= implicitHeight
|
||||
Layout.minimumHeight: implicitHeight // Avoid bug where UI is not computed by Qt
|
||||
Layout.preferredHeight: implicitHeight
|
||||
//Layout.preferredWidth: parent.width
|
||||
//width: parent.width
|
||||
// Not a style. Workaround to avoid a 0 width.
|
||||
// Arbitrary value.
|
||||
Layout.minimumWidth: 1
|
||||
//onWidthChanged: console.log(width)
|
||||
|
||||
}
|
||||
backgroundColorModel: ChatStyle.entry.message.outgoing.backgroundColor
|
||||
width: parent.width
|
||||
|
||||
Row {
|
||||
/*
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: ChatStyle.entry.message.extraContent.leftMargin
|
||||
spacing: ChatStyle.entry.message.extraContent.spacing
|
||||
|
||||
*/
|
||||
Component {
|
||||
id: iconComponent
|
||||
|
||||
Icon {
|
||||
id: iconId
|
||||
readonly property var isError: Utils.includes([
|
||||
LinphoneEnums.ChatMessageStateFileTransferError,
|
||||
LinphoneEnums.ChatMessageStateNotDelivered,
|
||||
], $chatEntry.state)
|
||||
readonly property bool isUploaded: $chatEntry.state == LinphoneEnums.ChatMessageStateDelivered
|
||||
readonly property bool isDelivered: $chatEntry.state == LinphoneEnums.ChatMessageStateDeliveredToUser
|
||||
readonly property bool isRead: $chatEntry.state == LinphoneEnums.ChatMessageStateDisplayed
|
||||
|
||||
icon: iconId.isError
|
||||
? 'chat_error'
|
||||
: (iconId.isRead ? 'chat_read' : (iconId.isDelivered ? 'chat_delivered' : '' ) )
|
||||
iconSize: ChatStyle.entry.message.outgoing.sendIconSize
|
||||
|
||||
MouseArea {
|
||||
id:retryAction
|
||||
anchors.fill: parent
|
||||
visible: iconId.isError || $chatEntry.state == LinphoneEnums.ChatMessageStateIdle
|
||||
onClicked: $chatEntry.resendMessage()
|
||||
}
|
||||
|
||||
TooltipArea {
|
||||
id:tooltip
|
||||
visible: text != ''
|
||||
text: iconId.isError
|
||||
? qsTr('messageError')
|
||||
: (iconId.isRead ? qsTr('messageRead') : (isDelivered ? qsTr('messageDelivered') : ''))
|
||||
hoveringCursor : retryAction.visible?Qt.PointingHandCursor:Qt.ArrowCursor
|
||||
Item{
|
||||
Icon {
|
||||
id: iconId
|
||||
readonly property var isError: Utils.includes([
|
||||
LinphoneEnums.ChatMessageStateFileTransferError,
|
||||
LinphoneEnums.ChatMessageStateNotDelivered,
|
||||
], $chatEntry.state)
|
||||
readonly property bool isUploaded: $chatEntry.state == LinphoneEnums.ChatMessageStateDelivered
|
||||
readonly property bool isDelivered: $chatEntry.state == LinphoneEnums.ChatMessageStateDeliveredToUser
|
||||
readonly property bool isRead: $chatEntry.state == LinphoneEnums.ChatMessageStateDisplayed
|
||||
|
||||
icon: iconId.isError
|
||||
? 'chat_error'
|
||||
: (iconId.isRead ? 'chat_read' : (iconId.isDelivered ? 'chat_delivered' : '' ) )
|
||||
iconSize: ChatStyle.entry.message.outgoing.sendIconSize
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
MouseArea {
|
||||
id:retryAction
|
||||
anchors.fill: parent
|
||||
visible: iconId.isError || $chatEntry.state == LinphoneEnums.ChatMessageStateIdle
|
||||
onClicked: $chatEntry.resendMessage()
|
||||
}
|
||||
|
||||
TooltipArea {
|
||||
id:tooltip
|
||||
visible: text != ''
|
||||
text: iconId.isError
|
||||
? qsTr('messageError')
|
||||
: (iconId.isRead ? qsTr('messageRead') : (iconId.isDelivered ? qsTr('messageDelivered') : ''))
|
||||
hoveringCursor : retryAction.visible?Qt.PointingHandCursor:Qt.ArrowCursor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -89,8 +122,6 @@ Item {
|
|||
id: indicator
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
|
||||
|
|
@ -101,13 +132,23 @@ Item {
|
|||
}
|
||||
|
||||
Loader {
|
||||
height: ChatStyle.entry.lineHeight
|
||||
width: ChatStyle.entry.message.outgoing.areaSize
|
||||
//height: ChatStyle.entry.lineHeight
|
||||
//anchors.bottom: parent.bottom
|
||||
//Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter
|
||||
Layout.preferredWidth: ChatStyle.entry.message.outgoing.areaSize
|
||||
Layout.fillHeight: true
|
||||
//Layout.rightMargin: 10
|
||||
|
||||
sourceComponent: $chatEntry.state == LinphoneEnums.ChatMessageStateInProgress || $chatEntry.state == LinphoneEnums.ChatMessageStateFileTransferInProgress
|
||||
? indicator
|
||||
: iconComponent
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
/*
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
color: 'yellow'
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,12 +76,7 @@ Column {
|
|||
}
|
||||
Text{
|
||||
id:status
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
//anchors.top:parent.top
|
||||
//anchors.bottom : parent.bottom
|
||||
//anchors.left:parent.right
|
||||
//anchors.leftMargin:5
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
visible: text != ''
|
||||
text : ''
|
||||
|
|
|
|||
|
|
@ -18,12 +18,14 @@ QtObject {
|
|||
}
|
||||
}
|
||||
property QtObject replyArea: QtObject{
|
||||
property var outgoingMarkColor: ColorsList.add(sectionName+'_reply_outgoing_mark', 'm')
|
||||
property var incomingMarkColor: ColorsList.add(sectionName+'_reply_incoming_mark', 'r')
|
||||
property var outgoingMarkColor: ColorsList.add(sectionName+'_reply_outgoing_mark', 'outgoing_reply_mark_bg')
|
||||
property var incomingMarkColor: ColorsList.add(sectionName+'_reply_incoming_mark', 'incoming_reply_mark_bg')
|
||||
property var backgroundColor: ColorsList.add(sectionName+'_reply_bg', 'q')
|
||||
property var foregroundColor: ColorsList.add(sectionName+'_reply_fg', 'h')
|
||||
property var fileBackgroundColor: ColorsList.add(sectionName+'_reply_file_bg', 'reply_file_bg')
|
||||
property int usernamePointSizeOffset: -2
|
||||
property int pointSizeOffset: -2
|
||||
|
||||
}
|
||||
|
||||
property int padding: 8
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ QtObject {
|
|||
|
||||
property QtObject message: QtObject {
|
||||
property int padding: 8
|
||||
property int radius: 4
|
||||
property int radius: 8
|
||||
|
||||
property QtObject extraContent: QtObject {
|
||||
property int leftMargin: 10
|
||||
|
|
@ -182,7 +182,7 @@ QtObject {
|
|||
}
|
||||
|
||||
property QtObject file: QtObject {
|
||||
property int height: 80
|
||||
property int height: 120
|
||||
property int heightbetter: 200
|
||||
property int iconSize: 18
|
||||
property int margins: 8
|
||||
|
|
@ -212,10 +212,11 @@ QtObject {
|
|||
property string icon: 'file_extension_custom'
|
||||
property string unknownIcon: 'file_unknown_custom'
|
||||
property int iconSize: 60
|
||||
property int radius: 5
|
||||
property int radius: 0
|
||||
|
||||
property QtObject background: QtObject {
|
||||
property var colorModel: ColorsList.add(sectionName+'_file_extension_bg', 'q')
|
||||
property var borderColorModel: ColorsList.add(sectionName+'_file_extension_border', 'extension_file_border')
|
||||
}
|
||||
|
||||
property QtObject text: QtObject {
|
||||
|
|
@ -249,7 +250,7 @@ QtObject {
|
|||
|
||||
property QtObject incoming: QtObject {
|
||||
property var backgroundColor: ColorsList.add(sectionName+'_incoming_bg', 'incoming_bg')
|
||||
property int avatarSize: 20
|
||||
property int avatarSize: 30
|
||||
|
||||
property QtObject text: QtObject {
|
||||
property var colorModel: ColorsList.add(sectionName+'_incoming_text', 'd')
|
||||
|
|
@ -259,9 +260,9 @@ QtObject {
|
|||
|
||||
property QtObject outgoing: QtObject {
|
||||
property var backgroundColor: ColorsList.add(sectionName+'_outgoing_bg', 'outgoing_bg')
|
||||
property int areaSize: 12
|
||||
property int areaSize: 32
|
||||
property int busyIndicatorSize: 12
|
||||
property int sendIconSize: 60
|
||||
property int sendIconSize: 12
|
||||
|
||||
property QtObject text: QtObject {
|
||||
property var colorModel: ColorsList.add(sectionName+'_outgoing_text', 'd')
|
||||
|
|
|
|||
|
|
@ -18,11 +18,14 @@ IncallAvatar 1.0 Calls/IncallAvatar.qml
|
|||
CameraItem 1.0 Camera/CameraItem.qml
|
||||
CameraView 1.0 Camera/CameraView.qml
|
||||
|
||||
|
||||
Chat 1.0 Chat/Chat.qml
|
||||
ChatAudioMessage 1.0 Chat/ChatAudioMessage.qml
|
||||
ChatAudioPreview 1.0 Chat/ChatAudioPreview.qml
|
||||
ChatCalendarMessage 1.0 Chat/ChatCalendarMessage.qml
|
||||
ChatConferenceInvitationMessage 1.0 Chat/ChatConferenceInvitationMessage.qml
|
||||
ChatContent 1.0 Chat/ChatContent.qml
|
||||
ChatFullContent 1.0 Chat/ChatFullContent.qml
|
||||
ChatMessagePreview 1.0 Chat/ChatMessagePreview.qml
|
||||
ChatForwardMessage 1.0 Chat/ChatForwardMessage.qml
|
||||
ChatReplyMessage 1.0 Chat/ChatReplyMessage.qml
|
||||
|
|
|
|||
|
|
@ -722,5 +722,8 @@ function printObject(o) {
|
|||
for (var p in o) {
|
||||
out += p + ': ' + o[p] + '\n';
|
||||
}
|
||||
return out;
|
||||
if(!o)
|
||||
return 'Empty'
|
||||
else
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue