- Chat room loading optimization.

- Fix loading more chat entries when going to beginning.
- Fix right padding text in chat messages.
- Fix black screen videos.
This commit is contained in:
Julien Wadel 2022-01-26 15:37:08 +01:00
parent 3be835d378
commit 3aab79261e
24 changed files with 229 additions and 180 deletions

View file

@ -54,22 +54,41 @@ Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) {
mRefreshTimer->start(); mRefreshTimer->start();
} }
class SafeFramebuffer : public QQuickFramebufferObject::Renderer{
public:
SafeFramebuffer(){}
QOpenGLFramebufferObject *createFramebufferObject (const QSize &size) override{
return new QOpenGLFramebufferObject(size);
}
void render () override{}
void synchronize (QQuickFramebufferObject *item) override{}
};
QQuickFramebufferObject::Renderer *Camera::createRenderer () const { QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
QQuickFramebufferObject::Renderer * renderer = NULL; QQuickFramebufferObject::Renderer * renderer = NULL;
if(mIsPreview){ if(mIsPreview){
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(NULL);// Reset CoreManager::getInstance()->getCore()->setNativePreviewWindowId(NULL);// Reset
renderer=(QQuickFramebufferObject::Renderer *)CoreManager::getInstance()->getCore()->getNativePreviewWindowId(); renderer=(QQuickFramebufferObject::Renderer *)CoreManager::getInstance()->getCore()->getNativePreviewWindowId();
return renderer; CoreManager::getInstance()->getCore()->setNativePreviewWindowId(renderer);
}else{ }else{
auto call = mCallModel->getCall(); auto call = mCallModel->getCall();
if(call){ if(call){
call->setNativeVideoWindowId(NULL);// Reset call->setNativeVideoWindowId(NULL);// Reset
return (QQuickFramebufferObject::Renderer *) call->getNativeVideoWindowId(); renderer = (QQuickFramebufferObject::Renderer *) call->getNativeVideoWindowId();
call->setNativeVideoWindowId(renderer);
}else{ }else{
CoreManager::getInstance()->getCore()->setNativeVideoWindowId(NULL); CoreManager::getInstance()->getCore()->setNativeVideoWindowId(NULL);
return (QQuickFramebufferObject::Renderer *) CoreManager::getInstance()->getCore()->getNativeVideoWindowId(); renderer = (QQuickFramebufferObject::Renderer *) CoreManager::getInstance()->getCore()->getNativeVideoWindowId();
CoreManager::getInstance()->getCore()->setNativeVideoWindowId(renderer);
} }
} }
if(renderer)
return renderer;
else{
qWarning() << "Camera stream couldn't start for Rendering";
return new SafeFramebuffer();
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View file

@ -88,6 +88,7 @@ QQuickFramebufferObject::Renderer *CameraPreview::createRenderer () const {
QQuickFramebufferObject::Renderer * renderer; QQuickFramebufferObject::Renderer * renderer;
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(NULL);// Reset CoreManager::getInstance()->getCore()->setNativePreviewWindowId(NULL);// Reset
renderer=(QQuickFramebufferObject::Renderer *)CoreManager::getInstance()->getCore()->getNativePreviewWindowId(); renderer=(QQuickFramebufferObject::Renderer *)CoreManager::getInstance()->getCore()->getNativePreviewWindowId();
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(renderer);
if(renderer) if(renderer)
return renderer; return renderer;
else{ else{

View file

@ -525,6 +525,9 @@ bool ChatRoomModel::getIsRemoteComposing () const {
return mComposers.size() > 0; return mComposers.size() > 0;
} }
bool ChatRoomModel::isEntriesLoading() const{
return mEntriesLoading;
}
std::shared_ptr<linphone::ChatRoom> ChatRoomModel::getChatRoom(){ std::shared_ptr<linphone::ChatRoom> ChatRoomModel::getChatRoom(){
return mChatRoom; return mChatRoom;
@ -885,6 +888,7 @@ void ChatRoomModel::updateNewMessageNotice(const int& count){
} }
void ChatRoomModel::initEntries(){ void ChatRoomModel::initEntries(){
qDebug() << "Internal Entries : Init";
// On call : reinitialize all entries. This allow to free up memory // On call : reinitialize all entries. This allow to free up memory
QList<std::shared_ptr<ChatEvent> > entries; QList<std::shared_ptr<ChatEvent> > entries;
QList<EntrySorterHelper> prepareEntries; QList<EntrySorterHelper> prepareEntries;
@ -909,7 +913,7 @@ void ChatRoomModel::initEntries(){
} }
} }
EntrySorterHelper::getLimitedSelection(&entries, prepareEntries, mLastEntriesStep, this); EntrySorterHelper::getLimitedSelection(&entries, prepareEntries, mLastEntriesStep, this);
qDebug() << "Internal Entries : Built";
mIsInitialized = true; mIsInitialized = true;
if(entries.size() >0){ if(entries.size() >0){
beginResetModel(); beginResetModel();
@ -917,9 +921,21 @@ void ChatRoomModel::initEntries(){
updateNewMessageNotice(mChatRoom->getUnreadMessagesCount()); updateNewMessageNotice(mChatRoom->getUnreadMessagesCount());
endResetModel(); endResetModel();
} }
qDebug() << "Internal Entries : End";
}
void ChatRoomModel::setEntriesLoading(const bool& loading){
if( mEntriesLoading != loading){
mEntriesLoading = loading;
emit entriesLoadingChanged(mEntriesLoading);
qApp->processEvents();
}
} }
int ChatRoomModel::loadMoreEntries(){ int ChatRoomModel::loadMoreEntries(){
setEntriesLoading(true);
int currentRowCount = rowCount();
int newEntries = 0;
do{
QList<std::shared_ptr<ChatEvent> > entries; QList<std::shared_ptr<ChatEvent> > entries;
QList<EntrySorterHelper> prepareEntries; QList<EntrySorterHelper> prepareEntries;
// Get current event count for each type // Get current event count for each type
@ -985,10 +1001,15 @@ int ChatRoomModel::loadMoreEntries(){
for(auto entry : entries) for(auto entry : entries)
mEntries.prepend(entry); mEntries.prepend(entry);
endInsertRows(); endInsertRows();
emit layoutChanged(); //emit layoutChanged();
updateLastUpdateTime(); updateLastUpdateTime();
} }
return entries.size(); newEntries = entries.size();
}while( newEntries>0 && currentRowCount == rowCount());
currentRowCount = rowCount() - currentRowCount + 1;
setEntriesLoading(false);
emit moreEntriesLoaded(currentRowCount);
return currentRowCount;
} }
//------------------------------------------------- //-------------------------------------------------

View file

@ -155,6 +155,8 @@ public:
Q_PROPERTY(ChatMessageModel * reply READ getReply WRITE setReply NOTIFY replyChanged) Q_PROPERTY(ChatMessageModel * reply READ getReply WRITE setReply NOTIFY replyChanged)
Q_PROPERTY(bool entriesLoading READ isEntriesLoading WRITE setEntriesLoading NOTIFY entriesLoadingChanged)
//ChatRoomModel (const QString &peerAddress, const QString &localAddress, const bool& isSecure); //ChatRoomModel (const QString &peerAddress, const QString &localAddress, const bool& isSecure);
@ -199,6 +201,7 @@ public:
bool isCurrentProxy() const; // Return true if this chat room is Me() is the current proxy bool isCurrentProxy() const; // Return true if this chat room is Me() is the current proxy
bool canHandleParticipants() const; bool canHandleParticipants() const;
bool getIsRemoteComposing () const; bool getIsRemoteComposing () const;
bool isEntriesLoading() const;
ParticipantListModel* getParticipants() const; ParticipantListModel* getParticipants() const;
std::shared_ptr<linphone::ChatRoom> getChatRoom(); std::shared_ptr<linphone::ChatRoom> getChatRoom();
QList<QString> getComposers(); QList<QString> getComposers();
@ -208,6 +211,7 @@ public:
void setSubject(QString& subject); void setSubject(QString& subject);
void setLastUpdateTime(const QDateTime& lastUpdateDate); void setLastUpdateTime(const QDateTime& lastUpdateDate);
void updateLastUpdateTime(); void updateLastUpdateTime();
void setEntriesLoading(const bool& loading);
void setUnreadMessagesCount(const int& count); void setUnreadMessagesCount(const int& count);
void setMissedCallsCount(const int& count); void setMissedCallsCount(const int& count);
@ -243,6 +247,7 @@ public:
bool mDeleteChatRoom = false; // Use as workaround because of core->deleteChatRoom() that call destructor without takking account of count ref : call it in ChatRoomModel destructor bool mDeleteChatRoom = false; // Use as workaround because of core->deleteChatRoom() that call destructor without takking account of count ref : call it in ChatRoomModel destructor
int mLastEntriesStep = 50; // Retrieve a part of the history to avoid too much processing int mLastEntriesStep = 50; // Retrieve a part of the history to avoid too much processing
bool mMarkAsReadEnabled = true; bool mMarkAsReadEnabled = true;
bool mEntriesLoading = false;
void insertCall (const std::shared_ptr<linphone::CallLog> &callLog); void insertCall (const std::shared_ptr<linphone::CallLog> &callLog);
@ -289,6 +294,8 @@ public slots:
signals: signals:
bool isRemoteComposingChanged (); bool isRemoteComposingChanged ();
void entriesLoadingChanged(const bool& loading);
void moreEntriesLoaded(const int& count);
void allEntriesRemoved (std::shared_ptr<ChatRoomModel> model); void allEntriesRemoved (std::shared_ptr<ChatRoomModel> model);
void lastEntryRemoved (); void lastEntryRemoved ();

View file

@ -19,6 +19,7 @@
*/ */
#include <QQuickWindow> #include <QQuickWindow>
#include <QTimer>
#include "app/App.hpp" #include "app/App.hpp"
#include "components/core/CoreManager.hpp" #include "components/core/CoreManager.hpp"
@ -140,16 +141,16 @@ void ChatRoomProxyModel::compose (const QString& text) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void ChatRoomProxyModel::loadMoreEntriesAsync(){
QTimer::singleShot(10, this, &ChatRoomProxyModel::loadMoreEntries);
}
void ChatRoomProxyModel::onMoreEntriesLoaded(const int& count){
emit moreEntriesLoaded(count);
}
void ChatRoomProxyModel::loadMoreEntries() { void ChatRoomProxyModel::loadMoreEntries() {
if(mChatRoomModel ) { if(mChatRoomModel ) {
int currentRowCount = rowCount(); mChatRoomModel->loadMoreEntries();
int newEntries = 0;
do{
newEntries = mChatRoomModel->loadMoreEntries();
invalidate();
}while( newEntries>0 && currentRowCount == rowCount());
currentRowCount = rowCount() - currentRowCount + 1;
emit moreEntriesLoaded(currentRowCount);
} }
} }
@ -228,7 +229,6 @@ QString ChatRoomProxyModel::getFullPeerAddress () const {
void ChatRoomProxyModel::setFullPeerAddress (const QString &peerAddress) { void ChatRoomProxyModel::setFullPeerAddress (const QString &peerAddress) {
mFullPeerAddress = peerAddress; mFullPeerAddress = peerAddress;
emit fullPeerAddressChanged(mFullPeerAddress); emit fullPeerAddressChanged(mFullPeerAddress);
//reload();
} }
QString ChatRoomProxyModel::getFullLocalAddress () const { QString ChatRoomProxyModel::getFullLocalAddress () const {
@ -238,7 +238,6 @@ QString ChatRoomProxyModel::getFullLocalAddress () const {
void ChatRoomProxyModel::setFullLocalAddress (const QString &localAddress) { void ChatRoomProxyModel::setFullLocalAddress (const QString &localAddress) {
mFullLocalAddress = localAddress; mFullLocalAddress = localAddress;
emit fullLocalAddressChanged(mFullLocalAddress); emit fullLocalAddressChanged(mFullLocalAddress);
//reload();
} }
bool ChatRoomProxyModel::markAsReadEnabled() const{ bool ChatRoomProxyModel::markAsReadEnabled() const{
@ -277,6 +276,7 @@ void ChatRoomProxyModel::reload (ChatRoomModel *chatRoomModel) {
QObject::disconnect(ChatRoomModel, &ChatRoomModel::messageReceived, this, &ChatRoomProxyModel::handleMessageReceived); QObject::disconnect(ChatRoomModel, &ChatRoomModel::messageReceived, this, &ChatRoomProxyModel::handleMessageReceived);
QObject::disconnect(ChatRoomModel, &ChatRoomModel::messageSent, this, &ChatRoomProxyModel::handleMessageSent); QObject::disconnect(ChatRoomModel, &ChatRoomModel::messageSent, this, &ChatRoomProxyModel::handleMessageSent);
QObject::disconnect(ChatRoomModel, &ChatRoomModel::markAsReadEnabledChanged, this, &ChatRoomProxyModel::markAsReadEnabledChanged); QObject::disconnect(ChatRoomModel, &ChatRoomModel::markAsReadEnabledChanged, this, &ChatRoomProxyModel::markAsReadEnabledChanged);
QObject::disconnect(ChatRoomModel, &ChatRoomModel::moreEntriesLoaded, this, &ChatRoomProxyModel::onMoreEntriesLoaded);
} }
@ -289,6 +289,7 @@ void ChatRoomProxyModel::reload (ChatRoomModel *chatRoomModel) {
QObject::connect(ChatRoomModel, &ChatRoomModel::messageReceived, this, &ChatRoomProxyModel::handleMessageReceived); QObject::connect(ChatRoomModel, &ChatRoomModel::messageReceived, this, &ChatRoomProxyModel::handleMessageReceived);
QObject::connect(ChatRoomModel, &ChatRoomModel::messageSent, this, &ChatRoomProxyModel::handleMessageSent); QObject::connect(ChatRoomModel, &ChatRoomModel::messageSent, this, &ChatRoomProxyModel::handleMessageSent);
QObject::connect(ChatRoomModel, &ChatRoomModel::markAsReadEnabledChanged, this, &ChatRoomProxyModel::markAsReadEnabledChanged); QObject::connect(ChatRoomModel, &ChatRoomModel::markAsReadEnabledChanged, this, &ChatRoomProxyModel::markAsReadEnabledChanged);
QObject::connect(ChatRoomModel, &ChatRoomModel::moreEntriesLoaded, this, &ChatRoomProxyModel::onMoreEntriesLoaded);
} }
static_cast<ChatRoomModelFilter *>(sourceModel())->setSourceModel(mChatRoomModel.get()); static_cast<ChatRoomModelFilter *>(sourceModel())->setSourceModel(mChatRoomModel.get());

View file

@ -55,6 +55,8 @@ public:
Q_INVOKABLE QString getDisplayNameComposers()const; Q_INVOKABLE QString getDisplayNameComposers()const;
Q_INVOKABLE QVariant getAt(int row); Q_INVOKABLE QVariant getAt(int row);
Q_INVOKABLE void loadMoreEntriesAsync ();
Q_INVOKABLE void loadMoreEntries (); Q_INVOKABLE void loadMoreEntries ();
Q_INVOKABLE void setEntryTypeFilter (int type); Q_INVOKABLE void setEntryTypeFilter (int type);
@ -73,6 +75,9 @@ public:
Q_INVOKABLE void setFilterText(const QString& text); Q_INVOKABLE void setFilterText(const QString& text);
public slots:
void onMoreEntriesLoaded(const int& count);
signals: signals:
void peerAddressChanged (const QString &peerAddress); void peerAddressChanged (const QString &peerAddress);
void localAddressChanged (const QString &localAddress); void localAddressChanged (const QString &localAddress);

View file

@ -102,10 +102,7 @@ void TimelineModel::setSelected(const bool& selected){
mChatRoomModel->initEntries(); mChatRoomModel->initEntries();
} }
emit selectedChanged(mSelected); emit selectedChanged(mSelected);
}else if(selected)// Warning, Setting to true is only when we want to force a selection. It's why we send a signal only in this case. We want avoid to change the counter on timelines that are already unselected. }
// This only work because we want at least only one timeline selected
emit selectedChanged(mSelected);
} }
void TimelineModel::updateUnreadCount(){ void TimelineModel::updateUnreadCount(){

View file

@ -39,7 +39,7 @@ BusyIndicator {
RotationAnimator { RotationAnimator {
duration: BusyIndicatorStyle.duration duration: BusyIndicatorStyle.duration
loops: Animation.Infinite loops: Animation.Infinite
running: busyIndicator.visible && busyIndicator.running running: true
target: item target: item
from: 0 from: 0

View file

@ -35,6 +35,7 @@ Item {
property bool colorOverwriteEnabled : false property bool colorOverwriteEnabled : false
mipmap: SettingsModel.mipmapEnabled mipmap: SettingsModel.mipmapEnabled
cache: Images.areReadOnlyImages cache: Images.areReadOnlyImages
asynchronous: true
//anchors.centerIn: parent //anchors.centerIn: parent
anchors.fill: parent anchors.fill: parent

View file

@ -41,8 +41,8 @@ ListView {
policy: (view.contentHeight > view.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff) policy: (view.contentHeight > view.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff)
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
boundsMovement: Flickable.StopAtBounds
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.DragOverBounds
clip: true clip: true
contentWidth: width - (vScrollBar.visible?vScrollBar.width:0) contentWidth: width - (vScrollBar.visible?vScrollBar.width:0)
spacing: 0 spacing: 0

View file

@ -31,8 +31,12 @@
// ============================================================================= // =============================================================================
function initView () { function initView () {
chat.tryToLoadMoreEntries = false
chat.bindToEnd = true chat.bindToEnd = true
chat.positionViewAtEnd()
if(chat.atYBeginning && !chat.loadingEntries){//Check if we are at beginning
chat.displaying = true
container.proxyModel.loadMoreEntriesAsync()
}
} }
function getComponentFromEntry (chatEntry) { function getComponentFromEntry (chatEntry) {
@ -76,8 +80,4 @@ function sendMessage (text) {
chat.bindToEnd = true chat.bindToEnd = true
if(container.proxyModel) if(container.proxyModel)
container.proxyModel.sendMessage(text) container.proxyModel.sendMessage(text)
/*
else{// Create a chat room
CallsListModel.createChat()
}*/
} }

View file

@ -39,61 +39,42 @@ Rectangle {
id: chat id: chat
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
property bool bindToEnd: false property bool bindToEnd: false
property bool tryToLoadMoreEntries: true property bool displaying: false
//property var sipAddressObserver: SipAddressesModel.getSipAddressObserver(proxyModel.fullPeerAddress, proxyModel.fullLocalAddress) property int loaderCount: 0
property int readyItems : 0
property bool loadingLoader: (readyItems != loaderCount)
property bool loadingEntries: container.proxyModel.chatRoomModel.entriesLoading || displaying
property bool tryToLoadMoreEntries: loadingEntries || loadingLoader
property bool isMoving : false // replace moving read-only property to allow using movement signals.
onLoadingEntriesChanged: {
if( loadingEntries && !displaying)
displaying = true
}
//property var sipAddressObserver: SipAddressesModel.getSipAddressObserver(proxyModel.fullPeerAddress, proxyModel.fullLocalAddress)
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
highlightFollowsCurrentItem: false highlightFollowsCurrentItem: false
// Use moving event => this is a user action.
onIsMovingChanged:{
if(!chat.isMoving && chat.atYBeginning && !chat.loadingEntries){// Moving has stopped. Check if we are at beginning
chat.displaying = true
container.proxyModel.loadMoreEntriesAsync()
}
}
section { section {
criteria: ViewSection.FullString criteria: ViewSection.FullString
delegate: sectionHeading delegate: sectionHeading
property: '$sectionDate' property: '$sectionDate'
} }
Timer {
id: loadMoreEntriesDelayer
interval: 1
repeat: false
running: false
onTriggered: {
chat.positionViewAtBeginning()
container.proxyModel.loadMoreEntries()
}
}
Timer {
// Delay each search by 100ms
id: endOfLoadMoreEntriesDelayer
interval: 100
repeat: false
running: false
onTriggered: {
if(chat.atYBeginning){// We are still at the beginning. Try to continue searching
loadMoreEntriesDelayer.start()
}else// We are not at the begining. New search can be done by moving to the top.
chat.tryToLoadMoreEntries = false
}
}
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
Component.onCompleted: Logic.initView() Component.onCompleted: Logic.initView()
onMovementStarted: {Logic.handleMovementStarted(); chat.isMoving = true}
onContentYChanged: { onMovementEnded: {Logic.handleMovementEnded(); chat.isMoving = false}
if (chat.atYBeginning && !chat.tryToLoadMoreEntries) {
chat.tryToLoadMoreEntries = true// Show busy indicator
loadMoreEntriesDelayer.start()// Let GUI time to the busy indicator to be shown
}
}
onMovementEnded: Logic.handleMovementEnded()
onMovementStarted: Logic.handleMovementStarted()
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@ -104,12 +85,10 @@ Rectangle {
// the position is set at end and it can be possible to load // the position is set at end and it can be possible to load
// more entries. // more entries.
onEntryTypeFilterChanged: Logic.initView() onEntryTypeFilterChanged: Logic.initView()
onMoreEntriesLoaded: { onMoreEntriesLoaded: {
Logic.handleMoreEntriesLoaded(n) Logic.handleMoreEntriesLoaded(n)// move view to n - 1 item
if(n>1)// New entries : delay the end chat.displaying = false
endOfLoadMoreEntriesDelayer.start()
else// No new entries, we can stop without waiting
chat.tryToLoadMoreEntries = false
} }
} }
@ -258,8 +237,18 @@ Rectangle {
// Display content. // Display content.
Loader { Loader {
id: loader id: loader
height: (item !== null && typeof(item)!== 'undefined')? item.height: 0
Layout.fillWidth: true Layout.fillWidth: true
source: Logic.getComponentFromEntry($chatEntry) source: Logic.getComponentFromEntry($chatEntry)
property int count: 0
asynchronous: chat.count - count > 100
onStatusChanged: if( status == Loader.Ready) ++chat.readyItems
Component.onCompleted: count = ++chat.loaderCount
Component.onDestruction: {
--chat.loaderCount
if( status == Loader.Ready)
--chat.readyItems
}
} }
Connections{ Connections{
target: loader.item target: loader.item
@ -300,16 +289,17 @@ Rectangle {
width: parent.width width: parent.width
Text { Text {
id: composersItem id: composersItem
property var composers : container.proxyModel.chatRoomModel && container.proxyModel.chatRoomModel.composers property var composers : container.proxyModel.chatRoomModel ? container.proxyModel.chatRoomModel.composers : undefined
property int count : composers && composers.length ? composers.length : 0
color: ChatStyle.composingText.color color: ChatStyle.composingText.color
font.pointSize: ChatStyle.composingText.pointSize font.pointSize: ChatStyle.composingText.pointSize
height: visible ? undefined : 0 height: visible ? undefined : 0
leftPadding: ChatStyle.composingText.leftPadding leftPadding: ChatStyle.composingText.leftPadding
visible: composers && composers.length > 0 && ( (!proxyModel.chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled) visible: count > 0 && ( (!proxyModel.chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled)
|| (proxyModel.chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled) ) || (proxyModel.chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled) )
wrapMode: Text.Wrap wrapMode: Text.Wrap
//: '%1 is typing...' indicate that someone is composing in chat //: '%1 is typing...' indicate that someone is composing in chat
text:(!composers || composers.length==0?'': qsTr('chatTyping','',composers.length).arg(container.proxyModel.getDisplayNameComposers())) text:(count==0?'': qsTr('chatTyping','',count).arg(container.proxyModel.getDisplayNameComposers()))
} }
} }

View file

@ -24,7 +24,7 @@ TextEdit {
property string lastTextSelected : '' property string lastTextSelected : ''
property font customFont : SettingsModel.textMessageFont property font customFont : SettingsModel.textMessageFont
property int fitHeight: visible ? contentHeight + padding : 0 property int fitHeight: visible ? contentHeight + padding : 0
property int fitWidth: visible ? implicitWidth + padding*2 : 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() signal rightClicked()
@ -36,10 +36,12 @@ TextEdit {
visible: contentModel && contentModel.isText() visible: contentModel && contentModel.isText()
clip: true clip: true
padding: ChatStyle.entry.message.padding padding: ChatStyle.entry.message.padding
textMargin: 0
readOnly: true readOnly: true
selectByMouse: true selectByMouse: true
font.family: customFont.family font.family: customFont.family
font.pointSize: Units.dp * customFont.pointSize font.pointSize: Units.dp * customFont.pointSize
text: visible ? Utils.encodeTextToQmlRichFormat(contentModel.text, { text: visible ? Utils.encodeTextToQmlRichFormat(contentModel.text, {
imagesHeight: ChatStyle.entry.message.images.height, imagesHeight: ChatStyle.entry.message.images.height,
imagesWidth: ChatStyle.entry.message.images.width imagesWidth: ChatStyle.entry.message.images.width
@ -51,7 +53,7 @@ TextEdit {
textFormat: Text.RichText // To supports links and imgs. textFormat: Text.RichText // To supports links and imgs.
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
onCursorRectangleChanged: if(!readOnly) Logic.ensureVisible(cursorRectangle) //onCursorRectangleChanged: if(!readOnly) Logic.ensureVisible(cursorRectangle)
onLinkActivated: Qt.openUrlExternally(link) onLinkActivated: Qt.openUrlExternally(link)
onSelectedTextChanged:{ onSelectedTextChanged:{
if(selectedText != '') lastTextSelected = selectedText if(selectedText != '') lastTextSelected = selectedText

View file

@ -93,8 +93,7 @@ DialogPlus {
updateSelectionModels: false updateSelectionModels: false
anchors.fill: parent anchors.fill: parent
model: TimelineProxyModel{} model: TimelineProxyModel{}
onEntrySelected:{ onEntryClicked:{
console.log(entry)
if( entry ) { if( entry ) {
mainItem.chatRoomSelectedCallback(entry.chatRoomModel) mainItem.chatRoomSelectedCallback(entry.chatRoomModel)
exit(1) exit(1)

View file

@ -38,7 +38,7 @@ function loadMoreEntries () {
if (history.atYBeginning && !history.tryToLoadMoreEntries) { if (history.atYBeginning && !history.tryToLoadMoreEntries) {
history.tryToLoadMoreEntries = true history.tryToLoadMoreEntries = true
history.positionViewAtBeginning() history.positionViewAtBeginning()
container.proxyModel.loadMoreEntries() container.proxyModel.loadMoreEntriesAsync()
} }
} }

View file

@ -49,7 +49,7 @@ Rectangle {
Component.onCompleted: Logic.initView() Component.onCompleted: Logic.initView()
onContentYChanged: Logic.loadMoreEntries() onContentYChanged: Logic.loadMoreEntriesAsync()
onMovementEnded: Logic.handleMovementEnded() onMovementEnded: Logic.handleMovementEnded()
onMovementStarted: Logic.handleMovementStarted() onMovementStarted: Logic.handleMovementStarted()

View file

@ -86,6 +86,7 @@ Notification {
onClicked: notification._close(function () { onClicked: notification._close(function () {
AccountSettingsModel.setDefaultProxyConfigFromSipAddress(notification.localAddress) AccountSettingsModel.setDefaultProxyConfigFromSipAddress(notification.localAddress)
notification.timelineModel.selected = true notification.timelineModel.selected = true
console.log("Load conversation from notification")
notification.notificationData.window.setView('Conversation', { notification.notificationData.window.setView('Conversation', {
chatRoomModel:notification.timelineModel.getChatRoomModel() chatRoomModel:notification.timelineModel.getChatRoomModel()
}) })

View file

@ -164,7 +164,7 @@ QtObject {
} }
property QtObject message: QtObject { property QtObject message: QtObject {
property int padding: 8 property int padding: 10
property int radius: 4 property int radius: 4
property QtObject extraContent: QtObject { property QtObject extraContent: QtObject {

View file

@ -28,6 +28,7 @@ Rectangle {
//signal entrySelected (string entry) //signal entrySelected (string entry)
signal entrySelected (TimelineModel entry) signal entrySelected (TimelineModel entry)
signal entryClicked(TimelineModel entry)
signal showHistoryRequest() signal showHistoryRequest()
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -329,8 +330,8 @@ Rectangle {
preventStealing: false preventStealing: false
onClicked: { onClicked: {
if(mouse.button == Qt.LeftButton){ if(mouse.button == Qt.LeftButton){
if(modelData.selected || !view.updateSelectionModels)// Update selection //if(modelData.selected || !view.updateSelectionModels)// Update selection
timeline.entrySelected(modelData) timeline.entryClicked(modelData)
if(view){ if(view){
if(view.updateSelectionModels) if(view.updateSelectionModels)
modelData.selected = true modelData.selected = true

View file

@ -216,8 +216,6 @@ Window {
fullPeerAddress: window.call.fullPeerAddress fullPeerAddress: window.call.fullPeerAddress
fullLocalAddress: window.call.fullLocalAddress fullLocalAddress: window.call.fullLocalAddress
localAddress: window.call.localAddress localAddress: window.call.localAddress
onChatRoomModelChanged: if(chatRoomModel) chatRoomModel.initEntries()
} }
Connections { Connections {

View file

@ -240,6 +240,7 @@ ColumnLayout {
sipAddresses: _contact ? _contact.vcard.sipAddresses : [ contactEdit.sipAddress ] sipAddresses: _contact ? _contact.vcard.sipAddresses : [ contactEdit.sipAddress ]
function vewConversation(chatRoomModel){ function vewConversation(chatRoomModel){
console.log("Load conversation from contact edit")
window.setView('Conversation', { window.setView('Conversation', {
chatRoomModel:chatRoomModel chatRoomModel:chatRoomModel
}, function(){ }, function(){

View file

@ -204,6 +204,7 @@ ColumnLayout {
Connections{ Connections{
target: lastChatRoom target: lastChatRoom
onStateChanged: if(state === 1) { onStateChanged: if(state === 1) {
console.log("Load conversation from contacts")
window.setView('Conversation', { window.setView('Conversation', {
chatRoomModel: lastChatRoom chatRoomModel: lastChatRoom
}) })

View file

@ -455,7 +455,7 @@ ColumnLayout {
anchors.leftMargin: 50 anchors.leftMargin: 50
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
//anchors.horizontalCenter: parent.horizontalCenter //anchors.horizontalCenter: parent.horizontalCenter
visible: chatArea.tryingToLoadMoreEntries running: chatArea.tryingToLoadMoreEntries
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
@ -527,7 +527,6 @@ ColumnLayout {
id:chatArea id:chatArea
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
proxyModel: ChatRoomProxyModel { proxyModel: ChatRoomProxyModel {
id: chatRoomProxyModel id: chatRoomProxyModel

View file

@ -319,10 +319,12 @@ ApplicationWindow {
onEntrySelected:{ onEntrySelected:{
if( entry ) { if( entry ) {
if( entry.selected){
console.log("Load conversation from entry selected on timeline")
window.setView('Conversation', { window.setView('Conversation', {
chatRoomModel:entry.chatRoomModel chatRoomModel:entry.chatRoomModel
}) })
}
}else{ }else{
window.setView('Home', {}) window.setView('Home', {})
@ -364,7 +366,9 @@ ApplicationWindow {
Connections { Connections {
target: UrlHandlers target: UrlHandlers
onSip: window.setView('Conversation', { onSip: {
console.log("Change conversation from url handler")
window.setView('Conversation', {
peerAddress: sipAddress, peerAddress: sipAddress,
localAddress: AccountSettingsModel.sipAddress, localAddress: AccountSettingsModel.sipAddress,
fullPeerAddress: sipAddress, fullPeerAddress: sipAddress,
@ -372,3 +376,4 @@ ApplicationWindow {
}) })
} }
} }
}