enlarge video size if single file sent
wait for chat messages model to be reset before changing chat (fix #LINQT-2011)
This commit is contained in:
parent
924224abc5
commit
8a2e842cd7
7 changed files with 151 additions and 27 deletions
|
|
@ -81,31 +81,53 @@ void EventLogList::connectItem(const QSharedPointer<EventLogCore> &item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventLogList::setIsUpdating(bool updating) {
|
||||||
|
if (mIsUpdating != updating) {
|
||||||
|
mIsUpdating = updating;
|
||||||
|
emit isUpdatingChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EventLogList::setChatCore(QSharedPointer<ChatCore> core) {
|
void EventLogList::setChatCore(QSharedPointer<ChatCore> core) {
|
||||||
if (mChatCore != core) {
|
auto updateChatCore = [this](QSharedPointer<ChatCore> core) {
|
||||||
if (mChatCore) {
|
if (mChatCore != core) {
|
||||||
disconnect(mChatCore.get(), &ChatCore::eventsInserted, this, nullptr);
|
if (mChatCore) {
|
||||||
|
disconnect(mChatCore.get(), &ChatCore::eventsInserted, this, nullptr);
|
||||||
|
disconnect(mChatCore.get(), &ChatCore::eventListCleared, this, nullptr);
|
||||||
|
}
|
||||||
|
mChatCore = core;
|
||||||
|
if (mChatCore) {
|
||||||
|
connect(mChatCore.get(), &ChatCore::eventListCleared, this, [this] { resetData(); });
|
||||||
|
connect(mChatCore.get(), &ChatCore::eventsInserted, this,
|
||||||
|
[this](QList<QSharedPointer<EventLogCore>> list) {
|
||||||
|
auto eventsList = getSharedList<EventLogCore>();
|
||||||
|
for (auto &event : list) {
|
||||||
|
auto it = std::find_if(
|
||||||
|
eventsList.begin(), eventsList.end(),
|
||||||
|
[event](const QSharedPointer<EventLogCore> item) { return item == event; });
|
||||||
|
if (it == eventsList.end()) {
|
||||||
|
connectItem(event);
|
||||||
|
add(event);
|
||||||
|
int index;
|
||||||
|
get(event.get(), &index);
|
||||||
|
emit eventInserted(index, new EventLogGui(event));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
lUpdate();
|
||||||
|
emit chatGuiChanged();
|
||||||
}
|
}
|
||||||
mChatCore = core;
|
};
|
||||||
if (mChatCore) {
|
if (mIsUpdating) {
|
||||||
connect(mChatCore.get(), &ChatCore::eventListCleared, this, [this] { resetData(); });
|
connect(this, &EventLogList::isUpdatingChanged, this, [this, core, updateChatCore] {
|
||||||
connect(mChatCore.get(), &ChatCore::eventsInserted, this, [this](QList<QSharedPointer<EventLogCore>> list) {
|
if (!mIsUpdating) {
|
||||||
auto eventsList = getSharedList<EventLogCore>();
|
updateChatCore(core);
|
||||||
for (auto &event : list) {
|
disconnect(this, &EventLogList::isUpdatingChanged, this, nullptr);
|
||||||
auto it = std::find_if(eventsList.begin(), eventsList.end(),
|
}
|
||||||
[event](const QSharedPointer<EventLogCore> item) { return item == event; });
|
});
|
||||||
if (it == eventsList.end()) {
|
} else {
|
||||||
connectItem(event);
|
updateChatCore(core);
|
||||||
add(event);
|
|
||||||
int index;
|
|
||||||
get(event.get(), &index);
|
|
||||||
emit eventInserted(index, new EventLogGui(event));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
lUpdate();
|
|
||||||
emit chatGuiChanged();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,15 +182,19 @@ void EventLogList::setSelf(QSharedPointer<EventLogList> me) {
|
||||||
|
|
||||||
mCoreModelConnection->makeConnectToCore(&EventLogList::lUpdate, [this]() {
|
mCoreModelConnection->makeConnectToCore(&EventLogList::lUpdate, [this]() {
|
||||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
||||||
|
if (mChatCore) qDebug() << "reset messages model for chat core" << mChatCore << mChatCore->getTitle();
|
||||||
|
setIsUpdating(true);
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
mList.clear();
|
mList.clear();
|
||||||
if (!mChatCore) {
|
if (!mChatCore) {
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
setIsUpdating(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto chatModel = mChatCore->getModel();
|
auto chatModel = mChatCore->getModel();
|
||||||
if (!chatModel) {
|
if (!chatModel) {
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
setIsUpdating(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mCoreModelConnection->invokeToModel([this, chatModel]() {
|
mCoreModelConnection->invokeToModel([this, chatModel]() {
|
||||||
|
|
@ -193,6 +219,7 @@ void EventLogList::setSelf(QSharedPointer<EventLogList> me) {
|
||||||
for (auto i : *events)
|
for (auto i : *events)
|
||||||
mList << i.template objectCast<QObject>();
|
mList << i.template objectCast<QObject>();
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
setIsUpdating(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ public:
|
||||||
void connectItem(const QSharedPointer<EventLogCore> &item);
|
void connectItem(const QSharedPointer<EventLogCore> &item);
|
||||||
void disconnectItem(const QSharedPointer<EventLogCore> &item);
|
void disconnectItem(const QSharedPointer<EventLogCore> &item);
|
||||||
|
|
||||||
|
void setIsUpdating(bool updating);
|
||||||
|
|
||||||
int findFirstUnreadIndex();
|
int findFirstUnreadIndex();
|
||||||
|
|
||||||
void findChatMessageWithFilter(QString filter,
|
void findChatMessageWithFilter(QString filter,
|
||||||
|
|
@ -66,12 +68,14 @@ signals:
|
||||||
void messageWithFilterFound(int index);
|
void messageWithFilterFound(int index);
|
||||||
void listAboutToBeReset();
|
void listAboutToBeReset();
|
||||||
void chatGuiChanged();
|
void chatGuiChanged();
|
||||||
|
void isUpdatingChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString mFilter;
|
QString mFilter;
|
||||||
QSharedPointer<ChatCore> mChatCore;
|
QSharedPointer<ChatCore> mChatCore;
|
||||||
QSharedPointer<SafeConnection<ChatCore, ChatModel>> mChatModelConnection;
|
QSharedPointer<SafeConnection<ChatCore, ChatModel>> mChatModelConnection;
|
||||||
QSharedPointer<SafeConnection<EventLogList, CoreModel>> mCoreModelConnection;
|
QSharedPointer<SafeConnection<EventLogList, CoreModel>> mCoreModelConnection;
|
||||||
|
bool mIsUpdating = false;
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
||||||
view/Control/Display/Chat/FileView.qml
|
view/Control/Display/Chat/FileView.qml
|
||||||
view/Control/Display/Chat/ImageFileView.qml
|
view/Control/Display/Chat/ImageFileView.qml
|
||||||
view/Control/Display/Chat/AnimatedImageFileView.qml
|
view/Control/Display/Chat/AnimatedImageFileView.qml
|
||||||
|
view/Control/Display/Chat/VideoFileView.qml
|
||||||
view/Control/Display/Contact/Avatar.qml
|
view/Control/Display/Contact/Avatar.qml
|
||||||
view/Control/Display/Contact/Contact.qml
|
view/Control/Display/Contact/Contact.qml
|
||||||
view/Control/Display/Contact/Presence.qml
|
view/Control/Display/Contact/Presence.qml
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import QtQuick
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Controls.Basic as Control
|
import QtQuick.Controls.Basic as Control
|
||||||
|
import QtMultimedia
|
||||||
|
|
||||||
import Linphone
|
import Linphone
|
||||||
import UtilsCpp
|
import UtilsCpp
|
||||||
|
|
||||||
|
|
@ -98,12 +100,27 @@ ColumnLayout {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
fillMode: Image.PreserveAspectFit
|
fillMode: Image.PreserveAspectFit
|
||||||
}
|
}
|
||||||
|
VideoFileView {
|
||||||
|
id: singleVideoFile
|
||||||
|
visible: mainItem.filescontentProxy.count === 1 && UtilsCpp.isVideo(contentGui.core.filePath)
|
||||||
|
contentGui: mainItem.filescontentProxy.count === 1
|
||||||
|
? mainItem.filescontentProxy.getChatMessageContentAtIndex(0)
|
||||||
|
: null
|
||||||
|
width: Math.round(285 * DefaultStyle.dp)
|
||||||
|
height: Math.round(285 * DefaultStyle.dp)
|
||||||
|
Layout.preferredWidth: videoOutput.contentRect.width
|
||||||
|
Layout.preferredHeight: videoOutput.contentRect.height
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
fillMode: VideoOutput.PreserveAspectFit
|
||||||
|
}
|
||||||
|
|
||||||
// FILES
|
// FILES
|
||||||
ChatFilesGridLayout {
|
ChatFilesGridLayout {
|
||||||
id: messageFilesList
|
id: messageFilesList
|
||||||
visible: mainItem.filescontentProxy.count > 0
|
visible: mainItem.filescontentProxy.count > 0
|
||||||
&& !singleImageFile.visible
|
&& !singleImageFile.visible
|
||||||
&& !singleAnimatedImageFile.visible
|
&& !singleAnimatedImageFile.visible
|
||||||
|
&& !singleVideoFile.visible
|
||||||
Layout.fillWidth: visible
|
Layout.fillWidth: visible
|
||||||
Layout.fillHeight: visible
|
Layout.fillHeight: visible
|
||||||
maxWidth: Math.round(115*3 * DefaultStyle.dp)
|
maxWidth: Math.round(115*3 * DefaultStyle.dp)
|
||||||
|
|
|
||||||
|
|
@ -93,13 +93,16 @@ ListView {
|
||||||
markIndexAsRead(index)
|
markIndexAsRead(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onModelAboutToBeReset: loading = true
|
onModelAboutToBeReset: {
|
||||||
onModelReset: Qt.callLater(function() {
|
loading = true
|
||||||
|
}
|
||||||
|
onModelReset: {
|
||||||
loading = false
|
loading = false
|
||||||
var index = eventLogProxy.findFirstUnreadIndex()
|
var index = eventLogProxy.findFirstUnreadIndex()
|
||||||
positionViewAtIndex(index, ListView.Beginning)
|
positionViewAtIndex(index, ListView.Beginning)
|
||||||
eventLogProxy.markIndexAsRead(index)
|
eventLogProxy.markIndexAsRead(index)
|
||||||
})
|
}
|
||||||
|
onChatGuiChanged: forceLayout()
|
||||||
onIndexWithFilterFound: (index) => {
|
onIndexWithFilterFound: (index) => {
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
currentIndex = index
|
currentIndex = index
|
||||||
|
|
|
||||||
72
Linphone/view/Control/Display/Chat/VideoFileView.qml
Normal file
72
Linphone/view/Control/Display/Chat/VideoFileView.qml
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls as Control
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtMultimedia
|
||||||
|
|
||||||
|
import Linphone
|
||||||
|
import UtilsCpp
|
||||||
|
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: mainItem
|
||||||
|
color: "transparent"//DefaultStyle.grey_1000
|
||||||
|
property ChatMessageContentGui contentGui
|
||||||
|
property string filePath: contentGui && contentGui.core.filePath
|
||||||
|
property var fillMode: playbackState === MediaPlayer.PlayingState ? VideoOutput.PreserveAspectFit : VideoOutput.PreserveAspectCrop
|
||||||
|
property alias videoOutput: output
|
||||||
|
property string source: mediaPlayer.source
|
||||||
|
MediaPlayer {
|
||||||
|
id: mediaPlayer
|
||||||
|
source: UtilsCpp.isVideo(mainItem.filePath) ? "file:///" + mainItem.filePath : ""
|
||||||
|
position: 100
|
||||||
|
videoOutput: output
|
||||||
|
}
|
||||||
|
VideoOutput {
|
||||||
|
id: output
|
||||||
|
fillMode: mainItem.fillMode
|
||||||
|
endOfStreamPolicy: VideoOutput.KeepLastFrame
|
||||||
|
width: mainItem.width
|
||||||
|
height: mainItem.height
|
||||||
|
Component.onCompleted: {
|
||||||
|
// We need to start the video so the content rect of the
|
||||||
|
// video output is updated
|
||||||
|
mediaPlayer.play()
|
||||||
|
mediaPlayer.pause()
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
z: parent.z + 1
|
||||||
|
property int timeDisplayed: mediaPlayer.playbackState === MediaPlayer.PlayingState ? mediaPlayer.position : mediaPlayer.duration
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.bottomMargin: Math.round(6 * DefaultStyle.dp)
|
||||||
|
anchors.leftMargin: Math.round(6 * DefaultStyle.dp)
|
||||||
|
text: UtilsCpp.formatDuration(timeDisplayed)
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
font {
|
||||||
|
pixelSize: Typography.d1.pixelSize
|
||||||
|
weight: Typography.d1.weight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
propagateComposedEvents: false
|
||||||
|
enabled: mainItem.visible
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: false
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onClicked: (mouse) => {
|
||||||
|
mouse.accepted = true
|
||||||
|
mediaPlayer.playbackState === MediaPlayer.PlayingState ? mediaPlayer.pause() : mediaPlayer.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EffectImage {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: mediaPlayer.playbackState !== MediaPlayer.PlayingState
|
||||||
|
width: Math.round(24 * DefaultStyle.dp)
|
||||||
|
height: Math.round(24 * DefaultStyle.dp)
|
||||||
|
imageSource: AppIcons.playFill
|
||||||
|
colorizationColor: DefaultStyle.main2_0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ MessageInfosLayout {
|
||||||
tabbarModel: chatMessageGui ? chatMessageGui.core.imdnStatusListAsString : []
|
tabbarModel: chatMessageGui ? chatMessageGui.core.imdnStatusListAsString : []
|
||||||
listModel: ImdnStatusProxy {
|
listModel: ImdnStatusProxy {
|
||||||
imdnStatusList: chatMessageGui ? chatMessageGui.core.imdnStatusList : []
|
imdnStatusList: chatMessageGui ? chatMessageGui.core.imdnStatusList : []
|
||||||
filter: chatMessageGui && chatMessageGui.core.imdnStatusAsSingletons[mainItem.tabbar.currentIndex]?.state || ""
|
filter: chatMessageGui && chatMessageGui.core.imdnStatusAsSingletons[mainItem.tabbar.currentIndex]?.state || LinphoneEnums.ChatMessageState.StateIdle
|
||||||
}
|
}
|
||||||
|
|
||||||
listView.delegate: Item {
|
listView.delegate: Item {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue