nheko/resources/qml/TimelineView.qml

379 lines
11 KiB
QML
Raw Normal View History

2021-03-05 00:35:15 +01:00
// SPDX-FileCopyrightText: 2021 Nheko Contributors
2021-03-14 02:45:20 +01:00
//
2021-03-05 00:35:15 +01:00
// SPDX-License-Identifier: GPL-3.0-or-later
2020-10-08 21:11:21 +02:00
import "./delegates"
import "./device-verification"
import "./emoji"
2020-12-17 17:25:32 +01:00
import "./voip"
2021-03-14 22:22:52 +01:00
import Qt.labs.platform 1.1 as Platform
2020-10-08 21:11:21 +02:00
import QtGraphicalEffects 1.0
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Window 2.2
import im.nheko 1.0
2020-05-14 02:19:15 +02:00
import im.nheko.EmojiModel 1.0
Page {
2020-10-08 21:11:21 +02:00
id: timelineRoot
2021-05-13 08:23:56 +02:00
palette: Nheko.colors
2020-10-08 21:11:21 +02:00
FontMetrics {
id: fontMetrics
}
EmojiPicker {
id: emojiPopup
colors: palette
model: TimelineManager.completerFor("allemoji", "")
2020-10-08 21:11:21 +02:00
}
Component {
id: userProfileComponent
UserProfile {
}
}
2021-02-09 18:41:39 +01:00
Component {
id: roomSettingsComponent
RoomSettings {
}
}
2021-01-12 20:22:52 +01:00
Component {
id: mobileCallInviteDialog
CallInvite {
}
2021-01-17 04:05:02 +01:00
2021-01-12 20:22:52 +01:00
}
Component {
id: quickSwitcherComponent
QuickSwitcher {
}
}
2021-04-11 16:31:49 +02:00
Component {
2021-04-13 19:01:49 +02:00
id: forwardCompleterComponent
2021-04-11 16:31:49 +02:00
2021-04-13 19:01:49 +02:00
ForwardCompleter {
2021-04-11 16:31:49 +02:00
}
2021-04-27 11:08:21 +02:00
2021-04-11 16:31:49 +02:00
}
Shortcut {
2021-02-24 15:20:36 +01:00
sequence: "Ctrl+K"
onActivated: {
var quickSwitch = quickSwitcherComponent.createObject(timelineRoot);
TimelineManager.focusTimeline();
quickSwitch.open();
}
}
2021-03-14 22:22:52 +01:00
Platform.Menu {
2020-10-08 21:11:21 +02:00
id: messageContextMenu
property string eventId
2021-04-29 23:09:13 +02:00
property string link
property string text
2020-10-08 21:11:21 +02:00
property int eventType
property bool isEncrypted
2021-04-11 22:24:39 +02:00
property bool isEditable
property bool isSender
2020-10-08 21:11:21 +02:00
function show(eventId_, eventType_, isSender_, isEncrypted_, isEditable_, link_, text_, showAt_) {
2020-10-08 21:11:21 +02:00
eventId = eventId_;
eventType = eventType_;
isEncrypted = isEncrypted_;
2021-04-11 22:24:39 +02:00
isEditable = isEditable_;
isSender = isSender_;
if (text_)
text = text_;
else
text = "";
2021-04-29 23:09:13 +02:00
if (link_)
link = link_;
else
link = "";
2021-03-14 22:22:52 +01:00
if (showAt_)
open(showAt_);
else
open();
2020-10-08 21:11:21 +02:00
}
Platform.MenuItem {
visible: messageContextMenu.text
enabled: visible
text: qsTr("Copy")
onTriggered: Clipboard.text = messageContextMenu.text
}
2021-04-29 23:09:13 +02:00
Platform.MenuItem {
visible: messageContextMenu.link
enabled: visible
text: qsTr("Copy link location")
2021-04-29 23:09:13 +02:00
onTriggered: Clipboard.text = messageContextMenu.link
}
2021-04-11 22:24:39 +02:00
Platform.MenuItem {
id: reactionOption
visible: TimelineManager.timeline ? TimelineManager.timeline.permissions.canSend(MtxEvent.Reaction) : false
2020-10-08 21:11:21 +02:00
text: qsTr("React")
onTriggered: emojiPopup.show(null, function(emoji) {
2020-11-16 18:41:29 +01:00
TimelineManager.queueReactionMessage(messageContextMenu.eventId, emoji);
})
2020-10-08 21:11:21 +02:00
}
2021-03-14 22:22:52 +01:00
Platform.MenuItem {
visible: TimelineManager.timeline ? TimelineManager.timeline.permissions.canSend(MtxEvent.TextMessage) : false
2020-10-08 21:11:21 +02:00
text: qsTr("Reply")
2021-03-14 22:22:52 +01:00
onTriggered: TimelineManager.timeline.replyAction(messageContextMenu.eventId)
2020-10-08 21:11:21 +02:00
}
2021-03-14 22:22:52 +01:00
Platform.MenuItem {
visible: messageContextMenu.isEditable && (TimelineManager.timeline ? TimelineManager.timeline.permissions.canSend(MtxEvent.TextMessage) : false)
2021-03-14 22:22:52 +01:00
enabled: visible
text: qsTr("Edit")
2021-03-14 22:22:52 +01:00
onTriggered: TimelineManager.timeline.editAction(messageContextMenu.eventId)
}
2021-03-14 22:22:52 +01:00
Platform.MenuItem {
2020-10-08 21:11:21 +02:00
text: qsTr("Read receipts")
2020-10-26 21:44:31 +01:00
onTriggered: TimelineManager.timeline.readReceiptsAction(messageContextMenu.eventId)
2020-10-08 21:11:21 +02:00
}
2021-04-11 16:31:49 +02:00
Platform.MenuItem {
2021-04-27 11:08:21 +02:00
visible: messageContextMenu.eventType == MtxEvent.ImageMessage || messageContextMenu.eventType == MtxEvent.VideoMessage || messageContextMenu.eventType == MtxEvent.AudioMessage || messageContextMenu.eventType == MtxEvent.FileMessage || messageContextMenu.eventType == MtxEvent.Sticker || messageContextMenu.eventType == MtxEvent.TextMessage || messageContextMenu.eventType == MtxEvent.LocationMessage || messageContextMenu.eventType == MtxEvent.EmoteMessage || messageContextMenu.eventType == MtxEvent.NoticeMessage
2021-04-11 16:31:49 +02:00
text: qsTr("Forward")
onTriggered: {
2021-04-13 19:01:49 +02:00
var forwardMess = forwardCompleterComponent.createObject(timelineRoot);
forwardMess.setMessageEventId(messageContextMenu.eventId);
2021-04-11 16:31:49 +02:00
forwardMess.open();
}
}
2021-03-14 22:22:52 +01:00
Platform.MenuItem {
2020-10-08 21:11:21 +02:00
text: qsTr("Mark as read")
}
2021-03-14 22:22:52 +01:00
Platform.MenuItem {
2020-10-08 21:11:21 +02:00
text: qsTr("View raw message")
2020-10-26 21:44:31 +01:00
onTriggered: TimelineManager.timeline.viewRawMessage(messageContextMenu.eventId)
2020-10-08 21:11:21 +02:00
}
2021-03-14 22:22:52 +01:00
Platform.MenuItem {
// TODO(Nico): Fix this still being iterated over, when using keyboard to select options
2020-10-08 21:11:21 +02:00
visible: messageContextMenu.isEncrypted
2021-03-14 22:22:52 +01:00
enabled: visible
2020-10-08 21:11:21 +02:00
text: qsTr("View decrypted raw message")
2020-10-26 21:44:31 +01:00
onTriggered: TimelineManager.timeline.viewDecryptedRawMessage(messageContextMenu.eventId)
2020-10-08 21:11:21 +02:00
}
2021-03-14 22:22:52 +01:00
Platform.MenuItem {
visible: (TimelineManager.timeline ? TimelineManager.timeline.permissions.canRedact() : false) || messageContextMenu.isSender
2020-11-26 09:50:37 +01:00
text: qsTr("Remove message")
2020-10-26 21:44:31 +01:00
onTriggered: TimelineManager.timeline.redactEvent(messageContextMenu.eventId)
2020-10-08 21:11:21 +02:00
}
2021-03-14 22:22:52 +01:00
Platform.MenuItem {
2020-10-08 21:11:21 +02:00
visible: messageContextMenu.eventType == MtxEvent.ImageMessage || messageContextMenu.eventType == MtxEvent.VideoMessage || messageContextMenu.eventType == MtxEvent.AudioMessage || messageContextMenu.eventType == MtxEvent.FileMessage || messageContextMenu.eventType == MtxEvent.Sticker
2021-03-14 22:22:52 +01:00
enabled: visible
2020-10-08 21:11:21 +02:00
text: qsTr("Save as")
onTriggered: TimelineManager.timeline.saveMedia(messageContextMenu.eventId)
}
2021-03-14 22:22:52 +01:00
Platform.MenuItem {
2021-01-24 01:29:30 +01:00
visible: messageContextMenu.eventType == MtxEvent.ImageMessage || messageContextMenu.eventType == MtxEvent.VideoMessage || messageContextMenu.eventType == MtxEvent.AudioMessage || messageContextMenu.eventType == MtxEvent.FileMessage || messageContextMenu.eventType == MtxEvent.Sticker
2021-03-14 22:22:52 +01:00
enabled: visible
2021-01-24 01:29:30 +01:00
text: qsTr("Open in external program")
onTriggered: TimelineManager.timeline.openMedia(messageContextMenu.eventId)
2021-04-29 23:09:13 +02:00
}
2021-04-29 21:46:49 +02:00
Platform.MenuItem {
visible: messageContextMenu.eventId
enabled: visible
text: qsTr("Copy link to event")
onTriggered: TimelineManager.timeline.copyLinkToEvent(messageContextMenu.eventId)
2021-01-24 01:29:30 +01:00
}
2020-10-08 21:11:21 +02:00
}
Rectangle {
anchors.fill: parent
2021-05-13 08:23:56 +02:00
color: Nheko.colors.window
2020-10-08 21:11:21 +02:00
Component {
id: deviceVerificationDialog
DeviceVerification {
}
}
Connections {
2020-11-14 22:38:17 +01:00
target: TimelineManager
onNewDeviceVerificationRequest: {
2020-10-08 21:11:21 +02:00
var dialog = deviceVerificationDialog.createObject(timelineRoot, {
"flow": flow
});
dialog.show();
}
2020-11-14 22:38:17 +01:00
onOpenProfile: {
2020-10-08 21:11:21 +02:00
var userProfile = userProfileComponent.createObject(timelineRoot, {
"profile": profile
});
userProfile.show();
}
}
2021-02-09 18:41:39 +01:00
Connections {
2021-02-11 19:20:45 +01:00
target: TimelineManager.timeline
2021-02-09 18:41:39 +01:00
onOpenRoomSettingsDialog: {
var roomSettings = roomSettingsComponent.createObject(timelineRoot, {
"roomSettings": settings
});
2021-02-09 18:41:39 +01:00
roomSettings.show();
}
}
2021-01-12 20:22:52 +01:00
Connections {
target: CallManager
onNewInviteState: {
if (CallManager.haveCallInvite && Settings.mobileMode) {
var dialog = mobileCallInviteDialog.createObject(msgView);
dialog.open();
}
}
}
2020-10-08 21:11:21 +02:00
Label {
visible: !TimelineManager.timeline && !TimelineManager.isInitialSync
anchors.centerIn: parent
text: qsTr("No room open")
font.pointSize: 24
2021-05-13 08:23:56 +02:00
color: Nheko.colors.text
2020-10-08 21:11:21 +02:00
}
BusyIndicator {
visible: running
anchors.centerIn: parent
running: TimelineManager.isInitialSync
height: 200
width: 200
z: 3
}
ColumnLayout {
id: timelineLayout
2021-01-26 06:03:09 +01:00
2020-10-18 22:30:42 +02:00
visible: TimelineManager.timeline != null
2020-10-08 21:11:21 +02:00
anchors.fill: parent
2020-10-26 13:50:44 +01:00
spacing: 0
2020-10-08 21:11:21 +02:00
TopBar {
2020-10-08 21:11:21 +02:00
}
2020-10-26 13:50:44 +01:00
Rectangle {
2020-10-08 21:11:21 +02:00
Layout.fillWidth: true
2020-10-26 13:50:44 +01:00
height: 1
2020-10-08 21:11:21 +02:00
z: 3
2021-05-13 08:23:56 +02:00
color: Nheko.colors.mid
2020-10-08 21:11:21 +02:00
}
2020-10-26 13:50:44 +01:00
Rectangle {
2021-01-12 20:22:52 +01:00
id: msgView
2021-01-17 04:05:02 +01:00
2020-10-08 21:11:21 +02:00
Layout.fillWidth: true
Layout.fillHeight: true
2021-05-13 08:23:56 +02:00
color: Nheko.colors.base
2020-10-27 18:14:06 +01:00
ColumnLayout {
2020-10-26 13:50:44 +01:00
anchors.fill: parent
spacing: 0
2020-10-27 18:14:06 +01:00
StackLayout {
id: stackLayout
2020-11-15 04:52:49 +01:00
currentIndex: 0
2020-10-08 21:11:21 +02:00
Connections {
function onActiveTimelineChanged() {
stackLayout.currentIndex = 0;
2020-10-08 21:11:21 +02:00
}
2020-11-15 04:52:49 +01:00
target: TimelineManager
2020-10-08 21:11:21 +02:00
}
MessageView {
Layout.fillWidth: true
Layout.fillHeight: true
2020-10-08 21:11:21 +02:00
}
Loader {
2021-02-21 22:30:10 +01:00
source: CallManager.isOnCall && CallManager.callType != CallType.VOICE ? "voip/VideoCall.qml" : ""
onLoaded: TimelineManager.setVideoCallItem()
2020-10-27 18:14:06 +01:00
}
2020-11-15 04:52:49 +01:00
2020-10-08 21:11:21 +02:00
}
TypingIndicator {
2020-10-27 18:14:06 +01:00
}
2020-10-08 21:11:21 +02:00
}
}
2020-12-17 17:25:32 +01:00
CallInviteBar {
id: callInviteBar
2021-01-11 23:51:39 +01:00
2020-12-17 17:25:32 +01:00
Layout.fillWidth: true
z: 3
}
2020-10-08 21:11:21 +02:00
ActiveCallBar {
Layout.fillWidth: true
z: 3
}
2020-10-26 13:50:44 +01:00
Rectangle {
2020-10-08 21:11:21 +02:00
Layout.fillWidth: true
z: 3
2020-10-26 13:50:44 +01:00
height: 1
2021-05-13 08:23:56 +02:00
color: Nheko.colors.mid
2020-10-08 21:11:21 +02:00
}
ReplyPopup {
}
2020-10-26 13:50:44 +01:00
2020-10-31 23:24:07 +01:00
MessageInput {
}
2021-02-03 01:30:03 +01:00
}
2020-10-26 13:50:44 +01:00
2021-02-03 01:30:03 +01:00
NhekoDropArea {
anchors.fill: parent
2021-02-03 01:30:03 +01:00
roomid: TimelineManager.timeline ? TimelineManager.timeline.roomId() : ""
2020-10-08 21:11:21 +02:00
}
}
PrivacyScreen {
anchors.fill: parent
visible: Settings.privacyScreen
screenTimeout: Settings.privacyScreenTimeout
timelineRoot: timelineLayout
2020-10-08 21:11:21 +02:00
}
2019-08-30 19:29:25 +02:00
}