diff --git a/qml.qrc b/qml.qrc index 68a24f05305bd4e480c38c005c4939ad5efa1a5e..e65945edecf4a9406861886556b0dcac84f3839b 100644 --- a/qml.qrc +++ b/qml.qrc @@ -17,13 +17,9 @@ <file>src/commoncomponents/PushButton.qml</file> <file>src/commoncomponents/JamiFileDialog.qml</file> <file>src/commoncomponents/TintedButton.qml</file> - <file>src/commoncomponents/GeneralMenuItem.qml</file> - <file>src/commoncomponents/GeneralMenuSeparator.qml</file> <file>src/commoncomponents/AccountMigrationDialog.qml</file> <file>src/commoncomponents/MaterialButton.qml</file> <file>src/commoncomponents/ElidedTextLabel.qml</file> - <file>src/commoncomponents/js/contextmenugenerator.js</file> - <file>src/commoncomponents/BaseContextMenu.qml</file> <file>src/commoncomponents/SpinnerButton.qml</file> <file>src/commoncomponents/UsernameLineEdit.qml</file> <file>src/commoncomponents/Scaffold.qml</file> @@ -125,7 +121,6 @@ <file>src/mainview/components/RecordBox.qml</file> <file>src/mainview/components/SipInputPanel.qml</file> <file>src/mainview/components/ParticipantOverlayMenu.qml</file> - <file>src/mainview/js/videodevicecontextmenuitemcreation.js</file> <file>src/mainview/js/selectscreenwindowcreation.js</file> <file>src/mainview/js/screenrubberbandcreation.js</file> <file>src/mainview/js/contactpickercreation.js</file> @@ -145,5 +140,9 @@ <file>src/mainview/components/ParticipantCallInStatusView.qml</file> <file>src/settingsview/components/TroubleshootSettings.qml</file> <file>src/settingsview/components/LogsView.qml</file> + <file>src/commoncomponents/contextmenu/ContextMenuAutoLoader.qml</file> + <file>src/commoncomponents/contextmenu/BaseContextMenu.qml</file> + <file>src/commoncomponents/contextmenu/GeneralMenuItem.qml</file> + <file>src/commoncomponents/contextmenu/GeneralMenuSeparator.qml</file> </qresource> </RCC> diff --git a/src/avadapter.cpp b/src/avadapter.cpp index fb7bfb7306677971599b6aa2230d013f2a58c190..c24a1e5c8239f29983210aa6814f5073486bdd68 100644 --- a/src/avadapter.cpp +++ b/src/avadapter.cpp @@ -46,33 +46,6 @@ AvAdapter::AvAdapter(LRCInstance* instance, QObject* parent) }); } -QVariantMap -AvAdapter::populateVideoDeviceContextMenuItem() -{ - auto activeDevice = lrcInstance_->avModel().getCurrentVideoCaptureDevice(); - - /* - * Create a list of video input devices. - */ - QVariantMap deciveContextMenuNeededInfo; - auto devices = lrcInstance_->avModel().getDevices(); - for (int i = 0; i < devices.size(); i++) { - try { - auto settings = lrcInstance_->avModel().getDeviceSettings(devices[i]); - deciveContextMenuNeededInfo[settings.name] = QVariant(settings.id == activeDevice); - } catch (...) { - qDebug().noquote() << "Error in getting device settings"; - } - } - - /* - * Add size parameter into the map since in qml there is no way to get the size. - */ - deciveContextMenuNeededInfo["size"] = QVariant(deciveContextMenuNeededInfo.size()); - - return deciveContextMenuNeededInfo; -} - void AvAdapter::selectVideoInputDeviceByName(const QString& deviceName) { @@ -242,7 +215,7 @@ AvAdapter::shareScreenArea(unsigned x, unsigned y, unsigned width, unsigned heig } void -AvAdapter::stopSharingScreen() +AvAdapter::stopSharing() { auto callId = getCurrentCallId(); if (!callId.isEmpty()) diff --git a/src/avadapter.h b/src/avadapter.h index 9f169df59b0659fc8b68915334568143f988b807..fc4b699be046d95e755a6d2153dd5c0dae0965b9 100644 --- a/src/avadapter.h +++ b/src/avadapter.h @@ -45,9 +45,6 @@ Q_SIGNALS: protected: void safeInit() override {}; - // Return needed info for populating video device context menu item. - Q_INVOKABLE QVariantMap populateVideoDeviceContextMenuItem(); - // switch preview video input by device name Q_INVOKABLE void selectVideoInputDeviceByName(const QString& deviceName); @@ -72,8 +69,8 @@ protected: // Select screen area to display (from all screens). Q_INVOKABLE void shareScreenArea(unsigned x, unsigned y, unsigned width, unsigned height); - // Stop sharing the screen - Q_INVOKABLE void stopSharingScreen(); + // Stop sharing the screen or file + Q_INVOKABLE void stopSharing(); Q_INVOKABLE void startAudioMeter(bool async); Q_INVOKABLE void stopAudioMeter(bool async); diff --git a/src/commoncomponents/BaseContextMenu.qml b/src/commoncomponents/BaseContextMenu.qml deleted file mode 100644 index 636fc74e2b2ae765ecda7db6a2ef198436d96aa5..0000000000000000000000000000000000000000 --- a/src/commoncomponents/BaseContextMenu.qml +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * - * 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 <https://www.gnu.org/licenses/>. - */ - -import QtQuick 2.14 -import QtQuick.Controls 2.14 -import QtGraphicalEffects 1.14 - -import net.jami.Constants 1.0 - -Menu { - id: root - - property int menuItemsPreferredWidth: 220 - property int menuItemsPreferredHeight: 48 - property int generalMenuSeparatorCount: 0 - property int commonBorderWidth: 1 - font.pointSize: JamiTheme.menuFontSize - - modal: true - Overlay.modal: Rectangle { - color: "transparent" - } - - // TODO: investigate - function openMenu(){ - visible = true - visible = false - visible = true - } - - background: Rectangle { - id: container - - implicitWidth: menuItemsPreferredWidth - implicitHeight: menuItemsPreferredHeight - * (root.count - generalMenuSeparatorCount) - - border.width: commonBorderWidth - border.color: JamiTheme.tabbarBorderColor - color: JamiTheme.backgroundColor - - layer.enabled: true - layer.effect: DropShadow { - z: -1 - horizontalOffset: 3.0 - verticalOffset: 3.0 - radius: 16.0 - samples: 16 - color: JamiTheme.shadowColor - } - } -} diff --git a/src/commoncomponents/LineEditContextMenu.qml b/src/commoncomponents/LineEditContextMenu.qml index c4e0d780afaa956ea21502962975bfc823470601..1a1f6ff747acb4472ca29ce6f3584145ab436779 100644 --- a/src/commoncomponents/LineEditContextMenu.qml +++ b/src/commoncomponents/LineEditContextMenu.qml @@ -24,49 +24,69 @@ import net.jami.Models 1.0 import net.jami.Adapters 1.0 import net.jami.Constants 1.0 -import "js/contextmenugenerator.js" as ContextMenuGenerator +import "contextmenu" -Item { +ContextMenuAutoLoader { id: root - function openMenu(lineEditObj, mouseEvent) { - ContextMenuGenerator.initMenu(Qt.size(150, 25), 2) - - if (lineEditObj.selectedText.length) { - ContextMenuGenerator.addMenuItem(qsTr("Copy"), - "", - function (){ - lineEditObj.copy() - }) - - ContextMenuGenerator.addMenuItem(qsTr("Cut"), - "", - function (){ - lineEditObj.cut() - }) - } + // lineEdit (TextEdit) selection will be lost when menu is opened + property var lineEditObj + property var selectionStart + property var selectionEnd + + property list<GeneralMenuItem> menuItems: [ + GeneralMenuItem { + id: copy + + canTrigger: lineEditObj.selectedText.length + itemName: JamiStrings.copy + onClicked: { + lineEditObj.copy() + } + }, + GeneralMenuItem { + id: cut - ContextMenuGenerator.addMenuItem(qsTr("Paste"), - "", - function (){ - lineEditObj.paste() - }) + canTrigger: lineEditObj.selectedText.length + itemName: JamiStrings.cut - root.height = ContextMenuGenerator.getMenu().height - root.width = ContextMenuGenerator.getMenu().width - ContextMenuGenerator.getMenu().x = mouseEvent.x - ContextMenuGenerator.getMenu().y = mouseEvent.y + onClicked: { + lineEditObj.cut() + } + }, + GeneralMenuItem { + id: paste + + itemName: JamiStrings.paste + onClicked: { + lineEditObj.paste() + } + } + ] - // lineEdit (TextEdit) selection will be lost when menu is opened - var selectionStartTemp = lineEditObj.selectionStart - var selectionEndTemp = lineEditObj.selectionEnd + function openMenuAt(mouseEvent) { + x = mouseEvent.x + y = mouseEvent.y - ContextMenuGenerator.getMenu().open() + selectionStart = lineEditObj.selectionStart + selectionEnd = lineEditObj.selectionEnd - lineEditObj.select(selectionStartTemp, selectionEndTemp) + root.openMenu() + + lineEditObj.select(selectionStart, selectionEnd) } - Component.onCompleted: { - ContextMenuGenerator.createBaseContextMenuObjects(root) + contextMenuItemPreferredHeight: JamiTheme.lineEditContextMenuItemsHeight + contextMenuItemPreferredWidth: JamiTheme.lineEditContextMenuItemsWidth + contextMenuSeparatorPreferredHeight: JamiTheme.lineEditContextMenuSeparatorsHeight + + Connections { + target: root.item + enabled: root.status === Loader.Ready + function onOpened() { + lineEditObj.select(selectionStart, selectionEnd) + } } + + Component.onCompleted: menuItemsToLoad = menuItems } diff --git a/src/commoncomponents/MaterialLineEdit.qml b/src/commoncomponents/MaterialLineEdit.qml index 9a9c4e446829e851ca5aac1d0078e1aaba5724fd..2b482d34533e6cf0a48fa281760336b7272573be 100644 --- a/src/commoncomponents/MaterialLineEdit.qml +++ b/src/commoncomponents/MaterialLineEdit.qml @@ -83,6 +83,8 @@ TextField { LineEditContextMenu { id: lineEditContextMenu + + lineEditObj: root } Image { @@ -142,6 +144,6 @@ TextField { onReleased: { if (event.button == Qt.RightButton) - lineEditContextMenu.openMenu(root, event) + lineEditContextMenu.openMenuAt(event) } } diff --git a/src/commoncomponents/contextmenu/BaseContextMenu.qml b/src/commoncomponents/contextmenu/BaseContextMenu.qml new file mode 100644 index 0000000000000000000000000000000000000000..79c4e5508b6bf76e933655160009e8bfc4ae9763 --- /dev/null +++ b/src/commoncomponents/contextmenu/BaseContextMenu.qml @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * + * 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 <https://www.gnu.org/licenses/>. + */ + +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtGraphicalEffects 1.14 + +import net.jami.Constants 1.0 + +Menu { + id: root + + property int menuPreferredWidth: 0 + property int menuItemsPreferredHeight: 0 + property int menuSeparatorPreferredHeight: 0 + + property GeneralMenuSeparator menuTopBorder: GeneralMenuSeparator { + separatorPreferredWidth: menuPreferredWidth ? + menuPreferredWidth : JamiTheme.menuItemsPreferredWidth + separatorPreferredHeight: menuSeparatorPreferredHeight ? + menuSeparatorPreferredHeight : JamiTheme.menuBorderPreferredHeight + separatorColor: "transparent" + } + + property GeneralMenuSeparator menuBottomBorder: GeneralMenuSeparator { + separatorPreferredWidth: menuPreferredWidth ? + menuPreferredWidth : JamiTheme.menuItemsPreferredWidth + separatorPreferredHeight: menuSeparatorPreferredHeight ? + menuSeparatorPreferredHeight : JamiTheme.menuBorderPreferredHeight + separatorColor: "transparent" + } + + property var generalMenuSeparatorList: [] + + function loadMenuItems(menuItems) { + root.addItem(menuTopBorder) + + for (var i = 0; i < menuItems.length; ++i) { + if (menuItems[i].canTrigger) { + menuItems[i].parentMenu = root + root.addItem(menuItems[i]) + + if (menuPreferredWidth) + menuItems[i].itemPreferredWidth = menuPreferredWidth + if (menuItemsPreferredHeight) + menuItems[i].itemPreferredHeight = menuItemsPreferredHeight + } + if (menuItems[i].addMenuSeparatorAfter) { + // If the QML file to be loaded is a local file, + // you could omit the finishCreation() function + var menuSeparatorComponent = Qt.createComponent( + "GeneralMenuSeparator.qml", + Component.PreferSynchronous, root) + var menuSeparatorComponentObj = menuSeparatorComponent.createObject() + generalMenuSeparatorList.push(menuSeparatorComponentObj) + root.addItem(menuSeparatorComponentObj) + } + } + + root.addItem(menuBottomBorder) + + root.open() + } + + onVisibleChanged: { + if (!visible) + root.close() + } + + modal: true + Overlay.modal: Rectangle { + color: "transparent" + } + font.pointSize: JamiTheme.menuFontSize + + background: Rectangle { + id: container + + implicitWidth: menuPreferredWidth ? menuPreferredWidth : JamiTheme.menuItemsPreferredWidth + + border.width: JamiTheme.menuItemsCommonBorderWidth + border.color: JamiTheme.tabbarBorderColor + color: JamiTheme.backgroundColor + + layer.enabled: true + layer.effect: DropShadow { + z: -1 + horizontalOffset: 3.0 + verticalOffset: 3.0 + radius: 16.0 + samples: 16 + color: JamiTheme.shadowColor + } + } + + Component.onDestruction: { + for (var i = 0; i < generalMenuSeparatorList.length; ++i) { + generalMenuSeparatorList[i].destroy() + } + } +} diff --git a/src/commoncomponents/contextmenu/ContextMenuAutoLoader.qml b/src/commoncomponents/contextmenu/ContextMenuAutoLoader.qml new file mode 100644 index 0000000000000000000000000000000000000000..711842327e5b19cedf9e6b975b57a30d89935898 --- /dev/null +++ b/src/commoncomponents/contextmenu/ContextMenuAutoLoader.qml @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * + * 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 <https://www.gnu.org/licenses/>. + */ + +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtGraphicalEffects 1.14 + +import net.jami.Models 1.0 +import net.jami.Adapters 1.0 +import net.jami.Constants 1.0 + +import "../../commoncomponents" +import "../../commoncomponents/contextmenu" + +Loader { + id: root + + // Cannot have menuItemsToLoad directly assigned as list<GeneralMenuItem> + // https://stackoverflow.com/questions/26733011/how-to-declare-list-property-in-qml + property var menuItemsToLoad + property int contextMenuItemPreferredWidth: 0 + property int contextMenuItemPreferredHeight: 0 + property int contextMenuSeparatorPreferredHeight: 0 + + function openMenu() { + root.active = true + root.sourceComponent = menuComponent + } + + Connections { + target: root.item + enabled: root.status === Loader.Ready + function onClosed() { + root.active = false + } + } + + Component { + id: menuComponent + + BaseContextMenu { + id: contextMenu + + Component.onCompleted: { + contextMenu.menuPreferredWidth = contextMenuItemPreferredWidth + contextMenu.menuItemsPreferredHeight = contextMenuItemPreferredHeight + contextMenu.menuSeparatorPreferredHeight = contextMenuSeparatorPreferredHeight + contextMenu.loadMenuItems(menuItemsToLoad) + } + } + } +} diff --git a/src/commoncomponents/GeneralMenuItem.qml b/src/commoncomponents/contextmenu/GeneralMenuItem.qml similarity index 71% rename from src/commoncomponents/GeneralMenuItem.qml rename to src/commoncomponents/contextmenu/GeneralMenuItem.qml index ac588ae34a2b468b3e48ccc52663bff056cd4fca..173835590f49b4c0977ab6284ecb25c341531c19 100644 --- a/src/commoncomponents/GeneralMenuItem.qml +++ b/src/commoncomponents/contextmenu/GeneralMenuItem.qml @@ -23,6 +23,8 @@ import QtGraphicalEffects 1.14 import net.jami.Constants 1.0 +import "../../commoncomponents" + // General menu item. // Can control top, bottom, left, right border width. // Use onClicked slot to simulate item click event. @@ -31,13 +33,16 @@ MenuItem { id: menuItem property string itemName: "" - property string iconSource: "" + property alias iconSource: contextMenuItemImage.source property string iconColor: "" - property int preferredWidth: 220 - property int preferredHeight: 48 + property bool canTrigger: true + property bool addMenuSeparatorAfter: false + property BaseContextMenu parentMenu - property int leftBorderWidth: 0 - property int rightBorderWidth: 0 + property int itemPreferredWidth: JamiTheme.menuItemsPreferredWidth + property int itemPreferredHeight: JamiTheme.menuItemsPreferredHeight + property int leftBorderWidth: JamiTheme.menuItemsCommonBorderWidth + property int rightBorderWidth: JamiTheme.menuItemsCommonBorderWidth signal clicked @@ -57,29 +62,25 @@ MenuItem { ResponsiveImage { id: contextMenuItemImage - anchors.left: menuItemContentRect.left - anchors.leftMargin: (visible ? 24 : 0) + anchors.left: status === Image.Ready ? menuItemContentRect.left : undefined + anchors.leftMargin: (status === Image.Ready ? 24 : 0) anchors.verticalCenter: menuItemContentRect.verticalCenter - width: (visible ? 24 : 0) - height: (visible ? 24 : 0) - color: iconColor !== ""? iconColor : JamiTheme.textColor + color: iconColor !== "" ? iconColor : JamiTheme.textColor - visible: false + smooth: true opacity: 0.7 } Text { id: contextMenuItemText - anchors.left: contextMenuItemImage.right - anchors.leftMargin: contextMenuItemImage.visible ? 20 : 5 + anchors.left: contextMenuItemImage.status === Image.Ready ? + contextMenuItemImage.right : menuItemContentRect.left + anchors.leftMargin: contextMenuItemImage.status === Image.Ready ? 20 : 10 anchors.verticalCenter: menuItemContentRect.verticalCenter - width: contextMenuItemImage.visible ? - (preferredWidth - contextMenuItemImage.width - 58) : - preferredWidth - 24 - height: 30 + height: itemPreferredHeight text: itemName color: JamiTheme.textColor @@ -89,7 +90,10 @@ MenuItem { verticalAlignment: Text.AlignVCenter } - onReleased: menuItem.clicked() + onReleased: { + menuItem.clicked() + parentMenu.close() + } states: [ State { @@ -103,13 +107,6 @@ MenuItem { ] } - onIconSourceChanged: { - if (iconSource !== "") { - contextMenuItemImage.source = iconSource - contextMenuItemImage.visible = true - } - } - highlighted: true background: Rectangle { @@ -119,8 +116,8 @@ MenuItem { anchors.leftMargin: leftBorderWidth anchors.rightMargin: rightBorderWidth - implicitWidth: preferredWidth - implicitHeight: preferredHeight + implicitWidth: itemPreferredWidth + implicitHeight: itemPreferredHeight border.width: 0 diff --git a/src/commoncomponents/GeneralMenuSeparator.qml b/src/commoncomponents/contextmenu/GeneralMenuSeparator.qml similarity index 83% rename from src/commoncomponents/GeneralMenuSeparator.qml rename to src/commoncomponents/contextmenu/GeneralMenuSeparator.qml index 6ccac22e0840686b8b84c90937aa3c8eb26f76ea..49f0e90f7e821bb49654a4842d041733466b3828 100644 --- a/src/commoncomponents/GeneralMenuSeparator.qml +++ b/src/commoncomponents/contextmenu/GeneralMenuSeparator.qml @@ -24,16 +24,16 @@ import net.jami.Constants 1.0 MenuSeparator { id: menuSeparator - property int preferredWidth: 10 - property int preferredHeight: 1 + property int separatorPreferredWidth: JamiTheme.menuItemsPreferredWidth + property int separatorPreferredHeight: 1 property string separatorColor: JamiTheme.tabbarBorderColor padding: 0 topPadding: 1 bottomPadding: 1 contentItem: Rectangle { - implicitWidth: preferredWidth - implicitHeight: preferredHeight + implicitWidth: separatorPreferredWidth + implicitHeight: separatorPreferredHeight color: separatorColor } } diff --git a/src/commoncomponents/js/contextmenugenerator.js b/src/commoncomponents/js/contextmenugenerator.js deleted file mode 100644 index 4f5848e7572c01f1b3dbc37485de3d026749a3c9..0000000000000000000000000000000000000000 --- a/src/commoncomponents/js/contextmenugenerator.js +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * - * 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 <https://www.gnu.org/licenses/>. - */ - -// Global base context menu, object variable for creation. -var baseContextMenuComponent -var baseContextMenuObject -var menuItemList = [] -var menuDefaultSeparatorHeight = 8 - -function createBaseContextMenuObjects(parent) { - // If already created, return, since object cannot be destroyed. - if (baseContextMenuObject) - return - - baseContextMenuComponent = Qt.createComponent("../BaseContextMenu.qml") - if (baseContextMenuComponent.status === Component.Ready) - finishCreation(parent) - else if (baseContextMenuComponent.status === Component.Error) - console.log("Error loading component:", - baseContextMenuComponent.errorString()) -} - -function finishCreation(parent) { - baseContextMenuObject = baseContextMenuComponent.createObject(parent) - if (baseContextMenuObject === null) { - // Error Handling. - console.log("Error creating object for base context menu") - } - - baseContextMenuObject.closed.connect(function () { - // Remove the menu items when hidden. - for (var i = 0; i < menuItemList.length; i++) { - baseContextMenuObject.removeItem(menuItemList[i]) - } - }) - - baseContextMenuObject.aboutToShow.connect(function () { - // Add default separator at the bottom. - addMenuSeparator(menuDefaultSeparatorHeight, "transparent") - }) -} - -function initMenu(preferedMenuItemSize, defaultSeparatorHeight) { - // Clear any existing items in the menu. - for (var i = 0; i < menuItemList.length; i++) { - baseContextMenuObject.removeItem(menuItemList[i]) - } - - if (preferedMenuItemSize) { - baseContextMenuObject.menuItemsPreferredWidth = preferedMenuItemSize.width - baseContextMenuObject.menuItemsPreferredHeight = preferedMenuItemSize.height - } - - if (defaultSeparatorHeight) - menuDefaultSeparatorHeight = defaultSeparatorHeight -} - -function addMenuSeparator(separatorHeight, separatorColor) { - var menuSeparatorObject - var menuSeparatorComponent = Qt.createComponent( - "../GeneralMenuSeparator.qml") - if (menuSeparatorComponent.status === Component.Ready) { - baseContextMenuObject.generalMenuSeparatorCount++ - menuSeparatorObject = menuSeparatorComponent.createObject( - null, { - "preferredWidth": baseContextMenuObject.menuItemsPreferredWidth, - "preferredHeight": separatorHeight ? separatorHeight : 1 - }) - if (separatorColor) - menuSeparatorObject.separatorColor = separatorColor - } else if (menuSeparatorComponent.status === Component.Error) - console.log("Error loading component:", - menuSeparatorComponent.errorString()) - if (menuSeparatorObject !== null) { - baseContextMenuObject.addItem(menuSeparatorObject) - - menuItemList.push(menuSeparatorObject) - } else { - // Error handling. - console.log("Error creating object") - } -} - -function addMenuItem(itemName, iconSource, onClickedCallback, iconColor) { - if (!baseContextMenuObject.count) { - // Add default separator at the top. - addMenuSeparator(menuDefaultSeparatorHeight, "transparent") - } - - var menuItemObject - var menuItemComponent = Qt.createComponent("../GeneralMenuItem.qml") - if (menuItemComponent.status === Component.Ready) { - menuItemObject = menuItemComponent.createObject( - null, { - "itemName": itemName, - "iconSource": iconSource, - "iconColor": iconColor, - "preferredWidth": baseContextMenuObject.menuItemsPreferredWidth, - "preferredHeight": baseContextMenuObject.menuItemsPreferredHeight, - "leftBorderWidth": baseContextMenuObject.commonBorderWidth, - "rightBorderWidth": baseContextMenuObject.commonBorderWidth - }) - } else if (menuItemComponent.status === Component.Error) - console.log("Error loading component:", menuItemComponent.errorString()) - if (menuItemObject !== null) { - menuItemObject.clicked.connect(function () { - var callback = function () { - onClickedCallback() - baseContextMenuObject.onVisibleChanged.disconnect(callback) - baseContextMenuObject.close() - } - - baseContextMenuObject.onVisibleChanged.connect(callback) - baseContextMenuObject.visible = false - }) - menuItemObject.icon.color = "green" - - baseContextMenuObject.addItem(menuItemObject) - - menuItemList.push(menuItemObject) - } else { - // Error handling. - console.log("Error creating object") - } -} - -function getMenu() { - return baseContextMenuObject -} diff --git a/src/constant/JamiStrings.qml b/src/constant/JamiStrings.qml index 82ffef41feef62e52bc5db8557241d361d899eaa..6e29cec22b1164d58580d2525bf3a6485e63930f 100644 --- a/src/constant/JamiStrings.qml +++ b/src/constant/JamiStrings.qml @@ -199,6 +199,19 @@ Item { property string moreOptions: qsTr("More options") property string mosaic: qsTr("Mosaic") + // LineEditContextMenu + property string copy: qsTr("Copy") + property string cut: qsTr("Cut") + property string paste: qsTr("Paste") + + // ConversationContextMenu + property string startVideoCall: qsTr("Start video call") + property string startAudioCall: qsTr("Start audio call") + property string clearConversation: qsTr("Clear conversation") + property string removeContact: qsTr("Remove contact") + property string blockContact: qsTr("Block contact") + property string contactDetails: qsTr("Contact details") + // CallViewContextMenu property string hold: qsTr("Hold") property string sipInputPanel: qsTr("Sip input panel") @@ -208,7 +221,7 @@ Item { property string exitFullScreen: qsTr("Exit full screen") property string fullScreen: qsTr("Full screen") property string shareScreen: qsTr("Share screen") - property string stopSharingScreen: qsTr("Stop sharing screen") + property string stopSharing: qsTr("Stop sharing screen or file") property string shareScreenArea: qsTr("Share screen area") property string shareFile: qsTr("Share file") property string viewPlugin: qsTr("View plugin") diff --git a/src/constant/JamiTheme.qml b/src/constant/JamiTheme.qml index 536c8b50500222834314f054c666cd0cf71b585a..78d5f825515e21c584ccb310fc9919194abc1515 100644 --- a/src/constant/JamiTheme.qml +++ b/src/constant/JamiTheme.qml @@ -34,6 +34,7 @@ Item { // General property color blackColor: "#000000" + property color redColor: "red" property color whiteColor: "#ffffff" property color darkGreyColor: "#272727" property color darkGreyColorOpacity: "#be272727" // 77% @@ -214,6 +215,11 @@ Item { property int mosaicButtonPreferredWidth: 70 property int mosaicButtonMaxWidth: 100 + property int menuItemsPreferredWidth: 220 + property int menuItemsPreferredHeight: 48 + property int menuItemsCommonBorderWidth: 1 + property int menuBorderPreferredHeight: 8 + property real maximumWidthSettingsView: 600 property real settingsHeaderpreferredHeight: 64 property real preferredFieldWidth: 256 @@ -225,6 +231,10 @@ Item { property real pluginHandlersPopupViewHeight: 200 property real pluginHandlersPopupViewDelegateHeight: 50 + property real lineEditContextMenuItemsHeight: 15 + property real lineEditContextMenuItemsWidth: 100 + property real lineEditContextMenuSeparatorsHeight: 2 + // main application spec property real mainViewMinWidth: 300 property real mainViewMinHeight: 400 diff --git a/src/mainview/components/CallActionBar.qml b/src/mainview/components/CallActionBar.qml index a140ce95eb972e838ff790dd08ca5832dd73cdd1..e5e18e7121491ecebb2524b8844e676cd932090a 100644 --- a/src/mainview/components/CallActionBar.qml +++ b/src/mainview/components/CallActionBar.qml @@ -39,7 +39,7 @@ Control { signal addToConferenceClicked signal transferClicked // TODO: bind this signal shareScreenClicked - signal stopSharingScreenClicked + signal stopSharingClicked signal shareScreenAreaClicked // TODO: bind this signal pluginsClicked @@ -189,7 +189,7 @@ Control { Action { id: shareAction onTriggered: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ? - root.stopSharingScreenClicked() : + root.stopSharingClicked() : root.shareScreenClicked() icon.source: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ? "qrc:/images/icons/share_stop_black_24dp.svg" : @@ -197,7 +197,7 @@ Control { icon.color: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ? "red" : "white" text: AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY ? - JamiStrings.stopSharingScreen : + JamiStrings.stopSharing : JamiStrings.shareScreen property real size: 34 }, @@ -248,7 +248,7 @@ Control { if (isModerator && !isSIP) CallOverlayModel.addSecondaryControl(addPersonAction) CallOverlayModel.addSecondaryControl(chatAction) - if (!isAudioOnly) + if (!isAudioOnly && !isSIP) CallOverlayModel.addSecondaryControl(shareAction) CallOverlayModel.addSecondaryControl(recordAction) if (UtilsAdapter.checkShowPluginsButton(true)) diff --git a/src/mainview/components/CallOverlay.qml b/src/mainview/components/CallOverlay.qml index e4d68709e514763530c1ad4c358615d9cc5f74d5..3718d85469541b5c07cf727a2f335ea198ca4a43 100644 --- a/src/mainview/components/CallOverlay.qml +++ b/src/mainview/components/CallOverlay.qml @@ -54,11 +54,6 @@ Item { signal chatButtonClicked - onVisibleChanged: { - if (!visible) - callViewContextMenu.close() - } - ParticipantsLayer { id: __participantsLayer anchors.fill: parent @@ -195,7 +190,7 @@ Item { function onAddToConferenceClicked() { openContactPicker(ContactList.CONFERENCE) } function onTransferClicked() { openContactPicker(ContactList.TRANSFER) } function onShareScreenClicked() { openShareScreen() } - function onStopSharingScreenClicked() { AvAdapter.stopSharingScreen() } + function onStopSharingClicked() { AvAdapter.stopSharing() } function onShareScreenAreaClicked() { openShareScreenArea() } function onPluginsClicked() { openPluginsMenu() } } diff --git a/src/mainview/components/CallViewContextMenu.qml b/src/mainview/components/CallViewContextMenu.qml index 351813b2908d90927e1d5775ee1589e8151ad1ac..9de9ec41a82e70b024983c62f556169162f2ec72 100644 --- a/src/mainview/components/CallViewContextMenu.qml +++ b/src/mainview/components/CallViewContextMenu.qml @@ -27,12 +27,11 @@ import net.jami.Adapters 1.0 import net.jami.Constants 1.0 import "../../commoncomponents" -import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator -import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation +import "../../commoncomponents/contextmenu" import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation import "../js/screenrubberbandcreation.js" as ScreenRubberBandCreation -Item { +ContextMenuAutoLoader { id: root property bool isSIP: false @@ -44,140 +43,130 @@ Item { signal pluginItemClicked signal transferCallButtonClicked - function close() { - // leave this debug line is a reminder of a design failure - console.debug("call view context menu close") - const menu = ContextMenuGenerator.getMenu() - if (menu) - menu.close() - } - - function openMenu() { - ContextMenuGenerator.initMenu() - if (isSIP) { - ContextMenuGenerator.addMenuItem( - isPaused ? JamiStrings.resumeCall : JamiStrings.pauseCall, - isPaused ? "qrc:/images/icons/play_circle_outline-24px.svg" : - "qrc:/images/icons/pause_circle_outline-24px.svg", - function () { - CallAdapter.holdThisCallToggle() - }) - ContextMenuGenerator.addMenuItem(JamiStrings.sipInputPanel, - "qrc:/images/icons/ic_keypad.svg", - function () { - sipInputPanel.open() - }) - ContextMenuGenerator.addMenuItem( - JamiStrings.transferCall, - "qrc:/images/icons/phone_forwarded-24px.svg", - function () { - root.transferCallButtonClicked() - }) - - ContextMenuGenerator.addMenuSeparator() - } + property list<GeneralMenuItem> menuItems: [ + GeneralMenuItem { + id: resumePauseCall - ContextMenuGenerator.addMenuItem( - localIsRecording ? JamiStrings.stopRec : JamiStrings.startRec, - "qrc:/images/icons/av_icons/fiber_manual_record-24px.svg", - function () { - CallAdapter.recordThisCallToggle() - localIsRecording = CallAdapter.isRecordingThisCall() - }, JamiTheme.recordIconColor) - - if (isAudioOnly && !isPaused) - ContextMenuGenerator.addMenuItem( - JamiQmlUtils.callIsFullscreen ? JamiStrings.exitFullScreen : JamiStrings.fullScreen, - JamiQmlUtils.callIsFullscreen ? "qrc:/images/icons/close_fullscreen-24px.svg" : - "qrc:/images/icons/open_in_full-24px.svg", - function () { - callStackView.toggleFullScreen() - }) - - if (!isAudioOnly && !isPaused) { - ContextMenuGenerator.addMenuItem( - JamiQmlUtils.callIsFullscreen ? JamiStrings.exitFullScreen : JamiStrings.fullScreen, - JamiQmlUtils.callIsFullscreen ? "qrc:/images/icons/close_fullscreen-24px.svg" : - "qrc:/images/icons/open_in_full-24px.svg", - function () { - callStackView.toggleFullScreen() - }) - - ContextMenuGenerator.addMenuSeparator() - - generateDeviceMenuItem() - - ContextMenuGenerator.addMenuSeparator() - - if (AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY) { - ContextMenuGenerator.addMenuItem( - JamiStrings.stopSharingScreen, - "qrc:/images/icons/share_stop_black_24dp.svg", - function () { - AvAdapter.stopSharingScreen() - }) - } else { - ContextMenuGenerator.addMenuItem( - JamiStrings.shareScreen, - "qrc:/images/icons/share_screen_black_24dp.svg", - function () { - if (Qt.application.screens.length === 1) { - AvAdapter.shareEntireScreen(0) - } else { - SelectScreenWindowCreation.createSelectScreenWindowObject() - SelectScreenWindowCreation.showSelectScreenWindow() - } - }) - ContextMenuGenerator.addMenuItem( - JamiStrings.shareScreenArea, - "qrc:/images/icons/share_screen_black_24dp.svg", - function () { - if (Qt.platform.os !== "windows") { - AvAdapter.shareScreenArea(0, 0, 0, 0) - } else { - ScreenRubberBandCreation.createScreenRubberBandWindowObject() - ScreenRubberBandCreation.showScreenRubberBandWindow() - } - }) + canTrigger: isSIP + itemName: isPaused ? JamiStrings.resumeCall : JamiStrings.pauseCall + iconSource: isPaused ? "qrc:/images/icons/play_circle_outline-24px.svg" : + "qrc:/images/icons/pause_circle_outline-24px.svg" + onClicked: { + CallAdapter.holdThisCallToggle() + } + }, + GeneralMenuItem { + id: inputPanelSIP + + canTrigger: isSIP + itemName: JamiStrings.sipInputPanel + iconSource: "qrc:/images/icons/ic_keypad.svg" + onClicked: { + sipInputPanel.open() + } + }, + GeneralMenuItem { + id: callTransfer + + canTrigger: isSIP + itemName: JamiStrings.transferCall + iconSource: "qrc:/images/icons/phone_forwarded-24px.svg" + addMenuSeparatorAfter: isSIP + onClicked: { + root.transferCallButtonClicked() + } + }, + GeneralMenuItem { + id: localRecord + + itemName: localIsRecording ? JamiStrings.stopRec : JamiStrings.startRec + iconSource: "qrc:/images/icons/av_icons/fiber_manual_record-24px.svg" + iconColor: JamiTheme.recordIconColor + onClicked: { + CallAdapter.recordThisCallToggle() + localIsRecording = CallAdapter.isRecordingThisCall() + } + }, + GeneralMenuItem { + id: fullScreen + + itemName: JamiQmlUtils.callIsFullscreen ? + JamiStrings.exitFullScreen : JamiStrings.fullScreen + iconSource: JamiQmlUtils.callIsFullscreen ? + "qrc:/images/icons/close_fullscreen-24px.svg" : + "qrc:/images/icons/open_in_full-24px.svg" + onClicked: { + callStackView.toggleFullScreen() + } + }, + GeneralMenuItem { + id: stopSharing + + canTrigger: !isAudioOnly + && AvAdapter.currentRenderingDeviceType === Video.DeviceType.DISPLAY + && !isSIP + itemName: JamiStrings.stopSharing + iconSource: "qrc:/images/icons/share_stop_black_24dp.svg" + iconColor: JamiTheme.redColor + onClicked: { + AvAdapter.stopSharing() + } + }, + GeneralMenuItem { + id: shareScreen + + canTrigger: !isAudioOnly + && AvAdapter.currentRenderingDeviceType !== Video.DeviceType.DISPLAY + && !isSIP + itemName: JamiStrings.shareScreen + iconSource: "qrc:/images/icons/share_screen_black_24dp.svg" + onClicked: { + if (Qt.application.screens.length === 1) { + AvAdapter.shareEntireScreen(0) + } else { + SelectScreenWindowCreation.createSelectScreenWindowObject() + SelectScreenWindowCreation.showSelectScreenWindow() + } + } + }, + GeneralMenuItem { + id: shareScreenArea + + canTrigger: !isAudioOnly + && AvAdapter.currentRenderingDeviceType !== Video.DeviceType.DISPLAY + && !isSIP + itemName: JamiStrings.shareScreenArea + iconSource: "qrc:/images/icons/share_screen_black_24dp.svg" + onClicked: { + if (Qt.platform.os !== "windows") { + AvAdapter.shareScreenArea(0, 0, 0, 0) + } else { + ScreenRubberBandCreation.createScreenRubberBandWindowObject() + ScreenRubberBandCreation.showScreenRubberBandWindow() + } + } + }, + GeneralMenuItem { + id: shareFile + + canTrigger: !isAudioOnly && !isSIP + itemName: JamiStrings.shareFile + iconSource: "qrc:/images/icons/insert_photo-24px.svg" + onClicked: { + jamiFileDialog.open() + } + }, + GeneralMenuItem { + id: viewPlugin + + canTrigger: UtilsAdapter.checkShowPluginsButton(true) + itemName: JamiStrings.viewPlugin + iconSource: "qrc:/images/icons/extension_24dp.svg" + onClicked: { + root.pluginItemClicked() } - - ContextMenuGenerator.addMenuItem( - JamiStrings.shareFile, - "qrc:/images/icons/insert_photo-24px.svg", function () { - jamiFileDialog.open() - }) - } - - if (UtilsAdapter.checkShowPluginsButton(true)) { - ContextMenuGenerator.addMenuItem( - JamiStrings.viewPlugin, - "qrc:/images/icons/extension_24dp.svg", function () { - root.pluginItemClicked() - }) - } - - root.height = ContextMenuGenerator.getMenu().height - root.width = ContextMenuGenerator.getMenu().width - ContextMenuGenerator.getMenu().open() - } - - function generateDeviceMenuItem() { - var deviceContextMenuInfoMap = AvAdapter.populateVideoDeviceContextMenuItem() - - // Somehow, the map size is undefined, so use this instead. - var mapSize = deviceContextMenuInfoMap["size"] - - if (mapSize === 0) - VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects( - JamiStrings.noVideoDevice, false) - - for (var deviceName in deviceContextMenuInfoMap) { - if (deviceName === "size") - continue - VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects( - deviceName, deviceContextMenuInfoMap[deviceName]) } - } + ] JamiFileDialog { id: jamiFileDialog @@ -187,28 +176,5 @@ Item { onAccepted: AvAdapter.shareFile(jamiFileDialog.file) } - Component.onCompleted: { - ContextMenuGenerator.createBaseContextMenuObjects(root) - VideoDeviceContextMenuItemCreation.setVideoContextMenuObject( - ContextMenuGenerator.getMenu()) - - ContextMenuGenerator.getMenu().closed.connect(function () { - VideoDeviceContextMenuItemCreation.removeCreatedItems() - }) - } - - // TODO: In the future we want to implement this - - // GeneralMenuItem { - // id: advancedInfosItem - - // itemName: qsTr("Advanced informations") - // iconSource: "qrc:/images/icons/info-24px.svg" - // leftBorderWidth: commonBorderWidth - // rightBorderWidth: commonBorderWidth - - // onClicked: { - // root.close() - // } - // } + Component.onCompleted: menuItemsToLoad = menuItems } diff --git a/src/mainview/components/ContactSearchBar.qml b/src/mainview/components/ContactSearchBar.qml index 1f9dbc7545021c0df6989d10864314eac85f709c..ef817b4bb536b07b4448898238ffcfc58405191d 100644 --- a/src/mainview/components/ContactSearchBar.qml +++ b/src/mainview/components/ContactSearchBar.qml @@ -48,6 +48,8 @@ Rectangle { LineEditContextMenu { id: lineEditContextMenu + + lineEditObj: contactSearchBar } ResponsiveImage { @@ -99,7 +101,7 @@ Rectangle { onTextChanged: root.contactSearchBarTextChanged(contactSearchBar.text) onReleased: { if (event.button == Qt.RightButton) - lineEditContextMenu.openMenu(contactSearchBar, event) + lineEditContextMenu.openMenuAt(event) } } diff --git a/src/mainview/components/ConversationSmartListContextMenu.qml b/src/mainview/components/ConversationSmartListContextMenu.qml index c4a3bce54cbcb5f9c2ecc1bc13a02354b5dccad6..119eb76b89b74df3c38ec60b5fe206138b4926b9 100644 --- a/src/mainview/components/ConversationSmartListContextMenu.qml +++ b/src/mainview/components/ConversationSmartListContextMenu.qml @@ -25,108 +25,131 @@ import net.jami.Adapters 1.0 import net.jami.Constants 1.0 import "../../commoncomponents" -import "../../commoncomponents/js/contextmenugenerator.js" as ContextMenuGenerator +import "../../commoncomponents/contextmenu" -Item { +ContextMenuAutoLoader { id: root property string responsibleAccountId: "" property string responsibleConvUid: "" property int contactType: Profile.Type.INVALID + property bool hasCall: { + if (responsibleAccountId && responsibleConvUid) + return UtilsAdapter.getCallId(responsibleAccountId, + responsibleConvUid) !== "" + return false + } + + property list<GeneralMenuItem> menuItems: [ + GeneralMenuItem { + id: startVideoCallItem - function isOpen() { return ContextMenuGenerator.getMenu().visible } - - function openMenu() { - ContextMenuGenerator.initMenu() - var hasCall = UtilsAdapter.getCallId(responsibleAccountId, responsibleConvUid) !== "" - if (!hasCall) { - ContextMenuGenerator.addMenuItem(qsTr("Start video call"), - "qrc:/images/icons/videocam-24px.svg", - function (){ - LRCInstance.selectConversation(responsibleConvUid, responsibleAccountId) - CallAdapter.placeCall() - communicationPageMessageWebView.setSendContactRequestButtonVisible(false) - }) - ContextMenuGenerator.addMenuItem(qsTr("Start audio call"), - "qrc:/images/icons/place_audiocall-24px.svg", - function (){ - LRCInstance.selectConversation(responsibleConvUid, responsibleAccountId) - CallAdapter.placeAudioOnlyCall() - communicationPageMessageWebView.setSendContactRequestButtonVisible(false) - }) - - ContextMenuGenerator.addMenuItem(qsTr("Clear conversation"), - "qrc:/images/icons/ic_clear_24px.svg", - function (){ - MessagesAdapter.clearConversationHistory( - responsibleAccountId, - responsibleConvUid) - }) - - if (contactType === Profile.Type.RING || contactType === Profile.Type.SIP) { - ContextMenuGenerator.addMenuItem(qsTr("Remove contact"), - "qrc:/images/icons/ic_hangup_participant-24px.svg", - function (){ - MessagesAdapter.removeConversation( - responsibleAccountId, - responsibleConvUid) - }) + canTrigger: !hasCall + itemName: JamiStrings.startVideoCall + iconSource: "qrc:/images/icons/videocam-24px.svg" + onClicked: { + LRCInstance.selectConversation(responsibleConvUid, + responsibleAccountId) + CallAdapter.placeCall() + communicationPageMessageWebView.setSendContactRequestButtonVisible( + false) } + }, + GeneralMenuItem { + id: startAudioCall - } else { - ContextMenuGenerator.addMenuItem(JamiStrings.hangup, - "qrc:/images/icons/ic_call_end_white_24px.svg", - function (){ - CallAdapter.hangUpACall(responsibleAccountId, - responsibleConvUid) - }) - } + canTrigger: !hasCall + itemName: JamiStrings.startAudioCall + iconSource: "qrc:/images/icons/place_audiocall-24px.svg" + onClicked: { + LRCInstance.selectConversation(responsibleConvUid, + responsibleAccountId) + CallAdapter.placeAudioOnlyCall() + communicationPageMessageWebView.setSendContactRequestButtonVisible( + false) + } + }, + GeneralMenuItem { + id: clearConversation - if ((contactType === Profile.Type.RING || contactType === Profile.Type.PENDING - || contactType === Profile.Type.TEMPORARY)) { - if (contactType === Profile.Type.PENDING || !hasCall) { - ContextMenuGenerator.addMenuSeparator() + canTrigger: !hasCall + itemName: JamiStrings.clearConversation + iconSource: "qrc:/images/icons/ic_clear_24px.svg" + onClicked: { + MessagesAdapter.clearConversationHistory(responsibleAccountId, + responsibleConvUid) } + }, + GeneralMenuItem { + id: removeContact - if (contactType === Profile.Type.PENDING) { - ContextMenuGenerator.addMenuItem(JamiStrings.acceptContactRequest, - "qrc:/images/icons/add_people-24px.svg", - function (){ - MessagesAdapter.acceptInvitation( - responsibleConvUid) - communicationPageMessageWebView. - setSendContactRequestButtonVisible(false) - }) - - ContextMenuGenerator.addMenuItem(JamiStrings.declineContactRequest, - "qrc:/images/icons/round-close-24px.svg", - function (){ - MessagesAdapter.refuseInvitation( - responsibleConvUid) - }) + canTrigger: !hasCall && (contactType === Profile.Type.RING + || contactType === Profile.Type.SIP) + itemName: JamiStrings.removeContact + iconSource: "qrc:/images/icons/ic_hangup_participant-24px.svg" + onClicked: { + MessagesAdapter.removeConversation(responsibleAccountId, + responsibleConvUid) } - if (!hasCall) { - ContextMenuGenerator.addMenuItem(qsTr("Block contact"), - "qrc:/images/icons/ic_block_24px.svg", - function (){ - MessagesAdapter.blockConversation( - responsibleConvUid) - }) + }, + GeneralMenuItem { + id: hangup + + canTrigger: hasCall + itemName: JamiStrings.hangup + iconSource: "qrc:/images/icons/ic_call_end_white_24px.svg" + addMenuSeparatorAfter: contactType !== Profile.Type.SIP + && (contactType === Profile.Type.PENDING + || !hasCall) + onClicked: { + CallAdapter.hangUpACall(responsibleAccountId, + responsibleConvUid) } - ContextMenuGenerator.addMenuSeparator() - ContextMenuGenerator.addMenuItem(qsTr("Contact details"), - "qrc:/images/icons/person-24px.svg", - function (){ - userProfile.open() - }) - } + }, + GeneralMenuItem { + id: acceptContactRequest - root.height = ContextMenuGenerator.getMenu().height - root.width = ContextMenuGenerator.getMenu().width - ContextMenuGenerator.getMenu().open() - } + canTrigger: contactType === Profile.Type.PENDING + itemName: JamiStrings.acceptContactRequest + iconSource: "qrc:/images/icons/add_people-24px.svg" + onClicked: { + MessagesAdapter.acceptInvitation(responsibleConvUid) + communicationPageMessageWebView.setSendContactRequestButtonVisible( + false) + } + }, + GeneralMenuItem { + id: declineContactRequest - Component.onCompleted: { - ContextMenuGenerator.createBaseContextMenuObjects(root) - } + canTrigger: contactType === Profile.Type.PENDING + itemName: JamiStrings.declineContactRequest + iconSource: "qrc:/images/icons/round-close-24px.svg" + onClicked: { + MessagesAdapter.refuseInvitation(responsibleConvUid) + } + }, + GeneralMenuItem { + id: blockContact + + canTrigger: !hasCall && contactType !== Profile.Type.SIP + itemName: JamiStrings.blockContact + iconSource: "qrc:/images/icons/ic_block_24px.svg" + addMenuSeparatorAfter: contactType !== Profile.Type.SIP + onClicked: { + MessagesAdapter.blockConversation(responsibleConvUid) + } + }, + GeneralMenuItem { + id: contactDetails + + canTrigger: contactType !== Profile.Type.SIP + itemName: JamiStrings.contactDetails + iconSource: "qrc:/images/icons/person-24px.svg" + onClicked: { + userProfile.open() + } + } + ] + + Component.onCompleted: menuItemsToLoad = menuItems } diff --git a/src/mainview/js/videodevicecontextmenuitemcreation.js b/src/mainview/js/videodevicecontextmenuitemcreation.js deleted file mode 100644 index ca17fc7cf732b9ab5ba7b14f8a1f1227b76d5c9b..0000000000000000000000000000000000000000 --- a/src/mainview/js/videodevicecontextmenuitemcreation.js +++ /dev/null @@ -1,89 +0,0 @@ - -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * - * 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 <https://www.gnu.org/licenses/>. - */ - - -/* - * Global storage for created video device context menu item, - * will be cleared once context menu is closed. - */ -var itemArray = [] - - -/* - * Global videoDeviceContextMenuItem component, object variable for creation. - */ -var videoContextMenuObject -var videoDeviceContextMenuItemComponent -var videoDeviceContextMenuItemObject - - -/* - * Init videoContextMenuObject. - */ -function setVideoContextMenuObject(obj) { - videoContextMenuObject = obj -} - -function createVideoDeviceContextMenuItemObjects(deviceName, setChecked) { - - videoDeviceContextMenuItemComponent = Qt.createComponent( - "../components/VideoCallPageContextMenuDeviceItem.qml") - if (videoDeviceContextMenuItemComponent.status === Component.Ready) - finishCreation(deviceName, setChecked) - else if (videoDeviceContextMenuItemComponent.status === Component.Error) - console.log("Error loading component:", - videoDeviceContextMenuItemComponent.errorString()) -} - -function finishCreation(deviceName, setChecked) { - videoDeviceContextMenuItemObject = videoDeviceContextMenuItemComponent.createObject() - if (videoDeviceContextMenuItemObject === null) { - // Error Handling. - console.log("Error creating video context menu object") - } - - videoDeviceContextMenuItemObject.leftBorderWidth = - videoContextMenuObject.commonBorderWidth - videoDeviceContextMenuItemObject.rightBorderWidth = - videoContextMenuObject.commonBorderWidth - videoDeviceContextMenuItemObject.itemName = deviceName - videoDeviceContextMenuItemObject.checkable = true - videoDeviceContextMenuItemObject.checked = setChecked - videoDeviceContextMenuItemObject.contextMenuPreferredWidth = videoContextMenuObject.implicitWidth - - - /* - * Push into the storage array, and insert it into context menu. - */ - itemArray.push(videoDeviceContextMenuItemObject) - videoContextMenuObject.addItem(videoDeviceContextMenuItemObject) - - videoDeviceContextMenuItemObject.clicked.connect(function () { - videoContextMenuObject.close() - }) -} - -function removeCreatedItems() { - var arrayLength = itemArray.length - for (var i = 0; i < arrayLength; i++) { - videoContextMenuObject.removeItem(itemArray[i]) - itemArray[i].destroy() - } - itemArray = [] -}