Newer
Older
// SPDX-FileCopyrightText: 2021 Nheko Contributors
// SPDX-FileCopyrightText: 2022 Nheko Contributors
import "./delegates"
import "./device-verification"
import "./emoji"
import QtQuick 2.15
import QtQuick.Layouts 1.3
import QtQuick.Window 2.13
import im.nheko 1.0
Item {
id: timelineView
onRoomChanged: if (room != null) room.triggerSpecialEffects()
// focus message input on key press, but not on Ctrl-C and such.
Keys.onPressed: if (event.text && !topBar.searchHasFocus) TimelineManager.focusMessageInput();
Shortcut {
sequence: StandardKey.Close
onActivated: Rooms.resetCurrentRoom()
}
visible: !room && !TimelineManager.isInitialSync && (!roomPreview || !roomPreview.roomid)
anchors.centerIn: parent
text: qsTr("No room open")
font.pointSize: 24
color: Nheko.colors.text
anchors.centerIn: parent
foreground: Nheko.colors.mid
running: TimelineManager.isInitialSync
// height is somewhat arbitrary here... don't set width because width scales w/ height
height: parent.height / 16
opacity: hh.hovered ? 0.3 : 1
Behavior on opacity {
NumberAnimation { duration: 100; }
}
HoverHandler {
id: hh
}
Jedi18
committed
}
ColumnLayout {
id: timelineLayout
visible: room != null && !room.isSpace
enabled: visible
showBackButton: timelineView.showBackButton
Rectangle {
Layout.fillWidth: true
height: 1
Rectangle {
id: msgView
Layout.fillWidth: true
Layout.fillHeight: true
color: Nheko.colors.base
ColumnLayout {
anchors.fill: parent
spacing: 0
StackLayout {
id: stackLayout
currentIndex: 0
function onRoomChanged() {
stackLayout.currentIndex = 0;
MessageView {
implicitHeight: msgView.height - typingIndicator.height
Loader {
source: CallManager.isOnCall && CallManager.callType != CallType.VOICE ? "voip/VideoCall.qml" : ""
onLoaded: TimelineManager.setVideoCallItem()
TypingIndicator {
id: typingIndicator
}
CallInviteBar {
id: callInviteBar
Layout.fillWidth: true
z: 3
}
ActiveCallBar {
Layout.fillWidth: true
z: 3
}
Rectangle {
Layout.fillWidth: true
z: 3
height: 1
UploadBox {
NotificationWarning {
}
MessageInput {
property string roomId: room ? room.roomId : (roomPreview ? roomPreview.roomid : "")
property string roomName: room ? room.roomName : (roomPreview ? roomPreview.roomName : "")
property string roomTopic: room ? room.roomTopic : (roomPreview ? roomPreview.roomTopic : "")
property string avatarUrl: room ? room.roomAvatarUrl : (roomPreview ? roomPreview.roomAvatarUrl : "")
visible: room != null && room.isSpace || roomPreview != null
enabled: visible
anchors.fill: parent
anchors.margins: Nheko.paddingLarge
spacing: Nheko.paddingLarge
Item {
Layout.fillHeight: true
}
url: parent.avatarUrl.replace("mxc://", "image://MxcImage/")
height: 130
width: 130
Layout.alignment: Qt.AlignHCenter
enabled: false
}
RowLayout {
spacing: Nheko.paddingMedium
MatrixText {
text: preview.roomName == "" ? qsTr("No preview available") : preview.roomName
font.pixelSize: 24
}
ImageButton {
image: ":/icons/icons/ui/settings.svg"
visible: !!room
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Settings")
onClicked: TimelineManager.openRoomSettings(room.roomId)
}
spacing: Nheko.paddingMedium
MatrixText {
text: qsTr("%n member(s)", "", room ? room.roomMemberCount : 0)
}
ImageButton {
image: ":/icons/icons/ui/people.svg"
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("View members of %1").arg(room ? room.roomName : "")
onClicked: TimelineManager.openRoomMembers(room)
}
}
ScrollView {
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.leftMargin: Nheko.paddingLarge
Layout.rightMargin: Nheko.paddingLarge
text: TimelineManager.escapeEmoji(preview.roomTopic)
wrapMode: TextEdit.WordWrap
textFormat: TextEdit.RichText
readOnly: true
background: null
selectByMouse: true
color: Nheko.colors.text
horizontalAlignment: TextEdit.AlignHCenter
onLinkActivated: Nheko.openLink(link)
CursorShape {
anchors.fill: parent
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
}
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
FlatButton {
visible: roomPreview && !roomPreview.isInvite
Layout.alignment: Qt.AlignHCenter
text: qsTr("join the conversation")
onClicked: Rooms.joinPreview(roomPreview.roomid)
}
FlatButton {
visible: roomPreview && roomPreview.isInvite
Layout.alignment: Qt.AlignHCenter
text: qsTr("accept invite")
onClicked: Rooms.acceptInvite(roomPreview.roomid)
}
FlatButton {
visible: roomPreview && roomPreview.isInvite
Layout.alignment: Qt.AlignHCenter
text: qsTr("decline invite")
onClicked: Rooms.declineInvite(roomPreview.roomid)
}
Item {
visible: room != null
Layout.preferredHeight: Math.ceil(fontMetrics.lineSpacing * 2)
}
Item {
Layout.fillHeight: true
}
}
Nicolas Werner
committed
ImageButton {
id: backToRoomsButton
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: Nheko.paddingMedium
width: Nheko.avatarSize
height: Nheko.avatarSize
visible: (room == null || room.isSpace) && showBackButton
Nicolas Werner
committed
enabled: visible
image: ":/icons/icons/ui/angle-arrow-left.svg"
Nicolas Werner
committed
ToolTip.visible: hovered
ToolTip.text: qsTr("Back to room list")
onClicked: Rooms.resetCurrentRoom()
}
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
ParticleSystem { id: confettiParticleSystem }
Emitter {
id: confettiEmitter
width: parent.width * 3/4
enabled: false
anchors.horizontalCenter: parent.horizontalCenter
y: parent.height
emitRate: Math.min(400 * Math.sqrt(parent.width * parent.height) / 870, 1000)
lifeSpan: 15000
system: confettiParticleSystem
velocityFromMovement: 8
size: 16
sizeVariation: 4
velocity: PointDirection {
x: 0
y: -Math.min(450 * parent.height / 700, 1000)
xVariation: Math.min(4 * parent.width / 7, 450)
yVariation: 250
}
ImageParticle {
system: confettiParticleSystem
source: "qrc:/confettiparticle.svg"
rotationVelocity: 0
rotationVelocityVariation: 360
colorVariation: 1
color: "white"
entryEffect: ImageParticle.None
xVector: PointDirection {
x: 1
y: 0
xVariation: 0.2
yVariation: 0.2
}
yVector: PointDirection {
x: 0
y: 0.5
xVariation: 0.2
yVariation: 0.2
}
}
}
Gravity {
system: confettiParticleSystem
anchors.fill: parent
magnitude: 350
angle: 90
}
NhekoDropArea {
roomid: room ? room.roomId : ""
Connections {
function onOpenReadReceiptsDialog(rr) {
var dialog = readReceiptsDialog.createObject(timelineRoot, {
"readReceipts": rr,
"room": room
});
dialog.show();
}
function onShowRawMessageDialog(rawMessage) {
var dialog = Qt.createComponent("qrc:/qml/dialogs/RawMessageDialog.qml").createObject(timelineRoot, {
"rawMessage": rawMessage
});
dialog.show();
function onConfetti()
{
if (!Settings.fancyEffects)
return
confettiEmitter.pulse(parent.height * 2)
room.markSpecialEffectsDone()
}
target: room
}