diff --git a/resources/icons/baseline_camera_alt_24dp.svg b/resources/icons/baseline_camera_alt_24dp.svg index 8347964512844eb8c8c9aacafe92823aeba4de0e..94b088f2be1b3d202b29c55a2f53b8361a12ac76 100644 --- a/resources/icons/baseline_camera_alt_24dp.svg +++ b/resources/icons/baseline_camera_alt_24dp.svg @@ -1 +1,19 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3.2"/><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/><path d="M0 0h24v24H0z" fill="none"/></svg> \ No newline at end of file +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> +<g id="Icones_Outline"> + <g id="Camera_Black_24dp"> + <g id="Ico_Camera" transform="translate(2.000000, 4.000000)"> + <g id="Fill-1"> + <path d="M1.6,16.3c-0.4,0-0.8-0.2-1.1-0.5c-0.2-0.2-0.4-0.6-0.4-0.9l0-0.2l0-11C0,3.4,0.2,3,0.5,2.7C0.7,2.4,1,2.3,1.3,2.2 + l0.2,0l4.4,0l1.2-2.5h5.7l1.2,2.5h4.3c0.4,0,0.8,0.2,1.1,0.5c0.2,0.2,0.4,0.6,0.4,0.9l0,0.2l0,11c0,0.4-0.2,0.8-0.5,1.1 + c-0.2,0.2-0.6,0.4-0.9,0.4l-0.2,0L1.6,16.3z M1.6,3.7L1.6,3.7l-0.1,11l0,0.1l17,0l0.1,0l0-11l0-0.1l-5.3,0L12,1.2H8L6.8,3.7H1.6 + z M10,13.4c-1.2,0-2.3-0.5-3.2-1.3c-0.8-0.8-1.3-2-1.3-3.2c0-1.2,0.5-2.3,1.3-3.2c0.8-0.8,2-1.3,3.2-1.3c1.2,0,2.3,0.5,3.2,1.3 + c0.8,0.8,1.3,2,1.3,3.2s-0.5,2.3-1.3,3.2C12.3,12.9,11.2,13.4,10,13.4z M10,5.9c-0.8,0-1.6,0.3-2.1,0.9S7,8.1,7,8.9 + c0,0.8,0.3,1.6,0.9,2.1c1.1,1.1,3.1,1.1,4.3,0c0.6-0.6,0.9-1.3,0.9-2.1c0-0.8-0.3-1.6-0.9-2.1C11.6,6.2,10.8,5.9,10,5.9z"/> + </g> + </g> + </g> +</g> +</svg> diff --git a/resources/icons/delete_24dp.svg b/resources/icons/delete_24dp.svg index 47e4e302b0463a0263636859aeb37c3da9ab3c4f..5c05fc8c1345da713cf4e02af4e4277290febb2f 100644 --- a/resources/icons/delete_24dp.svg +++ b/resources/icons/delete_24dp.svg @@ -1 +1,9 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="white"/><path d="M0 0h24v24H0z" fill="none"/></svg> \ No newline at end of file +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> +<path d="M20.9,4.6H15V4.2C15,3,14,2,12.8,2h-1.6C10,2,9,3,9,4.2v0.3H3.1c-0.4,0-0.7,0.3-0.7,0.7s0.3,0.7,0.7,0.7h1.4l0.7,13.8 + C5.2,21,6.3,22,7.6,22h8.9c1.3,0,2.4-1,2.4-2.3l0.7-13.8h1.4c0.4,0,0.7-0.3,0.7-0.7S21.3,4.6,20.9,4.6z M10.3,4.6V4.2 + c0-0.5,0.4-0.8,0.8-0.8h1.6c0.5,0,0.8,0.4,0.8,0.8v0.3H10.3z M18.1,5.9l-0.7,13.7c0,0.6-0.5,1-1,1H7.6c-0.6,0-1-0.4-1-1L5.8,5.9 + H18.1z"/> +</svg> diff --git a/resources/icons/round_folder_24dp.svg b/resources/icons/round_folder_24dp.svg index 4f02e223ddf232fbe366df90dcc2e46ca8f6e25e..6f201df32c6cf9dcefc2e854bf07e247ba3dadc8 100644 --- a/resources/icons/round_folder_24dp.svg +++ b/resources/icons/round_folder_24dp.svg @@ -1 +1,10 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M10.59 4.59C10.21 4.21 9.7 4 9.17 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-1.41-1.41z"/></svg> \ No newline at end of file +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> +<path d="M20.7,8.5c-0.1-1.3-1.1-2.3-2.4-2.3h-5.6c-0.3,0-0.7-0.2-0.9-0.5l-0.5-0.8c-0.4-0.7-1.2-1.2-2-1.2H5.7 + c-1.3,0-2.4,1.1-2.4,2.4l0.1,2.3c-0.4,0-0.7,0.2-1,0.5C2.2,9.2,2,9.6,2,10c0,0.1,0,0.2,0,0.3l1.1,7.9c0.2,1.2,1.2,2.1,2.4,2.1h13.1 + c1.2,0,2.2-0.9,2.4-2.1l1.1-7.9C22.1,9.4,21.5,8.6,20.7,8.5z M5.7,5.1h3.6c0.4,0,0.7,0.2,0.9,0.5l0.5,0.8c0.4,0.7,1.2,1.2,2,1.2h5.6 + c0.5,0,0.9,0.4,1,0.9H4.8L4.7,6.2l0,0C4.7,5.6,5.2,5.1,5.7,5.1z M19.5,18c-0.1,0.5-0.5,0.9-1,0.9H5.5c-0.5,0-0.9-0.4-1-0.9l-1.1-8 + c0-0.1,0-0.1,0.1-0.2c0,0,0.1-0.1,0.1-0.1l16.9,0c0.1,0,0.2,0.1,0.2,0.2L19.5,18z"/> +</svg> diff --git a/src/commoncomponents/PhotoboothView.qml b/src/commoncomponents/PhotoboothView.qml index c5c8d2f24d80ed85d5c97e15a7803f8c205d31ec..57dea273ad98a4a3bed0426fc79081d27da7f9cc 100644 --- a/src/commoncomponents/PhotoboothView.qml +++ b/src/commoncomponents/PhotoboothView.qml @@ -25,30 +25,28 @@ import net.jami.Models 1.1 import net.jami.Adapters 1.1 import net.jami.Constants 1.1 +import "../mainview/components" + Item { id: root - property bool isPreviewing: false property alias imageId: avatar.imageId property bool newConversation: false property real avatarSize + property real buttonSize: avatarSize + property bool inverted: false signal focusOnPreviousItem signal focusOnNextItem - width: avatarSize - height: boothLayout.height + height: Math.max(avatarSize, buttonSize) function startBooth() { - preview.startWithId(VideoDevices.getDefaultDevice()) - isPreviewing = true + recordBox.openRecorder(true) } function stopBooth(){ - if (!AccountAdapter.hasVideoCall()) { - VideoDevices.stopDevice(preview.deviceId) - } - isPreviewing = false + recordBox.closeRecorder() } function focusOnNextPhotoBoothItem () { @@ -56,10 +54,7 @@ Item { } function focusOnPreviousPhotoBoothItem () { - if (isPreviewing) - clearButton.forceActiveFocus() - else - importButton.forceActiveFocus() + importButton.forceActiveFocus() } onVisibleChanged: { @@ -68,6 +63,21 @@ Item { } } + RecordBox { + id: recordBox + + isPhoto: true + visible: false + + onValidatePhoto: function(photo) { + if (!root.newConversation) + AccountAdapter.setCurrentAccountAvatarBase64(photo) + else + UtilsAdapter.setSwarmCreationImageFromString(photo, imageId) + buttonsRowLayout.backToAvatar() + } + } + JamiFileDialog { id: importFromFileDialog @@ -109,228 +119,273 @@ Item { } } - ColumnLayout { - id: boothLayout - - spacing: JamiTheme.preferredMarginSize / 2 - - Item { - id: imageLayer - - Layout.preferredWidth: avatarSize - Layout.preferredHeight: avatarSize - Layout.alignment: Qt.AlignHCenter - - Avatar { - id: avatar - - anchors.fill: parent - anchors.margins: 1 - - visible: !preview.visible + Item { + id: imageLayer - mode: newConversation? Avatar.Mode.Conversation : Avatar.Mode.Account - - fillMode: Image.PreserveAspectCrop - showPresenceIndicator: false - } + anchors.centerIn: parent + width: avatarSize + height: avatarSize - LocalVideo { - id: preview + Avatar { + id: avatar - anchors.fill: parent - anchors.margins: 1 + anchors.fill: parent + anchors.margins: 1 - visible: isPreviewing + mode: newConversation? Avatar.Mode.Conversation : Avatar.Mode.Account - rendererId: VideoDevices.getDefaultDevice() + fillMode: Image.PreserveAspectCrop + showPresenceIndicator: false - function takePhoto() { - return videoProvider.captureVideoFrame(videoSink) + HoverHandler { + target: parent + enabled: parent.visible + onHoveredChanged: { + overlayHighlighted.visible = hovered } + } - layer.enabled: true - layer.effect: OpacityMask { - maskSource: Rectangle { - width: avatarSize - height: avatarSize - radius: avatarSize / 2 - } + TapHandler { + target: parent + enabled: parent.visible + onTapped: { + imageLayer.visible = false + buttonsRowLayout.visible = true } } Rectangle { - id: flashRect + id: overlayHighlighted + visible: false anchors.fill: parent - anchors.margins: 0 - radius: avatarSize / 2 - color: "white" - opacity: 0 + color: Qt.rgba(0, 0, 0, 0.5) + radius: parent.height / 2 - SequentialAnimation { - id: flashAnimation + opacity: visible + Behavior on opacity { NumberAnimation { - target: flashRect; property: "opacity" - to: 1; duration: 0 + from: 0 + duration: JamiTheme.shortFadeDuration } - NumberAnimation { - target: flashRect; property: "opacity" - to: 0; duration: 500 + } + + Image { + id: overlayImage + + width: JamiTheme.smartListAvatarSize / 2 + height: JamiTheme.smartListAvatarSize / 2 + anchors.centerIn: parent + + layer { + enabled: true + effect: ColorOverlay { + color: "white" + } } + source: JamiResources.round_edit_24dp_svg } } } + } - RowLayout { - id: buttonsRowLayout - - Layout.fillWidth: true - Layout.preferredHeight: childrenRect.height - Layout.bottomMargin: parent.spacing - Layout.alignment: Qt.AlignHCenter + RowLayout { + id: buttonsRowLayout + visible: false - PushButton { - id: takePhotoButton + anchors.centerIn: parent + Layout.preferredHeight: childrenRect.height + spacing: 12 - objectName: "takePhotoButton" + function backToAvatar() { + imageLayer.visible = true + buttonsRowLayout.visible = false + } - Layout.alignment: Qt.AlignHCenter + PushButton { + id: takePhotoButton - radius: JamiTheme.primaryRadius - imageColor: JamiTheme.textColor - toolTipText: JamiStrings.takePhoto - source: isPreviewing ? - JamiResources.round_add_a_photo_24dp_svg : - JamiResources.baseline_camera_alt_24dp_svg + objectName: "takePhotoButton" - Keys.onPressed: function (keyEvent) { - if (keyEvent.key === Qt.Key_Enter || - keyEvent.key === Qt.Key_Return) { - clicked() - keyEvent.accepted = true - } else if (keyEvent.key === Qt.Key_Up) { - root.focusOnPreviousItem() - keyEvent.accepted = true - } - } + Layout.alignment: Qt.AlignHCenter - KeyNavigation.tab: { - if (clearButton.visible) - return clearButton - return importButton + height: buttonSize + width: buttonSize + radius: height / 2 + border.width: 2 + border.color: JamiTheme.textColor + normalColor: "transparent" + imageColor: JamiTheme.textColor + toolTipText: JamiStrings.takePhoto + source: JamiResources.baseline_camera_alt_24dp_svg + hoveredColor: Qt.rgba(255, 255, 255, 0.2) + + Keys.onPressed: function (keyEvent) { + if (keyEvent.key === Qt.Key_Enter || + keyEvent.key === Qt.Key_Return) { + clicked() + keyEvent.accepted = true + } else if (keyEvent.key === Qt.Key_Up) { + root.focusOnPreviousItem() + keyEvent.accepted = true } - KeyNavigation.down: KeyNavigation.tab - - onClicked: { - if (isPreviewing) { - flashAnimation.start() - var photo = preview.takePhoto(avatarSize) - if (!root.newConversation) - AccountAdapter.setCurrentAccountAvatarBase64(photo) - else - UtilsAdapter.setSwarmCreationImageFromString(photo, imageId) - stopBooth() - return - } + } - startBooth() - } + KeyNavigation.tab: { + if (clearButton.visible) + return clearButton + return importButton } + KeyNavigation.down: KeyNavigation.tab + + onClicked: { + recordBox.parent = takePhotoButton + + recordBox.x = Qt.binding(function() { + var buttonCenterX = takePhotoButton.x + takePhotoButton.width / 2 + return buttonCenterX - recordBox.width / 2 + }) + recordBox.y = Qt.binding(function() { + var buttonY = takePhotoButton.y + return inverted? buttonY + takePhotoButton.height : buttonY - recordBox.height + }) + startBooth() + } + } - PushButton { - id: clearButton + PushButton { + id: importButton - objectName: "photoboothViewClearButton" + objectName: "photoboothViewImportButton" - Layout.alignment: Qt.AlignHCenter + property bool focusAfterFileDialogClosed: false - visible: { - if (isPreviewing) - return true - if (!newConversation && LRCInstance.currentAccountAvatarSet) - return true - if (newConversation && UtilsAdapter.swarmCreationImage(imageId).length !== 0) - return true - return false + Layout.alignment: Qt.AlignHCenter + visible: parent.visible + + height: buttonSize + width: buttonSize + radius: height / 2 + border.width: 2 + border.color: JamiTheme.textColor + normalColor: "transparent" + source: JamiResources.round_folder_24dp_svg + toolTipText: JamiStrings.importFromFile + imageColor: JamiTheme.textColor + hoveredColor: Qt.rgba(255, 255, 255, 0.2) + + Keys.onPressed: function (keyEvent) { + if (keyEvent.key === Qt.Key_Enter || + keyEvent.key === Qt.Key_Return) { + focusAfterFileDialogClosed = true + clicked() + keyEvent.accepted = true + } else if (keyEvent.key === Qt.Key_Down || + keyEvent.key === Qt.Key_Tab) { + clearButton.forceActiveFocus() + keyEvent.accepted = true } + } - radius: JamiTheme.primaryRadius - source: JamiResources.round_close_24dp_svg - toolTipText: isPreviewing ? JamiStrings.stopTakingPhoto : - JamiStrings.clearAvatar - imageColor: JamiTheme.textColor - - KeyNavigation.up: takePhotoButton - - Keys.onPressed: function (keyEvent) { - if (keyEvent.key === Qt.Key_Enter || - keyEvent.key === Qt.Key_Return) { - clicked() - takePhotoButton.forceActiveFocus() - keyEvent.accepted = true - } else if (keyEvent.key === Qt.Key_Down || - keyEvent.key === Qt.Key_Tab) { - if (isPreviewing) { - root.focusOnNextItem() - } else - importButton.forceActiveFocus() - keyEvent.accepted = true - } - } + KeyNavigation.up: takePhotoButton - onClicked: { - stopBooth() - if (!isPreviewing) { - if (!root.newConversation) - AccountAdapter.setCurrentAccountAvatarBase64() - else - UtilsAdapter.setSwarmCreationImageFromString("", imageId) - } - } + onClicked: { + stopBooth() + buttonsRowLayout.backToAvatar() + importFromFileDialog.open() } + } - PushButton { - id: importButton - - objectName: "photoboothViewImportButton" - property bool focusAfterFileDialogClosed: false + PushButton { + id: clearButton - Layout.alignment: Qt.AlignHCenter + objectName: "photoboothViewClearButton" - visible: !isPreviewing + Layout.alignment: Qt.AlignHCenter - radius: JamiTheme.primaryRadius - source: JamiResources.round_folder_24dp_svg - toolTipText: JamiStrings.importFromFile - imageColor: JamiTheme.textColor + height: buttonSize + width: buttonSize + radius: height / 2 + border.width: 2 + border.color: JamiTheme.textColor + normalColor: "transparent" + source: JamiResources.ic_hangup_participant_24dp_svg + toolTipText: JamiStrings.clearAvatar + imageColor: JamiTheme.textColor + hoveredColor: Qt.rgba(255, 255, 255, 0.2) + + visible: { + if (!newConversation && LRCInstance.currentAccountAvatarSet) + return true + if (newConversation && UtilsAdapter.swarmCreationImage(imageId).length !== 0) + return true + return false + } - Keys.onPressed: function (keyEvent) { - if (keyEvent.key === Qt.Key_Enter || - keyEvent.key === Qt.Key_Return) { - focusAfterFileDialogClosed = true - clicked() - keyEvent.accepted = true - } else if (keyEvent.key === Qt.Key_Down || - keyEvent.key === Qt.Key_Tab) { - root.focusOnNextItem() - keyEvent.accepted = true - } + KeyNavigation.up: importButton + + Keys.onPressed: function (keyEvent) { + if (keyEvent.key === Qt.Key_Enter || + keyEvent.key === Qt.Key_Return) { + clicked() + importButton.forceActiveFocus() + keyEvent.accepted = true + } else if (keyEvent.key === Qt.Key_Down || + keyEvent.key === Qt.Key_Tab) { + cancelButton.forceActiveFocus() + keyEvent.accepted = true } + } - KeyNavigation.up: { - if (clearButton.visible) - return clearButton - return takePhotoButton - } + onClicked: { + if (!root.newConversation) + AccountAdapter.setCurrentAccountAvatarBase64() + else + UtilsAdapter.setSwarmCreationImageFromString("", imageId) + stopBooth() + buttonsRowLayout.backToAvatar() + } + } - onClicked: { - stopBooth() - importFromFileDialog.open() + PushButton { + id: cancelButton + + preferredSize: 18 + radius: height / 2 + normalColor: "transparent" + source: JamiResources.round_close_24dp_svg + toolTipText: JamiStrings.cancel + imageColor: JamiTheme.textColor + hoveredColor: Qt.rgba(255, 255, 255, 0.2) + Layout.leftMargin: -8 + + Keys.onPressed: function (keyEvent) { + if (keyEvent.key === Qt.Key_Enter || + keyEvent.key === Qt.Key_Return) { + clicked() + takePhotoButton.forceActiveFocus() + keyEvent.accepted = true + } else if (keyEvent.key === Qt.Key_Down || + keyEvent.key === Qt.Key_Tab) { + importButton.forceActiveFocus() + keyEvent.accepted = true } } + + KeyNavigation.up: { + if (clearButton.visible) + return clearButton + if (importButton.visible) + return importButton + return takePhotoButton + } + + onClicked: { + stopBooth() + buttonsRowLayout.backToAvatar() + } } } } diff --git a/src/commoncomponents/PushButton.qml b/src/commoncomponents/PushButton.qml index 4ec286ee349beafc730435336ff66361a901d095..46dfe3197b51348b45228c80f6104976881b87fc 100644 --- a/src/commoncomponents/PushButton.qml +++ b/src/commoncomponents/PushButton.qml @@ -41,6 +41,7 @@ AbstractButton { property int preferredMargin: 16 // Note the radius will default to preferredSize property alias radius: background.radius + property alias border: background.border // Text properties property alias buttonText: textContent.text diff --git a/src/mainview/components/NewSwarmPage.qml b/src/mainview/components/NewSwarmPage.qml index e28a629cf78680aadafbff9a04895a3700562be4..ab44ae8848ccb4ecdf3d81e278e5be20c6839707 100644 --- a/src/mainview/components/NewSwarmPage.qml +++ b/src/mainview/components/NewSwarmPage.qml @@ -114,6 +114,7 @@ Rectangle { newConversation: true imageId: root.visible ? "temp" : "" avatarSize: 180 + buttonSize: JamiTheme.smartListAvatarSize } EditableLineEdit { @@ -123,7 +124,7 @@ Rectangle { font.pointSize: JamiTheme.titleFontSize - horizontalAlignment: Text.AlignHCenter + horizontalAlignment: editable ? Text.AlignLeft : Text.AlignHCenter verticalAlignment: Text.AlignVCenter placeholderText: JamiStrings.editTitle @@ -139,6 +140,9 @@ Rectangle { font.pointSize: JamiTheme.titleFontSize + horizontalAlignment: editable ? Text.AlignLeft : Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + placeholderText: JamiStrings.editDescription tooltipText: JamiStrings.editDescription backgroundColor: root.color diff --git a/src/mainview/components/RecordBox.qml b/src/mainview/components/RecordBox.qml index 75679e3c64cb756d4d4c586369a74ed327a502ed..83957535a8ace7c77bf5747f00a8edea5fecb0c8 100644 --- a/src/mainview/components/RecordBox.qml +++ b/src/mainview/components/RecordBox.qml @@ -19,7 +19,6 @@ import QtQuick import QtQuick.Controls import Qt5Compat.GraphicalEffects -import QtQuick.Shapes import net.jami.Models 1.1 import net.jami.Adapters 1.1 @@ -27,7 +26,7 @@ import net.jami.Constants 1.1 import "../../commoncomponents" -Rectangle { +Popup { id: root enum States { @@ -37,10 +36,10 @@ Rectangle { } property string pathRecorder: "" - property string timeText: "00:00" property int duration: 0 property int state: RecordBox.States.INIT property bool isVideo: false + property bool isPhoto: false property int preferredWidth: 320 property int preferredHeight: 240 property int btnSize: 40 @@ -49,9 +48,11 @@ Rectangle { property int curveRadius: 6 property int spikeHeight: 10 + offset + property string photo: "" + + signal validatePhoto(string photo) + function openRecorder(vid) { - focus = true - visible = true isVideo = vid scaleHeight() @@ -60,6 +61,7 @@ Rectangle { if (isVideo) { previewWidget.startWithId(VideoDevices.getDefaultDevice()) } + open() } function scaleHeight() { @@ -80,14 +82,22 @@ Rectangle { if (isVideo) { VideoDevices.stopDevice(previewWidget.deviceId) } - stopRecording() - visible = false + if (!root.isPhoto) + stopRecording() + close() } function updateState(new_state) { state = new_state - recordButton.visible = (state === RecordBox.States.INIT) - btnStop.visible = (state === RecordBox.States.RECORDING) + if (isPhoto) { + screenshotBtn.visible = (state === RecordBox.States.INIT) + recordButton.visible = false + btnStop.visible = false + } else { + screenshotBtn.visible = false + recordButton.visible = (state === RecordBox.States.INIT) + btnStop.visible = (state === RecordBox.States.RECORDING) + } btnRestart.visible = (state === RecordBox.States.REC_SUCCESS) btnSend.visible = (state === RecordBox.States.REC_SUCCESS) @@ -135,9 +145,8 @@ Rectangle { width: 320 height: 240 - radius: 5 - border.color: JamiTheme.tabbarBorderColor - color: JamiTheme.backgroundColor + modal: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent onActiveFocusChanged: { if (visible) { @@ -151,239 +160,284 @@ Rectangle { } } - Shape { - id: backgroundShape + background: Rectangle { + anchors.fill: parent + visible: !root.isVideo + radius: 5 + border.color: JamiTheme.tabbarBorderColor + color: JamiTheme.backgroundColor + } - anchors.centerIn: parent + Item { + anchors.fill: parent + anchors.margins: 0 + + Rectangle { + id: rectBox + + anchors.fill: parent + + visible: (isVideo && VideoDevices.listSize !== 0) + color: JamiTheme.blackColor + radius: 5 + + Item { + // Else it will be resized by the layer effect + id: photoMask + visible: false + anchors.fill: rectBox + Rectangle { + anchors.centerIn: parent + height: parent.height + width: parent.height + radius: height / 2 + } + } - width: root.width - height: root.height + Image { + id: screenshotImg + visible: parent.visible && root.isPhoto && btnSend.visible + + anchors.fill: parent + + layer.enabled: true + layer.effect: OpacityMask { + maskSource: rectBox + } + + Rectangle { + anchors.fill: parent + color: "black" + opacity: 0.6 + + layer.enabled: true + layer.effect: OpacityMask { + anchors.centerIn: parent + maskSource: photoMask + invert: true + } + } + source: root.photo === "" ? "" : "data:image/png;base64," + root.photo + } - x: -offset - y: -offset + LocalVideo { + id: previewWidget - ShapePath { - fillColor: JamiTheme.backgroundColor + visible: parent.visible && !screenshotImg.visible - strokeWidth: 1 - strokeColor: JamiTheme.tabbarBorderColor + anchors.fill: rectBox + anchors.margins: 1 - startX: -offset + curveRadius - startY: -offset - joinStyle: ShapePath.RoundJoin + rendererId: VideoDevices.getDefaultDevice() - PathLine { - x: width + offset - curveRadius - y: -offset - } + layer.enabled: true + layer.effect: OpacityMask { + maskSource: rectBox + } - PathArc { - x: width + offset - y: -offset + curveRadius - radiusX: curveRadius - radiusY: curveRadius - } + Rectangle { + anchors.fill: parent + color: "black" + opacity: 0.6 + visible: root.isPhoto - PathLine { - x: width + offset - y: height + offset - curveRadius - } - - PathArc { - x: width + offset - curveRadius - y: height + offset - radiusX: curveRadius - radiusY: curveRadius + layer.enabled: true + layer.effect: OpacityMask { + anchors.centerIn: parent + maskSource: photoMask + invert: true + } + } } + } - PathLine { - x: width / 2 + 10 - y: height + offset - } - PathLine { - x: width / 2 - y: height + spikeHeight - } - PathLine { - x: width / 2 - 10 - y: height + offset - } + Label { + anchors.centerIn: parent - PathLine { - x: -offset + curveRadius - y: height + offset - } + width: root.width - PathArc { - x: -offset - y: height + offset - curveRadius - radiusX: curveRadius - radiusY: curveRadius - } + visible: (isVideo && VideoDevices.listSize === 0) - PathLine { - x: -offset - y: -offset + curveRadius + onVisibleChanged: { + if (visible) { + closeRecorder() + } } - PathArc { - x: -offset + curveRadius - y: -offset - radiusX: curveRadius - radiusY: curveRadius - } + text: JamiStrings.previewUnavailable + font.pointSize: JamiTheme.settingsFontSize + font.kerning: true + color: JamiTheme.primaryForegroundColor + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter } - } - Rectangle { - id: rectBox + Timer { + id: timer - anchors.fill: parent - - visible: (isVideo && VideoDevices.listSize !== 0) - color: JamiTheme.blackColor - radius: 5 + interval: 1000 + running: false + repeat: true - LocalVideo { - id: previewWidget + onTriggered: updateTimer() + } - anchors.fill: rectBox - anchors.margins: 1 + Text { + id: time - rendererId: VideoDevices.getDefaultDevice() + anchors.centerIn: recordButton + anchors.horizontalCenterOffset: (isVideo ? 100 : 0) + anchors.verticalCenterOffset: (isVideo ? 0 : -100) - layer.enabled: true - layer.effect: OpacityMask { - maskSource: rectBox - } + visible: !root.isPhoto + text: "00:00" + color: (isVideo ? JamiTheme.whiteColor : JamiTheme.textColor) + font.pointSize: (isVideo ? 12 : 20) } - } - Label { - anchors.centerIn: parent + PushButton { + id: recordButton - width: root.width + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 - visible: (isVideo && VideoDevices.listSize === 0) + preferredSize: btnSize - onVisibleChanged: { - if (visible) { - closeRecorder() + normalColor: isVideo ? "transparent" : JamiTheme.backgroundColor + hoveredColor: Qt.rgba(255, 255, 255, 0.2) + + source: JamiResources.fiber_manual_record_24dp_svg + imageColor: JamiTheme.recordIconColor + + onClicked: { + updateState(RecordBox.States.RECORDING) + if (!root.isPhoto) + startRecording() } } - text: JamiStrings.previewUnavailable - font.pointSize: JamiTheme.settingsFontSize - font.kerning: true - color: JamiTheme.primaryForegroundColor - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } + PushButton { + id: screenshotBtn - Timer { - id: timer + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 - interval: 1000 - running: false - repeat: true + preferredSize: btnSize - onTriggered: updateTimer() - } - - Text { - id: time + normalColor: isVideo ? "transparent" : JamiTheme.backgroundColor + hoveredColor: Qt.rgba(255, 255, 255, 0.2) + border.width: 1 + border.color: imageColor - anchors.centerIn: recordButton - anchors.horizontalCenterOffset: (isVideo ? 100 : 0) - anchors.verticalCenterOffset: (isVideo ? 0 : -100) + source: JamiResources.fiber_manual_record_24dp_svg + imageColor: JamiTheme.whiteColor - visible: true - text: "00:00" - color: (isVideo ? JamiTheme.whiteColor : JamiTheme.textColor) - font.pointSize: (isVideo ? 12 : 20) - } + onClicked: { + root.photo = videoProvider.captureVideoFrame(previewWidget.videoSink) + updateState(RecordBox.States.REC_SUCCESS) + } + } - PushButton { - id: recordButton + PushButton { + id: btnStop - anchors.horizontalCenter: root.horizontalCenter - anchors.bottom: root.bottom - anchors.bottomMargin: 5 + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 - preferredSize: btnSize + preferredSize: btnSize - normalColor: isVideo ? "transparent" : JamiTheme.backgroundColor + normalColor: isVideo ? "transparent" : JamiTheme.backgroundColor + hoveredColor: Qt.rgba(255, 255, 255, 0.2) - source: JamiResources.fiber_manual_record_24dp_svg - imageColor: JamiTheme.recordIconColor + source: JamiResources.stop_24dp_red_svg + imageColor: isVideo ? JamiTheme.whiteColor : JamiTheme.textColor + border.width: 1 + border.color: imageColor - onClicked: { - updateState(RecordBox.States.RECORDING) - startRecording() + onClicked: { + if (!root.isPhoto) + stopRecording() + updateState(RecordBox.States.REC_SUCCESS) + } } - } - PushButton { - id: btnStop + PushButton { + id: btnRestart - anchors.horizontalCenter: root.horizontalCenter - anchors.bottom: root.bottom - anchors.bottomMargin: 5 + anchors.horizontalCenter: parent.horizontalCenter + anchors.horizontalCenterOffset: -25 + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 - preferredSize: btnSize + preferredSize: btnSize - normalColor: isVideo ? "transparent" : JamiTheme.backgroundColor + normalColor: isVideo ? "transparent" : JamiTheme.backgroundColor - source: JamiResources.stop_24dp_red_svg - imageColor: isVideo ? JamiTheme.whiteColor : JamiTheme.textColor + source: JamiResources.re_record_24dp_svg + hoveredColor: Qt.rgba(255, 255, 255, 0.2) + imageColor: isVideo ? JamiTheme.whiteColor : JamiTheme.textColor + border.width: 1 + border.color: imageColor - onClicked: { - stopRecording() - updateState(RecordBox.States.REC_SUCCESS) + onClicked: { + if (!root.isPhoto) + stopRecording() + updateState(RecordBox.States.INIT) + } } - } - PushButton { - id: btnRestart + PushButton { + id: btnSend - anchors.horizontalCenter: root.horizontalCenter - anchors.horizontalCenterOffset: -25 - anchors.bottom: root.bottom - anchors.bottomMargin: 5 + anchors.horizontalCenter: parent.horizontalCenter + anchors.horizontalCenterOffset: 25 + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 - preferredSize: btnSize + preferredSize: btnSize - normalColor: isVideo ? "transparent" : JamiTheme.backgroundColor + normalColor: isVideo ? "transparent" : JamiTheme.backgroundColor - source: JamiResources.re_record_24dp_svg - imageColor: isVideo ? JamiTheme.whiteColor : JamiTheme.textColor + source: JamiResources.check_black_24dp_svg + imageColor: isVideo ? JamiTheme.whiteColor : JamiTheme.textColor + border.width: 1 + border.color: imageColor - onClicked: { - stopRecording() - updateState(RecordBox.States.INIT) + onClicked: { + if (!root.isPhoto) { + stopRecording() + sendRecord() + } else if (root.photo !== "") { + root.validatePhoto(root.photo) + } + closeRecorder() + updateState(RecordBox.States.INIT) + } } - } - PushButton { - id: btnSend + PushButton { + id: cancelBtn - anchors.horizontalCenter: root.horizontalCenter - anchors.horizontalCenterOffset: 25 - anchors.bottom: parent.bottom - anchors.bottomMargin: 5 + normalColor: "transparent" + hoveredColor: Qt.rgba(255, 255, 255, 0.2) + imageColor: JamiTheme.primaryForegroundColor - preferredSize: btnSize + preferredSize: 12 - normalColor: isVideo ? "transparent" : JamiTheme.backgroundColor + source: JamiResources.round_close_24dp_svg + toolTipText: JamiStrings.back - source: JamiResources.send_24dp_svg - imageColor: isVideo ? JamiTheme.whiteColor : JamiTheme.textColor + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: 8 - onClicked: { - stopRecording() - sendRecord() - closeRecorder() - updateState(RecordBox.States.INIT) + onClicked: { + closeRecorder() + updateState(RecordBox.States.INIT) + } } } } diff --git a/src/mainview/components/SwarmDetailsPanel.qml b/src/mainview/components/SwarmDetailsPanel.qml index b28a32a26f4785d76c866a6a9e0c1f57061399d5..e3ac8d566fb0382850ea31986635c8c587ad3dfb 100644 --- a/src/mainview/components/SwarmDetailsPanel.qml +++ b/src/mainview/components/SwarmDetailsPanel.qml @@ -46,14 +46,15 @@ Rectangle { PhotoboothView { id: currentAccountAvatar + inverted: true - Layout.alignment: Qt.AlignCenter Layout.topMargin: JamiTheme.swarmDetailsPageTopMargin Layout.bottomMargin: JamiTheme.preferredMarginSize + Layout.alignment: Qt.AlignHCenter newConversation: true imageId: LRCInstance.selectedConvUid - avatarSize: JamiTheme.avatarSizeInCall + avatarSize: JamiTheme.smartListAvatarSize } EditableLineEdit { diff --git a/src/settingsview/components/AccountProfile.qml b/src/settingsview/components/AccountProfile.qml index 55efe335d70db834d978f6afca1aae1cdfe900c1..fa6ffe76538277393702f18fc71c3d97d5ba9bd9 100644 --- a/src/settingsview/components/AccountProfile.qml +++ b/src/settingsview/components/AccountProfile.qml @@ -62,6 +62,7 @@ ColumnLayout { imageId: LRCInstance.currentAccountId avatarSize: 180 + buttonSize: JamiTheme.smartListAvatarSize } MaterialLineEdit { diff --git a/src/wizardview/components/ProfilePage.qml b/src/wizardview/components/ProfilePage.qml index cba86402d98518e19d376a929b7874a18ecfd607..a1c13140863542a34e864ba00aef65b53203cb06 100644 --- a/src/wizardview/components/ProfilePage.qml +++ b/src/wizardview/components/ProfilePage.qml @@ -105,6 +105,7 @@ Rectangle { enabled: !saveProfileBtn.spinnerTriggered imageId: createdAccountId avatarSize: 200 + buttonSize: JamiTheme.smartListAvatarSize onFocusOnPreviousItem: { skipProfileSavingButton.forceActiveFocus()