mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-04-21 21:52:03 +02:00
callview: use dynamic loading for call views
This commit replaces a StackLayout with a Loader allowing us to load initial and ongoing call views dynamically based on the current conversation's call state. This may fix several issues related to conversation loading including a possible uncaught binding loop based on observing CurrentConversation.id changes. - small header clean up Change-Id: Idfc723d8b39f19aafb026c19f26590910b5c26cd
This commit is contained in:
parent
6105f4f7ce
commit
8a149b6c4f
9 changed files with 78 additions and 81 deletions
|
@ -362,38 +362,34 @@ CallOverlayModel::clearControls()
|
|||
}
|
||||
|
||||
void
|
||||
CallOverlayModel::registerFilter(QObject* object, QQuickItem* item)
|
||||
CallOverlayModel::setEventFilterActive(QObject* object, QQuickItem* item, bool isActive)
|
||||
{
|
||||
QQuickWindow* window = qobject_cast<QQuickWindow*>(object);
|
||||
if (!window || !item) {
|
||||
C_WARN << "Attempting to register an invalid object or item" << object << item;
|
||||
C_WARN << "Attempting to" << (isActive ? "register" : "unregister")
|
||||
<< "an invalid object or item" << window << item;
|
||||
return;
|
||||
}
|
||||
if (isActive) {
|
||||
if (watchedItems_.contains(item)) {
|
||||
C_DBG << "Item already registered" << item;
|
||||
}
|
||||
} else {
|
||||
watchedItems_.push_back(item);
|
||||
if (watchedItems_.size() == 1) {
|
||||
window->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CallOverlayModel::unregisterFilter(QObject* object, QQuickItem* item)
|
||||
{
|
||||
QQuickWindow* window = qobject_cast<QQuickWindow*>(object);
|
||||
if (!window || !item) {
|
||||
C_WARN << "Attempting to unregister an invalid object or item" << object << item;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!watchedItems_.contains(item)) {
|
||||
C_DBG << "Item not registered" << item;
|
||||
}
|
||||
} else {
|
||||
watchedItems_.removeOne(item);
|
||||
if (watchedItems_.size() == 0) {
|
||||
window->removeEventFilter(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CallOverlayModel::eventFilter(QObject* object, QEvent* event)
|
||||
|
|
|
@ -137,8 +137,7 @@ public:
|
|||
Q_INVOKABLE QVariant overflowHiddenModel();
|
||||
Q_INVOKABLE QVariant pendingConferenceesModel();
|
||||
|
||||
Q_INVOKABLE void registerFilter(QObject* object, QQuickItem* item);
|
||||
Q_INVOKABLE void unregisterFilter(QObject* object, QQuickItem* item);
|
||||
Q_INVOKABLE void setEventFilterActive(QObject* object, QQuickItem* item, bool isActive);
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
|
|
@ -28,6 +28,8 @@ VideoView {
|
|||
crop: true
|
||||
visible: isRendering && visibilityCondition
|
||||
|
||||
Component.onDestruction: VideoDevices.stopDevice(rendererId);
|
||||
|
||||
function startWithId(id, force = false) {
|
||||
if (id !== undefined && id.length === 0) {
|
||||
stop();
|
||||
|
|
|
@ -48,10 +48,10 @@ ListSelectionView {
|
|||
leftPaneItem: viewCoordinator.getView("SidePanel", true)
|
||||
|
||||
rightPaneItem: StackLayout {
|
||||
id: conversationStackLayout
|
||||
objectName: "ConversationLayout"
|
||||
|
||||
currentIndex: !CurrentConversation.hasCall ? 0 : 1
|
||||
onCurrentIndexChanged: chatView.parent = currentIndex === 1 ? callStackView.chatViewContainer : chatViewContainer
|
||||
currentIndex: CurrentConversation.hasCall ? 1 : 0
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
|
@ -64,24 +64,28 @@ ListSelectionView {
|
|||
ChatView {
|
||||
id: chatView
|
||||
anchors.fill: parent
|
||||
inCallView: parent == callStackView.chatViewContainer
|
||||
|
||||
// Parent the chat view to the call stack view when in call.
|
||||
parent: callStackView.chatViewContainer ? callStackView.chatViewContainer : chatViewContainer
|
||||
inCallView: parent === callStackView.chatViewContainer
|
||||
|
||||
readonly property string currentConvId: CurrentConversation.id
|
||||
onCurrentConvIdChanged: {
|
||||
if (!CurrentConversation.hasCall) {
|
||||
Qt.callLater(focusChatView);
|
||||
} else {
|
||||
dismiss();
|
||||
Qt.callLater(function() {
|
||||
if (CurrentConversation.hasCall) {
|
||||
callStackView.contentView.forceActiveFocus();
|
||||
} else {
|
||||
focusChatView();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onDismiss: {
|
||||
if (!inCallView) {
|
||||
viewNode.dismiss();
|
||||
} else {
|
||||
if (inCallView) {
|
||||
callStackView.chatViewContainer.visible = false;
|
||||
callStackView.contentView.forceActiveFocus();
|
||||
} else {
|
||||
viewNode.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,11 @@ import "../../commoncomponents"
|
|||
|
||||
Item {
|
||||
id: root
|
||||
property alias chatViewContainer: ongoingCallPage.chatViewContainer
|
||||
property var chatViewContainer: {
|
||||
if (callStackMainView.item instanceof OngoingCallPage)
|
||||
return callStackMainView.item.chatViewContainer;
|
||||
return undefined;
|
||||
}
|
||||
property alias contentView: callStackMainView
|
||||
|
||||
property var sipKeys: ["1", "2", "3", "A", "4", "5", "6", "B", "7", "8", "9", "C", "*", "0", "#", "D"]
|
||||
|
@ -61,44 +65,49 @@ Item {
|
|||
// TODO: this should all be done by listening to
|
||||
// parent visibility change or parent `Component.onDestruction`
|
||||
function needToCloseInCallConversationAndPotentialWindow() {
|
||||
ongoingCallPage.closeInCallConversation();
|
||||
ongoingCallPage.closeContextMenuAndRelatedWindows();
|
||||
if (callStackMainView.item instanceof OngoingCallPage) {
|
||||
callStackMainView.item.closeInCallConversation();
|
||||
callStackMainView.item.closeContextMenuAndRelatedWindows();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleFullScreen() {
|
||||
if (!layoutManager.isCallFullscreen) {
|
||||
layoutManager.pushFullScreenItem(callStackMainView.currentItem, callStackMainView, null, null);
|
||||
layoutManager.pushFullScreenItem(callStackMainView.item, callStackMainView, null, null);
|
||||
} else {
|
||||
layoutManager.removeFullScreenItem(callStackMainView.currentItem);
|
||||
layoutManager.removeFullScreenItem(callStackMainView.item);
|
||||
}
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
Loader {
|
||||
id: callStackMainView
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
property Item currentItem: itemAt(currentIndex)
|
||||
|
||||
currentIndex: {
|
||||
sourceComponent: {
|
||||
switch (CurrentCall.status) {
|
||||
case Call.Status.IN_PROGRESS:
|
||||
case Call.Status.CONNECTED:
|
||||
case Call.Status.PAUSED:
|
||||
return 1;
|
||||
return ongoingCallPageComponent;
|
||||
case Call.Status.SEARCHING:
|
||||
case Call.Status.CONNECTING:
|
||||
case Call.Status.INCOMING_RINGING:
|
||||
case Call.Status.OUTGOING_RINGING:
|
||||
return initialCallPageComponent;
|
||||
default:
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
InitialCallPage {
|
||||
Component {
|
||||
id: initialCallPageComponent
|
||||
InitialCallPage {}
|
||||
}
|
||||
OngoingCallPage {
|
||||
id: ongoingCallPage
|
||||
|
||||
Component {
|
||||
id: ongoingCallPageComponent
|
||||
OngoingCallPage {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,17 +61,9 @@ Item {
|
|||
|
||||
opacity: 0
|
||||
|
||||
// (un)subscribe to an app-wide mouse move event trap filtered
|
||||
// for the overlay's geometry
|
||||
function setupFilter() {
|
||||
if (visible) {
|
||||
CallOverlayModel.registerFilter(appWindow, this);
|
||||
} else {
|
||||
CallOverlayModel.unregisterFilter(appWindow, this);
|
||||
}
|
||||
}
|
||||
Component.onCompleted: setupFilter()
|
||||
onVisibleChanged: setupFilter()
|
||||
Component.onCompleted: CallOverlayModel.setEventFilterActive(appWindow, this, true)
|
||||
Component.onDestruction: CallOverlayModel.setEventFilterActive(appWindow, this, false)
|
||||
onVisibleChanged: CallOverlayModel.setEventFilterActive(appWindow, this, visible)
|
||||
|
||||
Connections {
|
||||
target: CallOverlayModel
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include "videodevices.h"
|
||||
|
||||
#include "api/devicemodel.h"
|
||||
#include "global.h"
|
||||
|
||||
VideoInputDeviceModel::VideoInputDeviceModel(LRCInstance* lrcInstance,
|
||||
VideoDevices* videoDeviceInstance)
|
||||
|
@ -260,11 +260,10 @@ VideoDevices::stopDevice(const QString& id)
|
|||
return;
|
||||
}
|
||||
|
||||
qInfo() << "Stopping device" << id;
|
||||
if (lrcInstance_->avModel().stopPreview(id)) {
|
||||
deviceOpen_ = false;
|
||||
} else {
|
||||
qWarning() << "Failed to stop device" << id;
|
||||
C_DBG << "Failed to stop device" << id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "directrenderer.h"
|
||||
#else
|
||||
#include "shmrenderer.h"
|
||||
#include <csignal>
|
||||
#include <thread>
|
||||
#endif
|
||||
#include "callbackshandler.h"
|
||||
#include "dbus/callmanager.h"
|
||||
|
@ -42,11 +44,7 @@
|
|||
|
||||
#include <algorithm> // std::sort
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include <iomanip> // for std::put_time
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
|
@ -328,7 +326,7 @@ void
|
|||
AVModel::setDeviceSettings(video::Settings& settings)
|
||||
{
|
||||
MapStringString newSettings;
|
||||
auto rate = QString::number(settings.rate, 'f', 7);
|
||||
auto rate = QString::number(static_cast<double>(settings.rate), 'f', 7);
|
||||
rate = rate.left(rate.length() - 1);
|
||||
newSettings["channel"] = settings.channel;
|
||||
newSettings["name"] = settings.name;
|
||||
|
@ -357,7 +355,7 @@ AVModel::getDeviceIdFromName(const QString& deviceName) const
|
|||
return settings.name == deviceName;
|
||||
});
|
||||
if (iter == devices.end()) {
|
||||
qWarning() << "Couldn't find device: " << deviceName;
|
||||
LC_WARN << "Couldn't find device: " << deviceName;
|
||||
return {};
|
||||
}
|
||||
return *iter;
|
||||
|
@ -491,7 +489,7 @@ void
|
|||
AVModel::stopLocalRecorder(const QString& path) const
|
||||
{
|
||||
if (path.isEmpty()) {
|
||||
qWarning("stopLocalRecorder: can't stop non existing recording");
|
||||
LC_WARN << "stopLocalRecorder: can't stop non existing recording";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -664,7 +662,7 @@ AVModel::getListWindows() const
|
|||
});
|
||||
|
||||
if (xcb_connection_has_error(c.get())) {
|
||||
qDebug() << "xcb connection has error";
|
||||
LC_DBG << "xcb connection has error";
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -690,7 +688,7 @@ AVModel::getListWindows() const
|
|||
propertyPtr replyPropList(xcb_get_property_reply(c.get(), propCookieList, &e),
|
||||
[](auto* ptr) { free(ptr); });
|
||||
if (e) {
|
||||
qDebug() << "Error: " << e->error_code;
|
||||
LC_DBG << "Error: " << e->error_code;
|
||||
free(e);
|
||||
}
|
||||
if (replyPropList.get()) {
|
||||
|
@ -710,7 +708,7 @@ AVModel::getListWindows() const
|
|||
free(ptr);
|
||||
}};
|
||||
if (e) {
|
||||
qDebug() << "Error: " << e->error_code;
|
||||
LC_DBG << "Error: " << e->error_code;
|
||||
free(e);
|
||||
}
|
||||
if (replyProp.get()) {
|
||||
|
@ -987,7 +985,7 @@ AVModelPimpl::getDevice(int type) const
|
|||
if (deviceIdx < devices.size())
|
||||
result = devices.at(deviceIdx);
|
||||
} catch (std::bad_alloc& ba) {
|
||||
qWarning() << "bad_alloc caught: " << ba.what();
|
||||
LC_WARN << "bad_alloc caught: " << ba.what();
|
||||
return "";
|
||||
}
|
||||
return result;
|
||||
|
@ -1060,7 +1058,7 @@ AVModelPimpl::removeRenderer(const QString& id)
|
|||
QWriteLocker lk(&renderersMutex_);
|
||||
auto it = renderers_.find(id);
|
||||
if (it == renderers_.end()) {
|
||||
qWarning() << "Cannot remove renderer. " << id << "not found";
|
||||
LC_DBG << "Cannot remove renderer. " << id << " not found";
|
||||
return {};
|
||||
}
|
||||
auto removed = std::move(it->second);
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
***************************************************************************/
|
||||
#include "api/lrc.h"
|
||||
|
||||
#include <locale>
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue