diff --git a/TODO.md b/TODO.md
index c8d7f9bb..33c268df 100644
--- a/TODO.md
+++ b/TODO.md
@@ -6,8 +6,8 @@
- Bottom/top bar
- Uploading (+local echo)
- Deduplicate uploads
- - Files, links, video, audio
- - File thumbnails, ask matrix API?
+ - EventLink
+ - File thumbnails + ask matrix API?
- Encrypted media
- Loading animation
- GIF thumbnails: load the real animated image
@@ -19,8 +19,13 @@
- Video: missing buttons and small size problems
- Audio: online playback is buggy, must download+play file
- - Refactor EventContent
- - No background/padding around medias
+ - With this as eventText: `https://0x0.st/ztXe.png`, shrinking the window
+ near its minimum size (seen at 262px) makes the image preview
+ left padding wrong
+ - In the "Leave me" room, "join > Hi > left" aren't combined
+ - GIF glitchy border
+ - Combined pure media events time looks bad
+ - Avatars shouldn't be vertically centered
- Copy to X11 selection with new CppUtils class
@@ -41,7 +46,7 @@
- When qml syntax highlighting supports ES6 string interpolation, use that
- Fixes
- - GIF glitchy border
+ - Event delegates changing height don't scroll the list
- When selecting text and scrolling up, selection stops working after a while
- Ensure all the text that should be copied is copied
diff --git a/src/python/utils.py b/src/python/utils.py
index 3ae437df..43df4549 100644
--- a/src/python/utils.py
+++ b/src/python/utils.py
@@ -44,6 +44,5 @@ def guess_mime(file: IO) -> Optional[str]:
def plain2html(text: str) -> str:
return html.escape(text)\
- .replace(" ", " ")\
.replace("\n", "
")\
.replace("\t", " " * 4)
diff --git a/src/qml/Base/HRepeater.qml b/src/qml/Base/HRepeater.qml
index 2f4e250e..089c332a 100644
--- a/src/qml/Base/HRepeater.qml
+++ b/src/qml/Base/HRepeater.qml
@@ -9,7 +9,19 @@ Repeater {
let total = 0
for (let i = 0; i < repeater.count; i++) {
- total += repeater.itemAt(i).implicitWidth
+ let item = repeater.itemAt(i)
+ if (item && item.width) total += item.width
+ }
+
+ return total
+ }
+
+ readonly property int childrenWidth: {
+ let total = 0
+
+ for (let i = 0; i < repeater.count; i++) {
+ let item = repeater.itemAt(i)
+ if (item && item.width) total += item.width
}
return total
diff --git a/src/qml/Chat/Timeline/EventAudio.qml b/src/qml/Chat/Timeline/EventAudio.qml
index 979f69de..94d394c7 100644
--- a/src/qml/Chat/Timeline/EventAudio.qml
+++ b/src/qml/Chat/Timeline/EventAudio.qml
@@ -7,10 +7,6 @@ import "../../utils.js" as Utils
AudioPlayer {
id: audio
- width: Math.min(
- mainColumn.width - eventContent.spacing * 2,
- theme.chat.message.audioWidth,
- )
HoverHandler {
onHoveredChanged:
diff --git a/src/qml/Chat/Timeline/EventContent.qml b/src/qml/Chat/Timeline/EventContent.qml
index 4f33058c..40e22fe1 100644
--- a/src/qml/Chat/Timeline/EventContent.qml
+++ b/src/qml/Chat/Timeline/EventContent.qml
@@ -3,149 +3,173 @@ import QtQuick.Layouts 1.12
import "../../Base"
import "../../utils.js" as Utils
-Row {
+HRowLayout {
id: eventContent
spacing: theme.spacing / 1.25
+ layoutDirection: onRight ? Qt.RightToLeft: Qt.LeftToRight
readonly property string eventText: Utils.processedEventText(model)
readonly property string eventTime: Utils.formatTime(model.date, false)
+ readonly property bool pureMedia: ! eventText && previewLinksRepeater.count
- readonly property string hoveredLink:
- nameLabel.hoveredLink || contentLabel.hoveredLink
+ readonly property string hoveredLink: contentLabel.hoveredLink
+ readonly property bool hoveredSelectable: contentHover.hovered
- readonly property bool hoveredSelectable:
- nameHover.hovered || contentHover.hovered
+ readonly property int messageBodyWidth:
+ width - (avatarWrapper.visible ? avatarWrapper.width : 0) -
+ totalSpacing
Item {
- width: hideAvatar ? 0 : 58
- height: hideAvatar ? 0 : collapseAvatar ? 1 : smallAvatar ? 28 : 58
- opacity: hideAvatar || collapseAvatar ? 0 : 1
- visible: width > 0
+ id: avatarWrapper
+ opacity: collapseAvatar ? 0 : 1
+ visible: ! hideAvatar
+
+ Layout.minimumWidth: 58
+ Layout.minimumHeight: collapseAvatar ? 1 : smallAvatar ? 28 : 58
+ Layout.maximumWidth: Layout.minimumWidth
+ Layout.maximumHeight: Layout.minimumHeight
HUserAvatar {
id: avatar
userId: model.sender_id
displayName: model.sender_name
avatarUrl: model.sender_avatar
- width: hideAvatar ? 0 : 58
- height: hideAvatar ? 0 : collapseAvatar ? 1 : 58
+ width: parent.width
+ height: collapseAvatar ? 1 : 58
}
}
- Rectangle {
- color: isOwn?
- theme.chat.message.ownBackground :
- theme.chat.message.background
+ HColumnLayout {
+ id: contentColumn
+ Layout.alignment: Qt.AlignVCenter
- //width: nameLabel.implicitWidth
- width: Math.min(
- eventList.width - avatar.width - eventContent.spacing,
- theme.fontSize.normal * 0.5 * 75, // 600 with 16px font
+ HSelectableLabel {
+ id: contentLabel
+ container: selectableLabelContainer
+ index: model.index
- Math.max(
- nameLabel.visible ? (nameLabel.implicitWidth + 1) : 0,
-
- contentLabel.implicitWidth + 1,
-
- previewLinksRepeater.count > 0 ?
- theme.chat.message.thumbnailWidth : 0,
- )
- )
- height: childrenRect.height
- y: parent.height / 2 - height / 2
-
- Column {
- id: mainColumn
- width: parent.width
- spacing: theme.spacing / 1.75
topPadding: theme.spacing / 1.75
bottomPadding: topPadding
+ leftPadding: eventContent.spacing
+ rightPadding: leftPadding
- HSelectableLabel {
- id: nameLabel
- width: parent.width
- visible: ! hideNameLine
- container: selectableLabelContainer
- selectable: ! unselectableNameLine
- leftPadding: eventContent.spacing
- rightPadding: leftPadding
+ color: theme.chat.message.body
+ wrapMode: TextEdit.Wrap
+ textFormat: Text.RichText
+ text:
+ // CSS
+ theme.chat.message.styleInclude +
- // This is +0.1 and content is +0 instead of the opposite,
- // because the eventList is reversed
- index: model.index + 0.1
+ // Sender name
+ (hideNameLine ? "" : (
+ "