diff --git a/TODO.md b/TODO.md
index 22e4c8f0..fb144411 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,6 +1,5 @@
- Refactoring
- Use HInterfaceBox for EditAccount Profile and Encryption
- - Use ItemDelegate
- Make all icon SVG files white/black, since we can now use ColorOverlay
- Make the icon blue in EditAccount when hovering and no avatar set
@@ -12,6 +11,7 @@
- Room Sidepane
- Hide when window too small
- Also save/load its size
+ - Is auto-sizing actually needed, or can we just set a default manual size?
- When qml syntax highlighting supports ES6 string interpolation, use them
- Fixes
diff --git a/src/qml/Base/HButton.qml b/src/qml/Base/HButton.qml
index d2942cc9..35df7aa5 100644
--- a/src/qml/Base/HButton.qml
+++ b/src/qml/Base/HButton.qml
@@ -4,6 +4,11 @@ import QtQuick.Layouts 1.12
Button {
id: button
+ spacing: theme.spacing
+ leftPadding: spacing / 1.5
+ rightPadding: spacing / 1.5
+ topPadding: spacing / 2
+ bottomPadding: spacing / 2
opacity: enabled ? 1 : theme.disabledElementsOpacity
onVisibleChanged: if (! visible) loading = false
diff --git a/src/qml/Base/HFixedListView.qml b/src/qml/Base/HFixedListView.qml
index 253de681..2994cb1d 100644
--- a/src/qml/Base/HFixedListView.qml
+++ b/src/qml/Base/HFixedListView.qml
@@ -18,8 +18,7 @@ ListView {
highlight: HRectangle {
- color: theme.controls.interactiveRectangle.checkedOverlay
- opacity: theme.controls.interactiveRectangle.checkedOpacity
+ color: theme.controls.button.checkedOverlay
}
// Important:
diff --git a/src/qml/Base/HTileDelegate.qml b/src/qml/Base/HTileDelegate.qml
new file mode 100644
index 00000000..2e669080
--- /dev/null
+++ b/src/qml/Base/HTileDelegate.qml
@@ -0,0 +1,101 @@
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+
+HButton {
+ id: tile
+
+
+ signal activated()
+ signal highlightMe()
+
+
+ property bool isCurrent: false
+
+ readonly property var delegateModel: model
+
+ default property var additionalItems: []
+
+ readonly property alias title: title
+ readonly property alias additionalInfo: additionalInfo
+ readonly property alias rightInfo: rightInfo
+ readonly property alias subtitle: subtitle
+
+ property Item image
+
+ property Item details: HColumnLayout {
+ Layout.fillWidth: true
+
+ HRowLayout {
+ spacing: tile.spacing
+
+ HLabel {
+ id: title
+ text: "Title"
+ elide: Text.ElideRight
+ verticalAlignment: Qt.AlignVCenter
+
+ Layout.fillWidth: true
+ }
+
+ HRowLayout {
+ id: additionalInfo
+ }
+
+ HLabel {
+ id: rightInfo
+ font.pixelSize: theme.fontSize.small
+
+ visible: Layout.maximumWidth > 0
+ Layout.maximumWidth:
+ text && tile.width >= 200 ? implicitWidth : 0
+
+ Behavior on Layout.maximumWidth { HNumberAnimation {} }
+ }
+ }
+
+ HRichLabel {
+ id: subtitle
+ textFormat: Text.StyledText
+ font.pixelSize: theme.fontSize.small
+ elide: Text.ElideRight
+
+ visible: Layout.maximumHeight > 0
+ Layout.maximumHeight: text ? implicitWidth : 0
+ Layout.fillWidth: true
+
+ Behavior on Layout.maximumHeight { HNumberAnimation {} }
+ }
+ }
+
+
+ contentItem: HRowLayout {
+ spacing: tile.spacing
+ children: [image, details].concat(additionalItems)
+ }
+
+ onIsCurrentChanged: if (isCurrent) highlightMe()
+ onHighlightMe: accountRoomList.currentIndex = model.index
+
+ onClicked: {
+ ListView.highlightRangeMode = ListView.NoHighlightRange
+ ListView.highlightMoveDuration = 0
+ activated()
+ ListView.highlightRangeMode = ListView.ApplyRange
+ ListView.highlightMoveDuration = theme.animationDuration
+ }
+
+
+ Timer {
+ interval: 100
+ repeat: true
+ running: ListView.currentIndex == -1
+ // Component.onCompleted won't work for this
+ onTriggered: if (isCurrent) highlightMe()
+ }
+
+ // Connections {
+ // target: ListView
+ // onHideHoverHighlight: tile.hovered = false
+ // }
+
+}
diff --git a/src/qml/Chat/RoomSidePane/MemberDelegate.qml b/src/qml/Chat/RoomSidePane/MemberDelegate.qml
index 4ad15c0a..b32d15af 100644
--- a/src/qml/Chat/RoomSidePane/MemberDelegate.qml
+++ b/src/qml/Chat/RoomSidePane/MemberDelegate.qml
@@ -1,38 +1,18 @@
import QtQuick 2.12
-import QtQuick.Layouts 1.12
import "../../Base"
-import "../../utils.js" as Utils
-HInteractiveRectangle {
+HTileDelegate {
id: memberDelegate
- width: memberList.width
- height: rowLayout.height
+ spacing: roomSidePane.currentSpacing
+ rightPadding: 0
+ backgroundColor: theme.sidePane.member.background
- HRowLayout {
- id: rowLayout
- x: roomSidePane.currentSpacing
- width: parent.width - roomSidePane.currentSpacing * 1.5
- height: avatar.height + roomSidePane.currentSpacing / 1.5
- spacing: roomSidePane.currentSpacing
-
- HUserAvatar {
- id: avatar
- userId: model.user_id
- displayName: model.display_name
- avatarUrl: model.avatar_url
- }
-
- HColumnLayout {
- Layout.fillWidth: true
-
- HLabel {
- id: memberName
- text: model.display_name || model.user_id
- elide: Text.ElideRight
- verticalAlignment: Qt.AlignVCenter
-
- Layout.fillWidth: true
- }
- }
+ image: HUserAvatar {
+ userId: model.user_id
+ displayName: model.display_name
+ avatarUrl: model.avatar_url
}
+
+ title.color: theme.sidePane.member.name
+ title.text: model.display_name || model.user_id
}
diff --git a/src/qml/Chat/RoomSidePane/MembersView.qml b/src/qml/Chat/RoomSidePane/MembersView.qml
index 9373aabe..b8119f21 100644
--- a/src/qml/Chat/RoomSidePane/MembersView.qml
+++ b/src/qml/Chat/RoomSidePane/MembersView.qml
@@ -6,7 +6,6 @@ import "../../utils.js" as Utils
HColumnLayout {
HListView {
id: memberList
- bottomMargin: currentSpacing
model: HListModel {
keyField: "user_id"
@@ -16,7 +15,9 @@ HColumnLayout {
)
}
- delegate: MemberDelegate {}
+ delegate: MemberDelegate {
+ width: memberList.width
+ }
Layout.fillWidth: true
Layout.fillHeight: true
diff --git a/src/qml/SidePane/AccountRoomList.qml b/src/qml/SidePane/AccountRoomList.qml
index 84e8c87b..60b6791a 100644
--- a/src/qml/SidePane/AccountRoomList.qml
+++ b/src/qml/SidePane/AccountRoomList.qml
@@ -75,7 +75,7 @@ HListView {
}
function activate() {
- currentItem.item.activate()
+ currentItem.item.activated()
}
function toggleCollapseAccount() {
diff --git a/src/qml/SidePane/DelegateAccount.qml b/src/qml/SidePane/DelegateAccount.qml
index 1f862cb1..936bd414 100644
--- a/src/qml/SidePane/DelegateAccount.qml
+++ b/src/qml/SidePane/DelegateAccount.qml
@@ -2,21 +2,24 @@ import QtQuick 2.12
import QtQuick.Layouts 1.12
import "../Base"
-HInteractiveRectangle {
+HTileDelegate {
id: accountDelegate
- color: theme.sidePane.account.background
- // checked: isCurrent
- height: row.height
+ spacing: 0
+ topPadding: model.index > 0 ? sidePane.currentSpacing / 2 : 0
+ bottomPadding: topPadding
+ backgroundColor: theme.sidePane.account.background
+
+ opacity: collapsed && ! forceExpand ?
+ theme.sidePane.account.collapsedOpacity : 1
+
+ isCurrent: window.uiState.page == "Pages/EditAccount/EditAccount.qml" &&
+ window.uiState.pageProperties.userId == model.data.user_id
- readonly property var delegateModel: model
+ Behavior on opacity { HNumberAnimation {} }
- readonly property bool isCurrent:
- window.uiState.page == "Pages/EditAccount/EditAccount.qml" &&
- window.uiState.pageProperties.userId == model.data.user_id
- readonly property bool forceExpand:
- Boolean(accountRoomList.filter)
+ readonly property bool forceExpand: Boolean(accountRoomList.filter)
// Hide harmless error when a filter matches nothing
readonly property bool collapsed: try {
@@ -24,109 +27,50 @@ HInteractiveRectangle {
} catch (err) {}
- onIsCurrentChanged: if (isCurrent) beHighlighted()
+ onActivated: pageLoader.showPage(
+ "EditAccount/EditAccount", { "userId": model.data.user_id }
+ )
- function beHighlighted() {
- accountRoomList.currentIndex = model.index
- }
-
function toggleCollapse() {
window.uiState.collapseAccounts[model.data.user_id] = ! collapsed
window.uiStateChanged()
}
- function activate() {
- pageLoader.showPage(
- "EditAccount/EditAccount", { "userId": model.data.user_id }
- )
+
+ image: HUserAvatar {
+ userId: model.data.user_id
+ displayName: model.data.display_name
+ avatarUrl: model.data.avatar_url
}
+ title.color: theme.sidePane.account.name
+ title.text: model.data.display_name || model.data.user_id
+ title.font.pixelSize: theme.fontSize.big
+ title.leftPadding: sidePane.currentSpacing
- // Component.onCompleted won't work for this
- Timer {
- interval: 100
- repeat: true
- running: accountRoomList.currentIndex == -1
- onTriggered: if (isCurrent) beHighlighted()
- }
+ HButton {
+ id: expand
+ iconName: "expand"
+ ico.dimension: 16
+ backgroundColor: "transparent"
+ leftPadding: sidePane.currentSpacing / 1.5
+ rightPadding: leftPadding
+ onClicked: accountDelegate.toggleCollapse()
- Connections {
- target: accountRoomList
- onHideHoverHighlight: accountDelegate.hovered = false
- }
+ visible: opacity > 0
+ opacity: accountDelegate.forceExpand ? 0 : 1
- TapHandler {
- onTapped: {
- accountRoomList.highlightRangeMode = ListView.NoHighlightRange
- accountRoomList.highlightMoveDuration = 0
- activate()
- accountRoomList.highlightRangeMode = ListView.ApplyRange
- accountRoomList.highlightMoveDuration = theme.animationDuration
- }
- }
+ ico.transform: Rotation {
+ origin.x: expand.ico.dimension / 2
+ origin.y: expand.ico.dimension / 2
- HRowLayout {
- id: row
- width: parent.width
-
- HUserAvatar {
- id: avatar
- userId: model.data.user_id
- displayName: model.data.display_name
- avatarUrl: model.data.avatar_url
-
- opacity: collapsed && ! forceExpand ?
- theme.sidePane.account.collapsedOpacity : 1
- Behavior on opacity { HNumberAnimation {} }
-
- Layout.topMargin: model.index > 0 ? sidePane.currentSpacing / 2 : 0
- Layout.bottomMargin: Layout.topMargin
+ angle: collapsed ? 180 : 90
+ Behavior on angle { HNumberAnimation {} }
}
- HLabel {
- id: accountLabel
- color: theme.sidePane.account.name
- text: model.data.display_name || model.data.user_id
- font.pixelSize: theme.fontSize.big
- elide: HLabel.ElideRight
+ Behavior on opacity { HNumberAnimation {} }
- leftPadding: sidePane.currentSpacing
- verticalAlignment: Text.AlignVCenter
-
- opacity: collapsed && ! forceExpand ?
- theme.sidePane.account.collapsedOpacity : 1
- Behavior on opacity { HNumberAnimation {} }
-
- Layout.fillWidth: true
- Layout.fillHeight: true
- }
-
- HButton {
- id: expandButton
- iconName: "expand"
- ico.dimension: 16
- backgroundColor: "transparent"
- leftPadding: sidePane.currentSpacing
- rightPadding: leftPadding
- onClicked: accountDelegate.toggleCollapse()
-
- visible: opacity > 0
- opacity:
- accountDelegate.forceExpand ? 0 :
- collapsed ? theme.sidePane.account.collapsedOpacity + 0.2 :
- 1
- Behavior on opacity { HNumberAnimation {} }
-
- ico.transform: Rotation {
- origin.x: expandButton.ico.dimension / 2
- origin.y: expandButton.ico.dimension / 2
-
- angle: collapsed ? 180 : 90
- Behavior on angle { HNumberAnimation {} }
- }
-
- Layout.fillHeight: true
- }
+ Layout.fillHeight: true
}
}
diff --git a/src/qml/SidePane/DelegateRoom.qml b/src/qml/SidePane/DelegateRoom.qml
index 3a9bb40a..708e8f0e 100644
--- a/src/qml/SidePane/DelegateRoom.qml
+++ b/src/qml/SidePane/DelegateRoom.qml
@@ -3,157 +3,73 @@ import QtQuick.Layouts 1.12
import "../Base"
import "../utils.js" as Utils
-HInteractiveRectangle {
+HTileDelegate {
id: roomDelegate
- color: theme.sidePane.room.background
- visible: height > 0
- height: rowLayout.height
+ spacing: sidePane.currentSpacing
+ backgroundColor: theme.sidePane.room.background
opacity: model.data.left ? theme.sidePane.room.leftRoomOpacity : 1
+ isCurrent: window.uiState.page == "Chat/Chat.qml" &&
+ window.uiState.pageProperties.userId == model.user_id &&
+ window.uiState.pageProperties.roomId == model.data.room_id
Behavior on opacity { HNumberAnimation {} }
- readonly property var delegateModel: model
-
- readonly property bool forceExpand:
- Boolean(accountRoomList.filter)
-
- readonly property bool isCurrent:
- window.uiState.page == "Chat/Chat.qml" &&
- window.uiState.pageProperties.userId == model.user_id &&
- window.uiState.pageProperties.roomId == model.data.room_id
+ readonly property var eventDate:
+ model.data.last_event ? model.data.last_event.date : null
- onIsCurrentChanged: if (isCurrent) beHighlighted()
+ onActivated: pageLoader.showRoom(model.user_id, model.data.room_id)
- function beHighlighted() {
- accountRoomList.currentIndex = model.index
+ image: HRoomAvatar {
+ displayName: model.data.display_name
+ avatarUrl: model.data.avatar_url
}
- function activate() {
- pageLoader.showRoom(model.user_id, model.data.room_id)
+ title.color: theme.sidePane.room.name
+ title.text: model.data.display_name || "Empty room"
+ title.textFormat: model.data.display_name? Text.PlainText : Text.StyledText
+
+ additionalInfo.children: HIcon {
+ svgName: "invite-received"
+
+ visible: Layout.maximumWidth > 0
+ Layout.maximumWidth:
+ model.data.inviter_id && ! model.data.left ?
+ implicitWidth : 0
+
+ Behavior on Layout.maximumWidth { HNumberAnimation {} }
}
+ rightInfo.color: theme.sidePane.room.lastEventDate
+ rightInfo.text: {
+ ! eventDate ? "" :
- // Component.onCompleted won't work for this
- Timer {
- interval: 100
- repeat: true
- running: accountRoomList.currentIndex == -1
- onTriggered: if (isCurrent) beHighlighted()
+ Utils.dateIsToday(eventDate) ?
+ Utils.formatTime(eventDate, false) : // no seconds
+
+ eventDate.getFullYear() == new Date().getFullYear() ?
+ Qt.formatDate(eventDate, "d MMM") : // e.g. "5 Dec"
+
+ eventDate.getFullYear()
}
- Connections {
- target: accountRoomList
- onHideHoverHighlight: roomDelegate.hovered = false
- }
+ subtitle.color: theme.sidePane.room.subtitle
+ subtitle.textFormat: Text.StyledText
+ subtitle.text: {
+ if (! model.data.last_event) { return "" }
- TapHandler {
- onTapped: {
- accountRoomList.highlightRangeMode = ListView.NoHighlightRange
- accountRoomList.highlightMoveDuration = 0
- activate()
- accountRoomList.highlightRangeMode = ListView.ApplyRange
- accountRoomList.highlightMoveDuration = theme.animationDuration
- }
- }
+ let ev = model.data.last_event
- HRowLayout {
- id: rowLayout
-
- spacing: sidePane.currentSpacing
- x: sidePane.currentSpacing
- width: parent.width - sidePane.currentSpacing * 1.75
- height: roomName.height + subtitle.height + sidePane.currentSpacing
-
- HRoomAvatar {
- id: roomAvatar
- displayName: model.data.display_name
- avatarUrl: model.data.avatar_url
+ if (ev.event_type === "RoomMessageEmote" ||
+ ! ev.event_type.startsWith("RoomMessage")) {
+ return Utils.processedEventText(ev)
}
- HColumnLayout {
- Layout.fillWidth: true
-
- HRowLayout {
- spacing: rowLayout.spacing
-
- HLabel {
- id: roomName
- color: theme.sidePane.room.name
- text: model.data.display_name || "Empty room"
- textFormat:
- model.data.display_name?
- Text.PlainText : Text.StyledText
- elide: Text.ElideRight
- verticalAlignment: Qt.AlignVCenter
-
- Layout.fillWidth: true
- }
-
- HIcon {
- svgName: "invite-received"
-
- visible: Layout.maximumWidth > 0
- Layout.maximumWidth:
- model.data.inviter_id && ! model.data.left ?
- implicitWidth : 0
- Behavior on Layout.maximumWidth { HNumberAnimation {} }
- }
-
- HLabel {
- readonly property var evDate:
- model.data.last_event ?
- model.data.last_event.date : null
-
- id: lastEventDate
- font.pixelSize: theme.fontSize.small
- color: theme.sidePane.room.lastEventDate
-
- text: ! evDate ? "" :
-
- Utils.dateIsToday(evDate) ?
- Utils.formatTime(evDate, false) : // no seconds
-
- evDate.getFullYear() == new Date().getFullYear() ?
- Qt.formatDate(evDate, "d MMM") : // e.g. "5 Dec"
-
- evDate.getFullYear()
-
- visible: Layout.maximumWidth > 0
- Layout.maximumWidth:
- text && roomDelegate.width >= 200 ? implicitWidth : 0
- Behavior on Layout.maximumWidth { HNumberAnimation {} }
- }
- }
-
- HRichLabel {
- id: subtitle
- color: theme.sidePane.room.subtitle
- visible: Boolean(text)
- textFormat: Text.StyledText
- font.pixelSize: theme.fontSize.small
- elide: Text.ElideRight
-
- text: {
- if (! model.data.last_event) { return "" }
-
- let ev = model.data.last_event
-
- if (ev.event_type === "RoomMessageEmote" ||
- ! ev.event_type.startsWith("RoomMessage")) {
- return Utils.processedEventText(ev)
- }
-
- return Utils.coloredNameHtml(
- ev.sender_name, ev.sender_id
- ) + ": " + ev.inline_content
- }
-
- Layout.fillWidth: true
- }
- }
+ return Utils.coloredNameHtml(
+ ev.sender_name, ev.sender_id
+ ) + ": " + ev.inline_content
}
}
diff --git a/src/themes/Default.qpl b/src/themes/Default.qpl
index 875737b0..9d8a7d43 100644
--- a/src/themes/Default.qpl
+++ b/src/themes/Default.qpl
@@ -106,17 +106,6 @@ controls:
color text: colors.text
- interactiveRectangle:
- color background: "transparent"
-
- color hoveredOverlay: hsluv(0, 0, 50)
- color pressedOverlay: hsluv(0, 0, 50)
- color checkedOverlay: hsluv(0, 0, 50)
-
- real hoveredOpacity: 0.3
- real pressedOpacity: 0.2
- real checkedOpacity: 0.2
-
textField:
color background: colors.inputBackground
color focusedBackground: background
@@ -184,6 +173,10 @@ sidePane:
color subtitle: colors.dimText
color lastEventDate: colors.halfDimText
+ member:
+ color background: "transparent"
+ color name: colors.text
+
settingsButton:
color background: colors.inputBackground