diff --git a/src/callview/qml/callview.qml b/src/callview/qml/callview.qml index af623cc6..8943ff04 100644 --- a/src/callview/qml/callview.qml +++ b/src/callview/qml/callview.qml @@ -1,284 +1,275 @@ /*************************************************************************** * Copyright (C) 2017 by Bluesystems * * Author : Emmanuel Lepage Vallee * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * **************************************************************************/ import QtQuick 2.7 import QtQuick.Layouts 1.0 import net.lvindustries.ringqtquick 1.0 as RingQtQuick import org.kde.ringkde.jamicallview 1.0 as JamiCallView import org.kde.ringkde.jamivideoview 1.0 as JamiVideoView import org.kde.ringkde.jamidialview 1.0 as JamiDialView Item { id: videoDock signal callWithVideo () signal callWithAudio () signal callWithScreen() - height: 480 - width: 640 - // C++ bindings property alias rendererName : videoWidget.rendererName property bool displayPreview : false property string mode : "PREVIEW" property bool previewRunning : false property alias peerRunning : videoWidget.started property QtObject call : null property QtObject renderer : call ? call.renderer : null property bool previewVisible: mode != "PREVIEW" && call && RingSession.previewManager.previewing Connections { target: renderer onDestroyed: { videoWidget.started = false } } // Let the animations finish before Timer { id: toolbarTimer running: false interval: 150 repeat: false onTriggered: { actionToolbar.visible = false videoSource.visible = false controlToolbar.visible = false } } function showToolbars() { actionToolbar.visible = true videoSource.visible = true // This toolbar is only useful when there is video if (videoWidget.started) controlToolbar.visible = true actionToolbar.opacity = 1 videoSource.opacity = 1 controlToolbar.opacity = 1 videoPreview.opacity = 0.8 actionToolbar.anchors.bottomMargin = 0 videoSource.anchors.rightMargin = 0 controlToolbar.anchors.topMargin = 0 } function hideToolbars() { actionToolbar.opacity = 0 videoSource.opacity = 0 controlToolbar.opacity = 0 videoPreview.opacity = 1 videoSource.anchors.rightMargin = -20 actionToolbar.anchors.bottomMargin = -20 controlToolbar.anchors.topMargin = -20 toolbarTimer.running = true } JamiVideoView.VideoWidget { id: videoWidget anchors.fill: parent z: -100 started: false visible: started && !hasFailed call: videoDock.call } JamiVideoView.VideoWidget { id: videoPreview z: -95 started: false visible: previewVisible anchors.right: parent.right anchors.bottom: parent.bottom width: 192 height: 108 } JamiVideoView.VideoControlToolbar { id: controlToolbar anchors.top: parent.top visible: false Behavior on opacity { NumberAnimation {duration: 100} } Behavior on anchors.topMargin { NumberAnimation {duration: 150} } } JamiDialView.ActionToolbar { id: actionToolbar anchors.bottom: parent.bottom visible: false Behavior on opacity { NumberAnimation {duration: 100} } Behavior on anchors.bottomMargin { NumberAnimation {duration: 150} } } JamiCallView.RecordingIcon { anchors.right: videoDock.right anchors.top: controlToolbar.bottom } JamiVideoView.DeviceSetting { id: deviceSettings visible: mode == "PREVIEW" width: parent.width z: 100 - Rectangle { - anchors.fill: parent - color: "black" - opacity: 0.5 - z: -1 - } } JamiVideoView.VideoSource { id: videoSource z: 101 visible: false anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter Behavior on opacity { NumberAnimation {duration: 100} } Behavior on anchors.rightMargin { NumberAnimation {duration: 150} } } // The background JamiCallView.CallBackground { id: placeholderMessage z: -99 anchors.fill: parent bottomMargin: actionToolbar.visible ? actionToolbar.height : 0 } // Hide both toolbars when the mouse isn't moving //TODO keep visible if the mouse if over the toolbars MouseArea { id: mainMouseArea Timer { id: activityTimer interval: 3000 running: true repeat: false onTriggered: { hideToolbars() } } function trackActivity() { if (mode == "PREVIEW") { deviceSettings.visible = true } else if (call) { showToolbars() } activityTimer.restart() } anchors.fill: parent hoverEnabled: true propagateComposedEvents: true onMouseXChanged: trackActivity() onMouseYChanged: trackActivity() } onModeChanged: { if (mode == "PREVIEW") { hideToolbars() videoWidget.rendererName = "preview" } else if (mode == "CONVERSATION") { videoPreview.started = RingSession.previewManager.previewing videoWidget.rendererName = "peer" } placeholderMessage.mode = mode } onCallChanged: { if (call) { actionToolbar.userActionModel = call.userActionModel placeholderMessage.call = call videoSource.call = call controlToolbar.call = call } videoWidget.hasFailed = false mainMouseArea.visible = call != null || mode == "PREVIEW" } Connections { target: RingSession.previewManager onPreviewingChanged: { if (mode == "PREVIEW") videoWidget.started = RingSession.previewManager.previewing videoPreview.started = RingSession.previewManager.previewing } } Connections { target: call } Connections { target: call onVideoStarted: { videoWidget.started = true } onVideoStopped: { videoWidget.started = false } onLiveMediaIssuesChanaged: { // This isn't using properties because the renderer live in their // own thread and QML doesn't support this yet videoWidget.hasFailed = call.hasIssue(RingQtQuick.Call.VIDEO_ACQUISITION_FAILED) } } Connections { target: videoWidget onStartedChanged: { placeholderMessage.visible = (!videoWidget.started) || (videoWidget.hasFailed) } onHasFailedChanged: { placeholderMessage.visible = (!videoWidget.started) || (videoWidget.hasFailed) } } Connections { target: call onStateChanged: { if (call == null || call.lifeCycleState == RingQtQuick.Call.FINISHED) { call = null hideToolbars() } } } } diff --git a/src/canvasindicators/qml/newcall.qml b/src/canvasindicators/qml/newcall.qml index 9b0ba68f..04bbd62c 100644 --- a/src/canvasindicators/qml/newcall.qml +++ b/src/canvasindicators/qml/newcall.qml @@ -1,78 +1,78 @@ /*************************************************************************** * Copyright (C) 2017 by Bluesystems * * Author : Emmanuel Lepage Vallee * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * **************************************************************************/ import QtQuick 2.7 import QtQuick.Layouts 1.0 ColumnLayout { width: 300 spacing: 10 Component { id: button Rectangle { id: bg height: 30 color: "#222222" border.color: "#333333" border.width: 1 radius: 5 - visible: currentIndividual + visible: mainPage.currentIndividual Text { text: label anchors.centerIn: parent color: "white" } MouseArea { anchors.fill: parent hoverEnabled: true onContainsMouseChanged: { bg.color = containsMouse ? "#444444" : "#222222" } onClicked: { callWithAudio() } } Behavior on color { ColorAnimation {duration: 100} } } } Loader { width: 300 Layout.fillWidth: true property string label: "Start a video call" visible: availabilityTracker.canVideoCall sourceComponent: button } Loader { width: 300 Layout.fillWidth: true property string label: "Start an audio call" visible: availabilityTracker.canCall sourceComponent: button } Loader { width: 300 Layout.fillWidth: true property string label: "Start screen sharing" visible: availabilityTracker.canVideoCall sourceComponent: button } } diff --git a/src/jamivideoview/qml/devicesetting.qml b/src/jamivideoview/qml/devicesetting.qml index 5eaecdcd..71ea7a8e 100644 --- a/src/jamivideoview/qml/devicesetting.qml +++ b/src/jamivideoview/qml/devicesetting.qml @@ -1,75 +1,79 @@ /*************************************************************************** * Copyright (C) 2017 by Bluesystems * * Author : Emmanuel Lepage Vallee * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * **************************************************************************/ import QtQuick 2.7 import QtQuick.Layouts 1.0 import org.kde.playground.kquickitemviews 1.0 as KQuickItemViews import net.lvindustries.ringqtquick 1.0 as RingQtQuick +import net.lvindustries.ringqtquick.video 1.0 as RingQtQuickVideo GridLayout { property alias deviceSelectionModel : device.selectionModel property alias channelSelectionModel : channel.selectionModel property alias resolutionSelectionModel: resolution.selectionModel property alias rateSelectionModel : rate.selectionModel columns: 2 Text { color: "white" text: i18n("Device") } KQuickItemViews.ComboBoxView { id: device Layout.fillWidth: true selectionModel: RingSession.deviceModel.configurationProxy.deviceSelectionModel } Text { color: "white" text: i18n("Channel") } KQuickItemViews.ComboBoxView { id: channel selectionModel: RingSession.deviceModel.configurationProxy.channelSelectionModel Layout.fillWidth: true + Component.onCompleted: { + console.log("\n\n\nCOMPLETE!", RingSession.deviceModel.configurationProxy.channelSelectionModel) + } } Text { color: "white" text: i18n("Resolution") } KQuickItemViews.ComboBoxView { id: resolution selectionModel: RingSession.deviceModel.configurationProxy.resolutionSelectionModel Layout.fillWidth: true } Text { color: "white" text: i18n("Frame rate") } KQuickItemViews.ComboBoxView { id: rate selectionModel: RingSession.deviceModel.configurationProxy.rateSelectionModel Layout.fillWidth: true } //I got no idea why. If there is no extra row, the column width is wrong Item { Layout.fillHeight: true } } diff --git a/views/basic/basic.qrc b/views/basic/basic.qrc index 06cb26d1..cc2ac7bb 100644 --- a/views/basic/basic.qrc +++ b/views/basic/basic.qrc @@ -1,18 +1,19 @@ qml/actioncollection.qml qml/basic.qml qml/chatpage.qml qml/contacts.qml qml/desktopheader.qml qml/detailpage.qml qml/detail.qml qml/formpage.qml qml/form.qml qml/listpage.qml qml/list.qml qml/globaldrawer.qml qml/sidebar.qml qml/actionswitch.qml + qml/callpage.qml diff --git a/views/basic/basicviewplugin.cpp b/views/basic/basicviewplugin.cpp index cb613421..784c5a37 100644 --- a/views/basic/basicviewplugin.cpp +++ b/views/basic/basicviewplugin.cpp @@ -1,47 +1,48 @@ /*************************************************************************** * Copyright (C) 2017 by Bluesystems * * Author : Emmanuel Lepage Vallee * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * **************************************************************************/ #include "basicviewplugin.h" #include #include #include void BasicView::registerTypes(const char *uri) { qmlRegisterType(QStringLiteral("qrc:/basicview/qml/actioncollection.qml"), uri, 1, 0, "ActionCollection"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/chatpage.qml"), uri, 1, 0, "ChatPage"); + qmlRegisterType(QStringLiteral("qrc:/basicview/qml/callpage.qml"), uri, 1, 0, "CallPage"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/contacts.qml"), uri, 1, 0, "Contacts"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/desktopheader.qml"), uri, 1, 0, "DesktopHeader"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/detailpage.qml"), uri, 1, 0, "DetailPage"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/detail.qml"), uri, 1, 0, "Detail"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/formpage.qml"), uri, 1, 0, "FormPage"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/form.qml"), uri, 1, 0, "Form"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/listpage.qml"), uri, 1, 0, "ListPage"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/list.qml"), uri, 1, 0, "List"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/globaldrawer.qml"), uri, 1, 0, "GlobalDrawer"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/sidebar.qml"), uri, 1, 0, "SideBar"); qmlRegisterType(QStringLiteral("qrc:/basicview/qml/actionswitch.qml"), uri, 1, 0, "ActionSwitch"); } void BasicView::initializeEngine(QQmlEngine* engine, const char* uri) { Q_UNUSED(engine) Q_UNUSED(uri) } diff --git a/views/basic/qml/actioncollection.qml b/views/basic/qml/actioncollection.qml index f2014323..9316456d 100644 --- a/views/basic/qml/actioncollection.qml +++ b/views/basic/qml/actioncollection.qml @@ -1,112 +1,116 @@ /* * Copyright 2018 Fabian Riethmayer * Copyright 2019 Emmanuel Lepage * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.0 import org.kde.kirigami 2.4 as Kirigami import QtQuick.Controls.Material 2.3 QtObject { readonly property Kirigami.Action mailAction: Kirigami.Action { iconName: "mail-message" text: i18n("Write mail") } readonly property Kirigami.Action callAction: Kirigami.Action { iconName: "call-start" text: i18n("Make call") + onTriggered: { + pageStack.push(callpage) + callpage.visible = true + } } readonly property Kirigami.Action chatAction: Kirigami.Action { iconName: "kmouth-phrase-new" text: i18n("Write SMS") } readonly property Kirigami.Action bookmarkAction: Kirigami.Action { iconName: "favorite" text: i18n("Select as favorite") } readonly property Kirigami.Action shareAction: Kirigami.Action { iconName: "document-share" text: i18n("Share") } readonly property Kirigami.Action editAction: Kirigami.Action { iconName: "document-edit" text: i18n("Edit") } readonly property Kirigami.Action photoAction: Kirigami.Action { iconName: "edit-image-face-add" text: i18n("Choose photo") } readonly property Kirigami.Action banAction: Kirigami.Action { iconName: "im-kick-user" text: i18n("Block number") } readonly property Kirigami.Action deleteAction: Kirigami.Action { iconName: "delete" text: i18n("Delete contact") } readonly property Kirigami.Action clearAction: Kirigami.Action { iconName: "edit-clear-history" text: i18n("Delete history") } readonly property Kirigami.Action newContactAction: Kirigami.Action { iconName: "contact-new" text: "Create contact" } readonly property Kirigami.Action darkMode: Kirigami.Action { iconName: "mail-message" text: i18n("Dark mode") onTriggered: { console.log("Enable dark mode", Material.Dark, Material.Blue) root.Material.theme = Material.Dark root.Material.accent = Material.Blue } } readonly property Kirigami.Action lightMode: Kirigami.Action { iconName: "mail-message" text: i18n("Light mode") onTriggered: { console.log("Enable light mode", Material.Light, Material.Purple) root.Material.theme = Material.Light root.Material.accent = Material.Purple } } readonly property Kirigami.Action settings: Kirigami.Action { text: i18n("Settings") Kirigami.Action { text: i18n("Settings") } Kirigami.Action { text: i18n("Settings") } } } diff --git a/views/basic/qml/basic.qml b/views/basic/qml/basic.qml index a39cc8c9..e0f11d9d 100644 --- a/views/basic/qml/basic.qml +++ b/views/basic/qml/basic.qml @@ -1,159 +1,164 @@ /* * Copyright 2018 Fabian Riethmayer * Copyright 2019 Emmanuel Lepage * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.6 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.2 import org.kde.kirigami 2.6 as Kirigami import net.lvindustries.ringqtquick 1.0 as RingQtQuick import org.kde.ringkde.basicview 1.0 as BasicView import org.kde.ringkde.jamicontactview 1.0 as JamiContactView import org.kde.ringkde.jamiwizard 1.0 as JamiWizard import org.kde.ringkde.jamikdeintegration 1.0 as JamiKDEIntegration import QtQuick.Controls.Material 2.3 Kirigami.ApplicationWindow { width: 320 height: 600 id: root // Localization is currently broken with the Material theme function i18n(t) {return t;} RingQtQuick.SharedModelLocker { id: mainPage onChanged: { chat.boo.timelineModel = timelineModel if (!currentIndividual) return; var idx = RingSession.peersTimelineModel.individualIndex(currentIndividual) list.currentIndex = idx.row } } BasicView.ActionCollection { id: actionCollection } BasicView.Contacts { id : mydata Component.onCompleted: { chat.model = mydata.get(3) } } pageStack.initialPage: [list, chat] pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.ToolBar pageStack.globalToolBar.preferredHeight: Kirigami.Units.gridUnit * 3 pageStack.defaultColumnWidth: root.width < 320 ? root.width : 320 BasicView.ListPage { id: list model: RingSession.peersTimelineModel } BasicView.ChatPage { id: chat } + BasicView.CallPage { + id: callpage + visible: false + } + contextDrawer: Kirigami.ContextDrawer { id: contextDrawer } globalDrawer: BasicView.GlobalDrawer { id: globalDrawer } JamiKDEIntegration.WindowEvent { id: events onRequestsConfigureAccounts: { var component = Qt.createComponent("qrc:/account/qml/accountdialog.qml") if (component.status == Component.Ready) { var window = component.createObject(applicationWindow().contentItem) window.open() } else console.log("ERROR", component.status, component.errorString()) } onRequestsHideWindow: { hide() } onRequestsWizard: { globalDrawer.drawerOpen = false wizardLoader.visible = true wizardLoader.active = true } } /** * Display the wizard when all accounts are deleted. */ JamiWizard.Policies { id: wizardPolicies } Loader { id: wizardLoader active: false anchors.fill: parent z: 999999 onActiveChanged: { if ( list.displayWelcome && !active) list.search() } sourceComponent: JamiWizard.Wizard { anchors.fill: parent z: 999999 onVisibleChanged: { if (!visible) { wizardLoader.visible = false wizardLoader.active = false } } onWizardFinished: { wizardLoader.active = false list.search() } } } Timer { interval: 0 running: true repeat: false onTriggered: { if (wizardPolicies.displayWizard) wizardLoader.active = true else if (list.displayWelcome) list.search() } } } diff --git a/views/basic/qml/callpage.qml b/views/basic/qml/callpage.qml new file mode 100644 index 00000000..0cd49afb --- /dev/null +++ b/views/basic/qml/callpage.qml @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Emmanuel Lepage + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 3, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import QtQuick 2.2 +import QtQuick.Layouts 1.4 +import QtQuick.Controls 2.2 as Controls +import org.kde.kirigami 2.6 as Kirigami +import org.kde.ringkde.basicview 1.0 as BasicView +import org.kde.ringkde.jamichatview 1.0 as JamiChatView +import org.kde.ringkde.jamicallview 1.0 as JamiCallView + +Kirigami.Page { + spacing: 0 + leftPadding: 0 + rightPadding: 0 + topPadding: 0 + bottomPadding: 0 + padding: 0 + Kirigami.Theme.colorSet: Kirigami.Theme.View + + JamiCallView.CallView { + anchors.fill: parent + } +} diff --git a/views/basic/qml/chatpage.qml b/views/basic/qml/chatpage.qml index 6f487891..a5517340 100644 --- a/views/basic/qml/chatpage.qml +++ b/views/basic/qml/chatpage.qml @@ -1,130 +1,129 @@ /* * Copyright 2018 Fabian Riethmayer * Copyright 2019 Emmanuel Lepage * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.2 import QtQuick.Layouts 1.4 import QtQuick.Controls 2.2 as Controls import org.kde.kirigami 2.6 as Kirigami import org.kde.ringkde.basicview 1.0 as BasicView import org.kde.ringkde.jamichatview 1.0 as JamiChatView Kirigami.Page { property var model; property var currentIndividual: null property var boo: chatView property alias showContactDetails: detail.active property alias editContact: form.active property bool _fits: false Kirigami.Theme.colorSet: Kirigami.Theme.View id: chatPage spacing: 0 leftPadding: 0 rightPadding: 0 topPadding: 0 bottomPadding: 0 padding: 0 - title: "Susan Hoffman" titleDelegate: BasicView.DesktopHeader { id: dheader visible: fits Component.onCompleted: _fits = fits onFitsChanged: _fits = fits } header: Controls.ToolBar { visible: (!_fits) height: visible ? Kirigami.Units.gridUnit * 2.5 : 0 Layout.fillWidth: true Layout.preferredHeight: visible ? Kirigami.Units.gridUnit * 5 : 0 Layout.margins: 0 BasicView.DesktopHeader { anchors.fill: parent } } RowLayout { anchors.fill: parent spacing: 0 JamiChatView.ChatPage { id: chatView Layout.fillWidth: true Layout.fillHeight: true Layout.bottomMargin: 0 currentIndividual: mainPage.currentIndividual timelineModel: mainPage.timelineModel } Loader { id: sidebarLoader // 750 is the 600pt maximum width of the chat + width of the sidebar active: pageStack.wideMode && (!Kirigami.Settings.isMobile) && parent.width > 750 Layout.preferredWidth: active ? 250 : 0 Layout.fillHeight: true sourceComponent: BasicView.SideBar { anchors.fill: sidebarLoader } } } Loader { active: false id: detail sourceComponent: BasicView.DetailPage { model: chatPage.model onSheetOpenChanged: detail.active = sheetOpen Component.onCompleted: sheetOpen = true } } Loader { active: false id: form sourceComponent: BasicView.DetailPage { model: chatPage.model onSheetOpenChanged: form.active = sheetOpen Component.onCompleted: {sheetOpen = true} } } actions { left : actionCollection.mailAction main : actionCollection.callAction right: actionCollection.chatAction } contextualActions: [ actionCollection.bookmarkAction, actionCollection.shareAction, actionCollection.editAction, actionCollection.photoAction, actionCollection.banAction, actionCollection.deleteAction, actionCollection.learAction, ] }