diff --git a/resources/qml/Avatar.qml b/resources/qml/Avatar.qml
index aa873ffe..2801bd37 100644
--- a/resources/qml/Avatar.qml
+++ b/resources/qml/Avatar.qml
@@ -1,3 +1,4 @@
+import "./ui"
import QtGraphicalEffects 1.0
import QtQuick 2.6
import QtQuick.Controls 2.3
@@ -43,6 +44,12 @@ Rectangle {
anchors.fill: parent
onClicked: TimelineManager.openImageOverlay(TimelineManager.timeline.avatarUrl(userid), TimelineManager.timeline.data.id)
+
+ Ripple {
+ rippleTarget: mouseArea
+ color: Qt.rgba(colors.alternateBase.r, colors.alternateBase.g, colors.alternateBase.b, 0.5)
+ }
+
}
layer.effect: OpacityMask {
diff --git a/resources/qml/ImageButton.qml b/resources/qml/ImageButton.qml
index 4ebda680..b5a34b7b 100644
--- a/resources/qml/ImageButton.qml
+++ b/resources/qml/ImageButton.qml
@@ -1,3 +1,4 @@
+import "./ui"
import QtQuick 2.3
import QtQuick.Controls 2.3
@@ -28,4 +29,10 @@ AbstractButton {
cursorShape: Qt.PointingHandCursor
}
+ Ripple {
+ color: Qt.rgba(buttonTextColor.r, buttonTextColor.g, buttonTextColor.b, 0.5)
+ clip: false
+ rippleTarget: button
+ }
+
}
diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml
index 00edb7e5..0090ea95 100644
--- a/resources/qml/MessageInput.qml
+++ b/resources/qml/MessageInput.qml
@@ -16,6 +16,7 @@ Rectangle {
PlaceCall {
}
+
}
RowLayout {
@@ -26,7 +27,7 @@ Rectangle {
ImageButton {
visible: CallManager.callsSupported
- opacity: CallManager.haveCallInvite ? 0.3 : 1.0
+ opacity: CallManager.haveCallInvite ? 0.3 : 1
Layout.alignment: Qt.AlignBottom
hoverEnabled: true
width: 22
@@ -40,12 +41,10 @@ Rectangle {
onClicked: {
if (TimelineManager.timeline) {
if (CallManager.haveCallInvite) {
- return;
- }
- else if (CallManager.isOnCall) {
+ return ;
+ } else if (CallManager.isOnCall) {
CallManager.hangUp();
- }
- else {
+ } else {
CallManager.refreshDevices();
var dialog = placeCallDialog.createObject(timelineRoot);
dialog.open();
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index 3e134b35..e596d8e2 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -226,6 +226,7 @@ Page {
CallInviteBar {
id: callInviteBar
+
Layout.fillWidth: true
z: 3
}
diff --git a/resources/qml/ui/Ripple.qml b/resources/qml/ui/Ripple.qml
new file mode 100644
index 00000000..93380f77
--- /dev/null
+++ b/resources/qml/ui/Ripple.qml
@@ -0,0 +1,177 @@
+import QtGraphicalEffects 1.10
+import QtQuick 2.10
+import QtQuick.Controls 2.3
+
+Item {
+ id: ripple
+
+ property alias clip: backgroundLayer.clip
+ property real radius: 0
+ property color color: "#22000000"
+ property real maxRadius: Math.max(width, height)
+ property real radiusAnimationRate: 0.05
+ property real radiusTailAnimationRate: 0.5
+ property real opacityAnimationDuration: 300
+ readonly property real diameter: radius * 2
+ property real centerX
+ property real centerY
+ property var rippleTarget: parent
+
+ function start() {
+ console.log("Starting ripple animation");
+ ripple.state = "ACTIVE";
+ }
+
+ function stop() {
+ console.log("Stopping ripple animation");
+ ripple.state = "NORMAL";
+ }
+
+ anchors.fill: parent
+ state: "NORMAL"
+ states: [
+ State {
+ name: "NORMAL"
+ },
+ State {
+ name: "ACTIVE"
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "NORMAL"
+ to: "ACTIVE"
+
+ SequentialAnimation {
+ ScriptAction {
+ script: {
+ ripple.opacity = 1;
+ ripple.visible = true;
+ }
+ }
+
+ NumberAnimation {
+ id: radius_animation
+
+ target: ripple
+ properties: "radius"
+ from: 0
+ to: ripple.maxRadius
+ duration: ripple.maxRadius / ripple.radiusAnimationRate
+
+ easing {
+ type: Easing.OutQuad
+ }
+
+ }
+
+ }
+
+ },
+ Transition {
+ from: "ACTIVE"
+ to: "NORMAL"
+
+ SequentialAnimation {
+ ParallelAnimation {
+ NumberAnimation {
+ id: radius_tail_animation
+
+ target: ripple
+ properties: "radius"
+ to: ripple.maxRadius
+ duration: ripple.maxRadius / ripple.radiusTailAnimationRate
+
+ easing {
+ type: Easing.Linear
+ }
+
+ }
+
+ NumberAnimation {
+ id: opacity_animation
+
+ target: ripple
+ properties: "opacity"
+ to: 0
+ duration: ripple.opacityAnimationDuration
+
+ easing {
+ type: Easing.InQuad
+ }
+
+ }
+
+ }
+
+ ScriptAction {
+ script: {
+ ripple.visible = false;
+ }
+ }
+
+ }
+
+ }
+ ]
+
+ Connections {
+ // Button
+ // Default to center
+
+ function onPressed(mouse) {
+ // MouseArea
+ if (mouse) {
+ ripple.centerX = mouse.x;
+ ripple.centerY = mouse.y;
+ } else if (rippleTarget.pressX) {
+ ripple.centerX = rippleTarget.pressX;
+ ripple.centerY = rippleTarget.pressY;
+ } else {
+ ripple.centerX = width / 2;
+ ripple.centerY = height / 2;
+ }
+ ripple.start();
+ }
+
+ function onReleased() {
+ ripple.stop();
+ }
+
+ function onExited() {
+ ripple.stop();
+ }
+
+ function onCanceled() {
+ ripple.stop();
+ }
+
+ function onClicked() {
+ ripple.stop();
+ }
+
+ target: rippleTarget
+ ignoreUnknownSignals: true
+ }
+
+ Rectangle {
+ id: backgroundLayer
+
+ anchors.fill: parent
+ color: "transparent"
+ clip: true
+
+ Rectangle {
+ id: circle
+
+ x: ripple.centerX - ripple.radius
+ y: ripple.centerY - ripple.radius
+ height: ripple.diameter
+ width: ripple.diameter
+ radius: ripple.radius
+ color: ripple.color
+ }
+
+ }
+
+}
diff --git a/resources/qml/ui/qmldir b/resources/qml/ui/qmldir
new file mode 100644
index 00000000..a8466a10
--- /dev/null
+++ b/resources/qml/ui/qmldir
@@ -0,0 +1,2 @@
+module im.nheko.UI
+Ripple 1.0 Ripple.qml
\ No newline at end of file
diff --git a/resources/qml/voip/ActiveCallBar.qml b/resources/qml/voip/ActiveCallBar.qml
index 0e932e13..85da4e3c 100644
--- a/resources/qml/voip/ActiveCallBar.qml
+++ b/resources/qml/voip/ActiveCallBar.qml
@@ -5,7 +5,6 @@ import QtQuick.Layouts 1.2
import im.nheko 1.0
Rectangle {
-
visible: CallManager.isOnCall
color: callInviteBar.color
implicitHeight: visible ? rowLayout.height + 8 : 0
@@ -175,5 +174,7 @@ Rectangle {
ToolTip.text: CallManager.isMicMuted ? qsTr("Unmute Mic") : qsTr("Mute Mic")
onClicked: CallManager.toggleMicMute()
}
+
}
+
}
diff --git a/resources/qml/voip/CallDevices.qml b/resources/qml/voip/CallDevices.qml
index f0847b14..8b30c540 100644
--- a/resources/qml/voip/CallDevices.qml
+++ b/resources/qml/voip/CallDevices.qml
@@ -4,29 +4,20 @@ import QtQuick.Layouts 1.2
import im.nheko 1.0
Popup {
-
modal: true
anchors.centerIn: parent
- background: Rectangle {
- color: colors.window
- border.color: colors.windowText
- }
-
palette: colors
ColumnLayout {
-
spacing: 16
ColumnLayout {
spacing: 8
-
Layout.topMargin: 8
Layout.leftMargin: 8
Layout.rightMargin: 8
RowLayout {
-
Image {
Layout.preferredWidth: 22
Layout.preferredHeight: 22
@@ -35,13 +26,14 @@ Popup {
ComboBox {
id: micCombo
+
Layout.fillWidth: true
model: CallManager.mics
}
+
}
RowLayout {
-
visible: CallManager.isVideo && CallManager.cameras.length > 0
Image {
@@ -52,28 +44,35 @@ Popup {
ComboBox {
id: cameraCombo
+
Layout.fillWidth: true
model: CallManager.cameras
}
+
}
+
}
DialogButtonBox {
-
Layout.leftMargin: 128
standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
+ onAccepted: {
+ Settings.microphone = micCombo.currentText;
+ if (cameraCombo.visible)
+ Settings.camera = cameraCombo.currentText;
- onAccepted: {
- Settings.microphone = micCombo.currentText
- if (cameraCombo.visible) {
- Settings.camera = cameraCombo.currentText
- }
close();
}
-
onRejected: {
close();
}
}
+
}
+
+ background: Rectangle {
+ color: colors.window
+ border.color: colors.windowText
+ }
+
}
diff --git a/resources/qml/voip/CallInviteBar.qml b/resources/qml/voip/CallInviteBar.qml
index 5021949a..e349332f 100644
--- a/resources/qml/voip/CallInviteBar.qml
+++ b/resources/qml/voip/CallInviteBar.qml
@@ -5,21 +5,24 @@ import QtQuick.Layouts 1.2
import im.nheko 1.0
Rectangle {
-
visible: CallManager.haveCallInvite
color: "#2ECC71"
implicitHeight: visible ? rowLayout.height + 8 : 0
Component {
id: devicesDialog
+
CallDevices {
}
+
}
Component {
id: deviceError
+
DeviceError {
}
+
}
RowLayout {
@@ -71,9 +74,9 @@ Rectangle {
ToolTip.visible: hovered
ToolTip.text: qsTr("Devices")
onClicked: {
- CallManager.refreshDevices();
- var dialog = devicesDialog.createObject(timelineRoot);
- dialog.open();
+ CallManager.refreshDevices();
+ var dialog = devicesDialog.createObject(timelineRoot);
+ dialog.open();
}
}
@@ -82,7 +85,6 @@ Rectangle {
icon.source: CallManager.isVideo ? "qrc:/icons/icons/ui/video-call.png" : "qrc:/icons/icons/ui/place-call.png"
text: qsTr(" Accept ")
palette: colors
-
onClicked: {
if (CallManager.mics.length == 0) {
var dialog = deviceError.createObject(timelineRoot, {
@@ -90,15 +92,14 @@ Rectangle {
"image": ":/icons/icons/ui/place-call.png"
});
dialog.open();
- return;
- }
- else if (!CallManager.mics.includes(Settings.microphone)) {
+ return ;
+ } else if (!CallManager.mics.includes(Settings.microphone)) {
var dialog = deviceError.createObject(timelineRoot, {
"errorString": qsTr("Unknown microphone: ") + Settings.microphone,
"image": ":/icons/icons/ui/place-call.png"
});
dialog.open();
- return;
+ return ;
}
if (CallManager.isVideo && CallManager.cameras.length > 0 && !CallManager.cameras.includes(Settings.camera)) {
var dialog = deviceError.createObject(timelineRoot, {
@@ -106,7 +107,7 @@ Rectangle {
"image": ":/icons/icons/ui/video-call.png"
});
dialog.open();
- return;
+ return ;
}
CallManager.acceptInvite();
}
@@ -117,10 +118,11 @@ Rectangle {
icon.source: "qrc:/icons/icons/ui/end-call.png"
text: qsTr(" Decline ")
palette: colors
-
onClicked: {
CallManager.hangUp();
}
}
+
}
+
}
diff --git a/resources/qml/voip/DeviceError.qml b/resources/qml/voip/DeviceError.qml
index a6411b95..81872ef7 100644
--- a/resources/qml/voip/DeviceError.qml
+++ b/resources/qml/voip/DeviceError.qml
@@ -4,19 +4,13 @@ import QtQuick.Layouts 1.2
import im.nheko 1.0
Popup {
-
property string errorString
property var image
modal: true
anchors.centerIn: parent
- background: Rectangle {
- color: colors.window
- border.color: colors.windowText
- }
RowLayout {
-
Image {
Layout.preferredWidth: 16
Layout.preferredHeight: 16
@@ -27,5 +21,12 @@ Popup {
text: errorString
color: colors.windowText
}
+
}
+
+ background: Rectangle {
+ color: colors.window
+ border.color: colors.windowText
+ }
+
}
diff --git a/resources/qml/voip/PlaceCall.qml b/resources/qml/voip/PlaceCall.qml
index 95383d95..65f2f350 100644
--- a/resources/qml/voip/PlaceCall.qml
+++ b/resources/qml/voip/PlaceCall.qml
@@ -5,19 +5,16 @@ import QtQuick.Layouts 1.2
import im.nheko 1.0
Popup {
-
modal: true
anchors.centerIn: parent
palette: colors
- background: Rectangle {
- color: colors.window
- border.color: colors.windowText
- }
Component {
id: deviceError
+
DeviceError {
}
+
}
ColumnLayout {
@@ -26,7 +23,6 @@ Popup {
spacing: 16
RowLayout {
-
Layout.topMargin: 8
Layout.leftMargin: 8
@@ -38,14 +34,12 @@ Popup {
Item {
Layout.fillWidth: true
}
+
}
RowLayout {
id: buttonLayout
- Layout.leftMargin: 8
- Layout.rightMargin: 8
-
function validateMic() {
if (CallManager.mics.length == 0) {
var dialog = deviceError.createObject(timelineRoot, {
@@ -58,6 +52,9 @@ Popup {
return true;
}
+ Layout.leftMargin: 8
+ Layout.rightMargin: 8
+
Avatar {
Layout.rightMargin: cameraCombo.visible ? 16 : 64
width: avatarSize
@@ -71,7 +68,7 @@ Popup {
icon.source: "qrc:/icons/icons/ui/place-call.png"
onClicked: {
if (buttonLayout.validateMic()) {
- Settings.microphone = micCombo.currentText
+ Settings.microphone = micCombo.currentText;
CallManager.sendInvite(TimelineManager.timeline.roomId(), false);
close();
}
@@ -84,8 +81,8 @@ Popup {
icon.source: "qrc:/icons/icons/ui/video-call.png"
onClicked: {
if (buttonLayout.validateMic()) {
- Settings.microphone = micCombo.currentText
- Settings.camera = cameraCombo.currentText
+ Settings.microphone = micCombo.currentText;
+ Settings.camera = cameraCombo.currentText;
CallManager.sendInvite(TimelineManager.timeline.roomId(), true);
close();
}
@@ -98,13 +95,13 @@ Popup {
close();
}
}
+
}
ColumnLayout {
spacing: 8
RowLayout {
-
Layout.leftMargin: 8
Layout.rightMargin: 8
Layout.bottomMargin: cameraCombo.visible ? 0 : 8
@@ -117,13 +114,14 @@ Popup {
ComboBox {
id: micCombo
+
Layout.fillWidth: true
model: CallManager.mics
}
+
}
RowLayout {
-
visible: CallManager.cameras.length > 0
Layout.leftMargin: 8
Layout.rightMargin: 8
@@ -137,10 +135,20 @@ Popup {
ComboBox {
id: cameraCombo
+
Layout.fillWidth: true
model: CallManager.cameras
}
+
}
+
}
+
}
+
+ background: Rectangle {
+ color: colors.window
+ border.color: colors.windowText
+ }
+
}
|