diff options
author | trilene <trilene@runbox.com> | 2020-10-27 13:14:06 -0400 |
---|---|---|
committer | trilene <trilene@runbox.com> | 2020-10-27 13:14:06 -0400 |
commit | d1f3a3ef40a69fe50efe6e2b76400e7f5f5dfb6c (patch) | |
tree | 1d5eb5645f0aa410ddc22050d3bfb7459989e727 /resources/qml | |
parent | Merge branch 'master' of ssh://github.com/Nheko-Reborn/nheko (diff) | |
download | nheko-d1f3a3ef40a69fe50efe6e2b76400e7f5f5dfb6c.tar.xz |
Support video calls
Diffstat (limited to 'resources/qml')
-rw-r--r-- | resources/qml/ActiveCallBar.qml | 12 | ||||
-rw-r--r-- | resources/qml/TimelineView.qml | 330 | ||||
-rw-r--r-- | resources/qml/VideoCall.qml | 7 |
3 files changed, 192 insertions, 157 deletions
diff --git a/resources/qml/ActiveCallBar.qml b/resources/qml/ActiveCallBar.qml index 9344738e..49b5d059 100644 --- a/resources/qml/ActiveCallBar.qml +++ b/resources/qml/ActiveCallBar.qml @@ -10,6 +10,12 @@ Rectangle { color: "#2ECC71" implicitHeight: rowLayout.height + 8 + MouseArea { + anchors.fill: parent + onClicked: if (TimelineManager.onVideoCall) + stackLayout.currentIndex = stackLayout.currentIndex ? 0 : 1; + } + RowLayout { id: rowLayout @@ -33,7 +39,8 @@ Rectangle { Image { Layout.preferredWidth: 24 Layout.preferredHeight: 24 - source: "qrc:/icons/icons/ui/place-call.png" + source: TimelineManager.onVideoCall ? + "qrc:/icons/icons/ui/video-call.png" : "qrc:/icons/icons/ui/place-call.png" } Label { @@ -58,9 +65,12 @@ Rectangle { callStateLabel.text = "00:00"; var d = new Date(); callTimer.startTime = Math.floor(d.getTime() / 1000); + if (TimelineManager.onVideoCall) + stackLayout.currentIndex = 1; break; case WebRTCState.DISCONNECTED: callStateLabel.text = ""; + stackLayout.currentIndex = 0; } } diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index ab0148e9..d69d5568 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -4,7 +4,7 @@ import "./emoji" import QtGraphicalEffects 1.0 import QtQuick 2.9 import QtQuick.Controls 2.3 -import QtQuick.Layouts 1.2 +import QtQuick.Layouts 1.3 import QtQuick.Window 2.2 import im.nheko 1.0 import im.nheko.EmojiModel 1.0 @@ -282,144 +282,157 @@ Page { } - ListView { - id: chat + StackLayout { + id: stackLayout + currentIndex: 0 - property int delegateMaxWidth: (Settings.timelineMaxWidth > 100 && (parent.width - Settings.timelineMaxWidth) > scrollbar.width * 2) ? Settings.timelineMaxWidth : (parent.width - scrollbar.width * 2) - - visible: TimelineManager.timeline != null - cacheBuffer: 400 - Layout.fillWidth: true - Layout.fillHeight: true - model: TimelineManager.timeline - boundsBehavior: Flickable.StopAtBounds - pixelAligned: true - spacing: 4 - verticalLayoutDirection: ListView.BottomToTop - onCountChanged: { - if (atYEnd) - model.currentIndex = 0; - - } // Mark last event as read, since we are at the bottom - - ScrollHelper { - flickable: parent - anchors.fill: parent - } - - Shortcut { - sequence: StandardKey.MoveToPreviousPage - onActivated: { - chat.contentY = chat.contentY - chat.height / 2; - chat.returnToBounds(); + Connections { + target: TimelineManager + function onActiveTimelineChanged() { + stackLayout.currentIndex = 0; } } - Shortcut { - sequence: StandardKey.MoveToNextPage - onActivated: { - chat.contentY = chat.contentY + chat.height / 2; - chat.returnToBounds(); + ListView { + id: chat + + property int delegateMaxWidth: (Settings.timelineMaxWidth > 100 && (parent.width - Settings.timelineMaxWidth) > scrollbar.width * 2) ? Settings.timelineMaxWidth : (parent.width - scrollbar.width * 2) + + visible: TimelineManager.timeline != null + cacheBuffer: 400 + Layout.fillWidth: true + Layout.fillHeight: true + model: TimelineManager.timeline + boundsBehavior: Flickable.StopAtBounds + pixelAligned: true + spacing: 4 + verticalLayoutDirection: ListView.BottomToTop + onCountChanged: { + if (atYEnd) + model.currentIndex = 0; + + } // Mark last event as read, since we are at the bottom + + ScrollHelper { + flickable: parent + anchors.fill: parent } - } - Shortcut { - sequence: StandardKey.Cancel - onActivated: chat.model.reply = undefined - } + Shortcut { + sequence: StandardKey.MoveToPreviousPage + onActivated: { + chat.contentY = chat.contentY - chat.height / 2; + chat.returnToBounds(); + } + } - Shortcut { - sequence: "Alt+Up" - onActivated: chat.model.reply = chat.model.indexToId(chat.model.reply ? chat.model.idToIndex(chat.model.reply) + 1 : 0) - } + Shortcut { + sequence: StandardKey.MoveToNextPage + onActivated: { + chat.contentY = chat.contentY + chat.height / 2; + chat.returnToBounds(); + } + } - Shortcut { - sequence: "Alt+Down" - onActivated: { - var idx = chat.model.reply ? chat.model.idToIndex(chat.model.reply) - 1 : -1; - chat.model.reply = idx >= 0 ? chat.model.indexToId(idx) : undefined; + Shortcut { + sequence: StandardKey.Cancel + onActivated: chat.model.reply = undefined } - } - Component { - id: userProfileComponent + Shortcut { + sequence: "Alt+Up" + onActivated: chat.model.reply = chat.model.indexToId(chat.model.reply ? chat.model.idToIndex(chat.model.reply) + 1 : 0) + } - UserProfile { + Shortcut { + sequence: "Alt+Down" + onActivated: { + var idx = chat.model.reply ? chat.model.idToIndex(chat.model.reply) - 1 : -1; + chat.model.reply = idx >= 0 ? chat.model.indexToId(idx) : undefined; + } } - } + Component { + id: userProfileComponent - section { - property: "section" - } + UserProfile { + } - Component { - id: sectionHeader + } - Column { - property var modelData - property string section - property string nextSection + section { + property: "section" + } - topPadding: 4 - bottomPadding: 4 - spacing: 8 - visible: !!modelData - width: parent.width - height: (section.includes(" ") ? dateBubble.height + 8 + userName.height : userName.height) + 8 + Component { + id: sectionHeader - Label { - id: dateBubble + Column { + property var modelData + property string section + property string nextSection + + topPadding: 4 + bottomPadding: 4 + spacing: 8 + visible: !!modelData + width: parent.width + height: (section.includes(" ") ? dateBubble.height + 8 + userName.height : userName.height) + 8 + + Label { + id: dateBubble + + anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined + visible: section.includes(" ") + text: chat.model.formatDateSeparator(modelData.timestamp) + color: colors.text + height: fontMetrics.height * 1.4 + width: contentWidth * 1.2 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + background: Rectangle { + radius: parent.height / 2 + color: colors.base + } - anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined - visible: section.includes(" ") - text: chat.model.formatDateSeparator(modelData.timestamp) - color: colors.text - height: fontMetrics.height * 1.4 - width: contentWidth * 1.2 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - background: Rectangle { - radius: parent.height / 2 - color: colors.base } - } + Row { + height: userName.height + spacing: 8 - Row { - height: userName.height - spacing: 8 + Avatar { + width: avatarSize + height: avatarSize + url: chat.model.avatarUrl(modelData.userId).replace("mxc://", "image://MxcImage/") + displayName: modelData.userName + userid: modelData.userId + + MouseArea { + anchors.fill: parent + onClicked: chat.model.openUserProfile(modelData.userId) + cursorShape: Qt.PointingHandCursor + propagateComposedEvents: true + } - Avatar { - width: avatarSize - height: avatarSize - url: chat.model.avatarUrl(modelData.userId).replace("mxc://", "image://MxcImage/") - displayName: modelData.userName - userid: modelData.userId - - MouseArea { - anchors.fill: parent - onClicked: chat.model.openUserProfile(modelData.userId) - cursorShape: Qt.PointingHandCursor - propagateComposedEvents: true } - } + Label { + id: userName + + text: TimelineManager.escapeEmoji(modelData.userName) + color: TimelineManager.userColor(modelData.userId, colors.window) + textFormat: Text.RichText + + MouseArea { + anchors.fill: parent + Layout.alignment: Qt.AlignHCenter + onClicked: chat.model.openUserProfile(modelData.userId) + cursorShape: Qt.PointingHandCursor + propagateComposedEvents: true + } - Label { - id: userName - - text: TimelineManager.escapeEmoji(modelData.userName) - color: TimelineManager.userColor(modelData.userId, colors.window) - textFormat: Text.RichText - - MouseArea { - anchors.fill: parent - Layout.alignment: Qt.AlignHCenter - onClicked: chat.model.openUserProfile(modelData.userId) - cursorShape: Qt.PointingHandCursor - propagateComposedEvents: true } } @@ -428,62 +441,67 @@ Page { } - } - - ScrollBar.vertical: ScrollBar { - id: scrollbar - } + ScrollBar.vertical: ScrollBar { + id: scrollbar + } - delegate: Item { - id: wrapper - - // This would normally be previousSection, but our model's order is inverted. - property bool sectionBoundary: (ListView.nextSection != "" && ListView.nextSection !== ListView.section) || model.index === chat.count - 1 - property Item section - - anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined - width: chat.delegateMaxWidth - height: section ? section.height + timelinerow.height : timelinerow.height - onSectionBoundaryChanged: { - if (sectionBoundary) { - var properties = { - "modelData": model.dump, - "section": ListView.section, - "nextSection": ListView.nextSection - }; - section = sectionHeader.createObject(wrapper, properties); - } else { - section.destroy(); - section = null; + delegate: Item { + id: wrapper + + // This would normally be previousSection, but our model's order is inverted. + property bool sectionBoundary: (ListView.nextSection != "" && ListView.nextSection !== ListView.section) || model.index === chat.count - 1 + property Item section + + anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined + width: chat.delegateMaxWidth + height: section ? section.height + timelinerow.height : timelinerow.height + onSectionBoundaryChanged: { + if (sectionBoundary) { + var properties = { + "modelData": model.dump, + "section": ListView.section, + "nextSection": ListView.nextSection + }; + section = sectionHeader.createObject(wrapper, properties); + } else { + section.destroy(); + section = null; + } } - } - TimelineRow { - id: timelinerow + TimelineRow { + id: timelinerow - y: section ? section.y + section.height : 0 - } + y: section ? section.y + section.height : 0 + } - Connections { - function onMovementEnded() { - if (y + height + 2 * chat.spacing > chat.contentY + chat.height && y < chat.contentY + chat.height) - chat.model.currentIndex = index; + Connections { + function onMovementEnded() { + if (y + height + 2 * chat.spacing > chat.contentY + chat.height && y < chat.contentY + chat.height) + chat.model.currentIndex = index; + } + + target: chat } - target: chat } - } + footer: BusyIndicator { + anchors.horizontalCenter: parent.horizontalCenter + running: chat.model && chat.model.paginationInProgress + height: 50 + width: 50 + z: 3 + } - footer: BusyIndicator { - anchors.horizontalCenter: parent.horizontalCenter - running: chat.model && chat.model.paginationInProgress - height: 50 - width: 50 - z: 3 } + Loader { + id: videoCallLoader + source: TimelineManager.onVideoCall ? "VideoCall.qml" : "" + onLoaded: TimelineManager.setVideoCallItem() + } } Item { diff --git a/resources/qml/VideoCall.qml b/resources/qml/VideoCall.qml new file mode 100644 index 00000000..69fc1a2b --- /dev/null +++ b/resources/qml/VideoCall.qml @@ -0,0 +1,7 @@ +import QtQuick 2.9 + +import org.freedesktop.gstreamer.GLVideoItem 1.0 + +GstGLVideoItem { + objectName: "videoCallItem" +} |