2020-04-01 15:15:49 -04:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
|
2019-07-13 05:39:01 -04:00
|
|
|
import QtQuick 2.12
|
|
|
|
import QtQuick.Layouts 1.12
|
2019-12-27 09:06:42 -04:00
|
|
|
import Clipboard 0.1
|
2019-12-02 16:29:29 -04:00
|
|
|
import "../../.."
|
2019-12-18 04:53:08 -04:00
|
|
|
import "../../../Base"
|
2020-07-20 00:22:12 -04:00
|
|
|
import "../../../PythonBridge"
|
2019-03-21 23:28:14 -04:00
|
|
|
|
2019-12-17 03:45:00 -04:00
|
|
|
HColumnLayout {
|
2019-07-19 23:07:26 -04:00
|
|
|
id: eventDelegate
|
2019-03-21 23:28:14 -04:00
|
|
|
|
2020-07-20 00:22:12 -04:00
|
|
|
property var hoveredMediaTypeUrl: [] // [] or [mediaType, url, title]
|
2019-09-14 18:33:32 -04:00
|
|
|
|
2020-05-20 03:42:40 -04:00
|
|
|
property var fetchProfilesFuture: null
|
|
|
|
|
2019-07-19 23:07:26 -04:00
|
|
|
// Remember timeline goes from newest message at index 0 to oldest
|
2019-12-17 03:45:00 -04:00
|
|
|
readonly property var previousModel: eventList.model.get(model.index + 1)
|
|
|
|
readonly property var nextModel: eventList.model.get(model.index - 1)
|
|
|
|
readonly property QtObject currentModel: model
|
2019-07-02 23:32:39 -04:00
|
|
|
|
2020-09-01 12:45:55 -04:00
|
|
|
readonly property bool compact: window.settings.compactMode
|
|
|
|
readonly property bool checked: model.id in eventList.checked
|
|
|
|
readonly property bool isOwn: chat.userId === model.sender_id
|
2020-03-29 19:06:13 -03:00
|
|
|
readonly property bool isRedacted: model.event_type === "RedactedEvent"
|
2020-09-01 12:45:55 -04:00
|
|
|
readonly property bool onRight: ! eventList.ownEventsOnLeft && isOwn
|
|
|
|
readonly property bool combine: eventList.canCombine(previousModel, model)
|
2020-09-01 13:22:51 -04:00
|
|
|
readonly property bool asOneLine: eventList.renderEventAsOneLine(model)
|
2020-09-01 12:45:55 -04:00
|
|
|
readonly property bool talkBreak:
|
|
|
|
eventList.canTalkBreak(previousModel, model)
|
|
|
|
readonly property bool dayBreak:
|
|
|
|
eventList.canDayBreak(previousModel, model)
|
2019-03-21 23:28:14 -04:00
|
|
|
|
2019-09-14 18:33:32 -04:00
|
|
|
readonly property int cursorShape:
|
2020-07-20 00:22:12 -04:00
|
|
|
eventContent.hoveredLink || hoveredMediaTypeUrl.length === 3 ?
|
2019-09-14 18:33:32 -04:00
|
|
|
Qt.PointingHandCursor :
|
|
|
|
|
|
|
|
eventContent.hoveredSelectable ? Qt.IBeamCursor :
|
|
|
|
|
|
|
|
Qt.ArrowCursor
|
|
|
|
|
2019-12-17 03:45:00 -04:00
|
|
|
readonly property int separationSpacing:
|
2020-09-01 13:29:27 -04:00
|
|
|
dayBreak ? theme.spacing * 4 :
|
|
|
|
talkBreak ? theme.spacing * 6 :
|
|
|
|
combine ? theme.spacing / (compact ? 4 : 2) :
|
|
|
|
theme.spacing * (compact ? 1 : 2)
|
2019-12-17 03:45:00 -04:00
|
|
|
|
2020-03-27 04:49:01 -04:00
|
|
|
readonly property alias eventContent: eventContent
|
|
|
|
|
2019-09-05 16:24:49 -04:00
|
|
|
function json() {
|
2020-02-12 13:04:46 -04:00
|
|
|
let event = ModelStore.get(chat.userId, chat.roomId, "events")
|
2020-03-19 18:49:33 -04:00
|
|
|
.get(model.index)
|
2020-02-12 13:04:46 -04:00
|
|
|
event = JSON.parse(JSON.stringify(event))
|
|
|
|
event.source = JSON.parse(event.source)
|
|
|
|
return JSON.stringify(event, null, 4)
|
2019-09-05 16:24:49 -04:00
|
|
|
}
|
|
|
|
|
2019-09-14 18:52:43 -04:00
|
|
|
function openContextMenu() {
|
|
|
|
contextMenu.media = eventDelegate.hoveredMediaTypeUrl
|
|
|
|
contextMenu.link = eventContent.hoveredLink
|
|
|
|
contextMenu.popup()
|
|
|
|
}
|
|
|
|
|
2020-03-25 23:06:51 -04:00
|
|
|
function toggleChecked() {
|
2020-03-27 05:05:25 -04:00
|
|
|
eventList.toggleCheck(model.index)
|
2020-03-25 23:06:51 -04:00
|
|
|
}
|
|
|
|
|
2019-09-05 16:24:49 -04:00
|
|
|
|
2020-07-12 00:25:57 -04:00
|
|
|
width: eventList.width - eventList.leftMargin - eventList.rightMargin
|
|
|
|
|
|
|
|
// Needed because of eventList's MouseArea which steals the
|
|
|
|
// HSelectableLabel's MouseArea hover events
|
|
|
|
onCursorShapeChanged: eventList.cursorShape = cursorShape
|
|
|
|
|
2020-07-27 04:22:34 -04:00
|
|
|
Component.onCompleted: if (model.fetch_profile)
|
|
|
|
fetchProfilesFuture = py.callClientCoro(
|
|
|
|
chat.userId,
|
|
|
|
"get_event_profiles",
|
|
|
|
[chat.roomId, model.id],
|
|
|
|
() => { fetchProfilesFuture = null }
|
|
|
|
)
|
2020-07-12 00:25:57 -04:00
|
|
|
|
|
|
|
Component.onDestruction:
|
|
|
|
if (fetchProfilesFuture) fetchProfilesFuture.cancel()
|
|
|
|
|
|
|
|
ListView.onRemove: eventList.uncheck(model.id)
|
|
|
|
|
2019-12-17 03:45:00 -04:00
|
|
|
Item {
|
|
|
|
Layout.fillWidth: true
|
2020-07-18 15:02:19 -04:00
|
|
|
visible: model.event_type !== "RoomCreateEvent"
|
|
|
|
Layout.preferredHeight: separationSpacing
|
2019-12-17 03:45:00 -04:00
|
|
|
}
|
|
|
|
|
2019-07-20 02:21:12 -04:00
|
|
|
Daybreak {
|
|
|
|
visible: dayBreak
|
2019-12-17 03:45:00 -04:00
|
|
|
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.minimumWidth: parent.width
|
2020-07-18 15:02:19 -04:00
|
|
|
Layout.bottomMargin: separationSpacing
|
2019-07-20 02:27:17 -04:00
|
|
|
}
|
|
|
|
|
2019-07-02 22:29:09 -04:00
|
|
|
EventContent {
|
2019-09-01 19:03:32 -04:00
|
|
|
id: eventContent
|
2019-12-17 03:45:00 -04:00
|
|
|
|
|
|
|
Layout.fillWidth: true
|
2019-09-01 19:03:32 -04:00
|
|
|
|
2019-12-16 04:42:41 -04:00
|
|
|
Behavior on x { HNumberAnimation {} }
|
2019-04-28 14:48:59 -04:00
|
|
|
}
|
2019-09-01 19:03:32 -04:00
|
|
|
|
2020-03-25 23:06:51 -04:00
|
|
|
TapHandler {
|
|
|
|
acceptedButtons: Qt.LeftButton
|
2020-03-26 23:24:37 -04:00
|
|
|
acceptedModifiers: Qt.NoModifier
|
2020-03-25 23:06:51 -04:00
|
|
|
onTapped: toggleChecked()
|
|
|
|
}
|
2019-09-01 19:03:32 -04:00
|
|
|
|
2020-03-26 23:24:37 -04:00
|
|
|
TapHandler {
|
|
|
|
acceptedButtons: Qt.LeftButton
|
|
|
|
acceptedModifiers: Qt.ShiftModifier
|
2020-03-27 05:05:25 -04:00
|
|
|
onTapped: eventList.checkFromLastToHere(model.index)
|
2020-03-26 23:24:37 -04:00
|
|
|
}
|
|
|
|
|
2019-09-01 19:03:32 -04:00
|
|
|
TapHandler {
|
|
|
|
acceptedButtons: Qt.RightButton
|
2020-03-24 19:52:48 +02:00
|
|
|
acceptedPointerTypes: PointerDevice.GenericPointer | PointerDevice.Pen
|
2019-09-14 18:52:43 -04:00
|
|
|
onTapped: openContextMenu()
|
2019-09-01 19:03:32 -04:00
|
|
|
}
|
|
|
|
|
2020-03-24 16:42:41 +02:00
|
|
|
TapHandler {
|
|
|
|
acceptedPointerTypes: PointerDevice.Finger | PointerDevice.Pen
|
|
|
|
onLongPressed: openContextMenu()
|
|
|
|
}
|
|
|
|
|
2019-09-01 19:03:32 -04:00
|
|
|
HMenu {
|
|
|
|
id: contextMenu
|
|
|
|
|
2019-09-14 18:33:32 -04:00
|
|
|
property var media: []
|
2019-09-01 19:03:32 -04:00
|
|
|
property string link: ""
|
|
|
|
|
2020-07-20 00:22:12 -04:00
|
|
|
readonly property bool isEncryptedMedia:
|
|
|
|
Object.keys(JSON.parse(model.media_crypt_dict)).length > 0
|
|
|
|
|
|
|
|
onClosed: {
|
|
|
|
media = []
|
|
|
|
link = ""
|
|
|
|
}
|
|
|
|
|
2020-03-25 23:06:51 -04:00
|
|
|
HMenuItem {
|
|
|
|
icon.name: "toggle-select-message"
|
2020-03-27 07:06:38 -04:00
|
|
|
text: eventDelegate.checked ? qsTr("Deselect") : qsTr("Select")
|
2020-03-25 23:06:51 -04:00
|
|
|
onTriggered: eventDelegate.toggleChecked()
|
|
|
|
}
|
|
|
|
|
|
|
|
HMenuItem {
|
|
|
|
visible: eventList.selectedCount >= 2
|
2020-03-27 07:06:38 -04:00
|
|
|
icon.name: "deselect-all-messages"
|
|
|
|
text: qsTr("Deselect all")
|
2020-03-27 05:05:25 -04:00
|
|
|
onTriggered: eventList.checked = {}
|
2020-03-25 23:06:51 -04:00
|
|
|
}
|
|
|
|
|
2020-03-26 23:24:37 -04:00
|
|
|
HMenuItem {
|
|
|
|
visible: model.index !== 0
|
|
|
|
icon.name: "select-until-here"
|
|
|
|
text: qsTr("Select until here")
|
2020-03-27 05:05:25 -04:00
|
|
|
onTriggered: eventList.checkFromLastToHere(model.index)
|
2020-03-26 23:24:37 -04:00
|
|
|
}
|
|
|
|
|
2020-07-21 01:06:31 -04:00
|
|
|
HMenuItem {
|
|
|
|
icon.name: "open-externally"
|
|
|
|
text: qsTr("Open externally")
|
|
|
|
visible: Boolean(model.media_url)
|
|
|
|
onTriggered: eventList.openMediaExternally(model)
|
|
|
|
}
|
|
|
|
|
2020-07-20 00:22:12 -04:00
|
|
|
HMenuItem {
|
|
|
|
icon.name: "copy-local-path"
|
|
|
|
text: qsTr("Copy local path")
|
2020-07-20 22:58:02 -04:00
|
|
|
visible: Boolean(model.media_local_path)
|
2020-07-20 00:22:12 -04:00
|
|
|
onTriggered:
|
|
|
|
Clipboard.text =
|
2020-07-20 22:58:02 -04:00
|
|
|
model.media_local_path.replace(/^file:\/\//, "")
|
2020-07-20 00:22:12 -04:00
|
|
|
}
|
|
|
|
|
2019-09-03 03:04:57 -04:00
|
|
|
HMenuItem {
|
2019-09-14 18:33:32 -04:00
|
|
|
id: copyMedia
|
2019-09-03 03:04:57 -04:00
|
|
|
icon.name: "copy-link"
|
2019-09-14 18:33:32 -04:00
|
|
|
text:
|
2020-07-20 12:34:32 -04:00
|
|
|
contextMenu.media.length === 0 ||
|
|
|
|
contextMenu.isEncryptedMedia ?
|
2020-07-20 00:22:12 -04:00
|
|
|
"" :
|
2019-09-14 18:33:32 -04:00
|
|
|
|
2020-07-19 20:10:31 -04:00
|
|
|
contextMenu.media[0] === Utils.Media.File ?
|
2019-09-14 18:33:32 -04:00
|
|
|
qsTr("Copy file address") :
|
|
|
|
|
2020-07-19 20:10:31 -04:00
|
|
|
contextMenu.media[0] === Utils.Media.Image ?
|
2019-09-14 18:33:32 -04:00
|
|
|
qsTr("Copy image address") :
|
|
|
|
|
2020-07-19 20:10:31 -04:00
|
|
|
contextMenu.media[0] === Utils.Media.Video ?
|
2019-09-17 23:23:47 -04:00
|
|
|
qsTr("Copy video address") :
|
|
|
|
|
2020-07-20 00:22:12 -04:00
|
|
|
qsTr("Copy audio address")
|
2019-09-14 18:33:32 -04:00
|
|
|
|
|
|
|
visible: Boolean(text)
|
2020-07-20 23:09:28 -04:00
|
|
|
onTriggered: Clipboard.text = model.media_http_url
|
2019-09-03 03:04:57 -04:00
|
|
|
}
|
2019-09-01 19:03:32 -04:00
|
|
|
|
|
|
|
HMenuItem {
|
|
|
|
icon.name: "copy-link"
|
|
|
|
text: qsTr("Copy link address")
|
|
|
|
visible: Boolean(contextMenu.link)
|
2019-10-25 08:42:04 -04:00
|
|
|
onTriggered: Clipboard.text = contextMenu.link
|
2019-09-01 19:03:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
HMenuItem {
|
|
|
|
icon.name: "copy-text"
|
2020-03-26 21:34:51 -04:00
|
|
|
text:
|
2020-07-20 00:22:12 -04:00
|
|
|
eventList.selectedCount ? qsTr("Copy selection") :
|
|
|
|
contextMenu.media.length > 0 ? qsTr("Copy filename") :
|
2020-03-26 21:34:51 -04:00
|
|
|
qsTr("Copy text")
|
|
|
|
|
2020-03-25 23:06:51 -04:00
|
|
|
onTriggered: {
|
2020-07-20 12:31:40 -04:00
|
|
|
if (! eventList.selectedCount){
|
2020-03-25 23:06:51 -04:00
|
|
|
Clipboard.text = JSON.parse(model.source).body
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-03-26 21:23:43 -04:00
|
|
|
eventList.copySelectedDelegates()
|
2020-03-25 23:06:51 -04:00
|
|
|
}
|
2019-09-01 19:03:32 -04:00
|
|
|
}
|
2019-09-05 16:09:04 -04:00
|
|
|
|
2020-05-20 05:19:06 -04:00
|
|
|
HMenuItem {
|
|
|
|
icon.name: "reply-to"
|
|
|
|
text: qsTr("Reply")
|
|
|
|
|
|
|
|
onTriggered: {
|
2020-05-20 06:17:14 -04:00
|
|
|
chat.replyToEventId = model.id
|
2020-05-20 05:19:06 -04:00
|
|
|
chat.replyToUserId = model.sender_id
|
|
|
|
chat.replyToDisplayName = model.sender_name
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-26 17:31:57 -03:00
|
|
|
HMenuItemPopupSpawner {
|
2020-07-12 00:25:57 -04:00
|
|
|
readonly property var events: {
|
|
|
|
eventList.selectedCount ?
|
|
|
|
eventList.redactableCheckedEvents :
|
|
|
|
|
|
|
|
eventList.canRedact(currentModel) ?
|
|
|
|
[model] :
|
|
|
|
|
|
|
|
[]
|
|
|
|
}
|
|
|
|
|
2020-03-26 17:31:57 -03:00
|
|
|
icon.name: "remove-message"
|
|
|
|
text: qsTr("Remove")
|
2020-04-03 06:13:45 -04:00
|
|
|
enabled: properties.eventSenderAndIds.length
|
2020-03-26 17:31:57 -03:00
|
|
|
|
2020-04-01 15:15:49 -04:00
|
|
|
popup: "Popups/RedactPopup.qml"
|
2020-03-26 17:31:57 -03:00
|
|
|
properties: ({
|
2020-04-03 06:13:45 -04:00
|
|
|
preferUserId: chat.userId,
|
2020-03-26 17:31:57 -03:00
|
|
|
roomId: chat.roomId,
|
2020-04-03 06:50:24 -04:00
|
|
|
eventSenderAndIds: events.map(ev => [ev.sender_id, ev.id]),
|
2020-04-01 15:15:49 -04:00
|
|
|
|
|
|
|
onlyOwnMessageWarning:
|
|
|
|
! chat.roomInfo.can_redact_all &&
|
2020-04-02 10:19:43 -04:00
|
|
|
events.length < eventList.selectedCount
|
2020-03-26 17:31:57 -03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-12-20 10:39:10 -04:00
|
|
|
HMenuItem {
|
|
|
|
icon.name: "debug"
|
|
|
|
text: qsTr("Debug this event")
|
2020-04-01 05:37:44 -04:00
|
|
|
onTriggered:
|
|
|
|
mainUI.debugConsole.toggle(eventContent, "t.parent.json()")
|
2019-12-20 10:39:10 -04:00
|
|
|
}
|
|
|
|
|
2019-12-20 10:29:45 -04:00
|
|
|
HMenuItemPopupSpawner {
|
2019-09-08 11:40:39 -04:00
|
|
|
icon.name: "clear-messages"
|
|
|
|
text: qsTr("Clear messages")
|
2019-12-20 10:29:45 -04:00
|
|
|
|
|
|
|
popup: "Popups/ClearMessagesPopup.qml"
|
2020-06-26 06:09:20 -04:00
|
|
|
properties: ({
|
|
|
|
userId: chat.userId,
|
|
|
|
roomId: chat.roomId,
|
|
|
|
preClearCallback: eventList.uncheckAll,
|
|
|
|
})
|
2019-09-08 11:40:39 -04:00
|
|
|
}
|
2019-09-01 19:03:32 -04:00
|
|
|
}
|
2019-03-21 23:28:14 -04:00
|
|
|
}
|