Replace HInteractiveRectangle by HTiledelegate
This commit is contained in:
parent
4abf57c8d4
commit
46e685847f
2
TODO.md
2
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -18,8 +18,7 @@ ListView {
|
|||
|
||||
|
||||
highlight: HRectangle {
|
||||
color: theme.controls.interactiveRectangle.checkedOverlay
|
||||
opacity: theme.controls.interactiveRectangle.checkedOpacity
|
||||
color: theme.controls.button.checkedOverlay
|
||||
}
|
||||
|
||||
// Important:
|
||||
|
|
101
src/qml/Base/HTileDelegate.qml
Normal file
101
src/qml/Base/HTileDelegate.qml
Normal file
|
@ -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
|
||||
// }
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -75,7 +75,7 @@ HListView {
|
|||
}
|
||||
|
||||
function activate() {
|
||||
currentItem.item.activate()
|
||||
currentItem.item.activated()
|
||||
}
|
||||
|
||||
function toggleCollapseAccount() {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 || "<i>Empty room</i>"
|
||||
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 || "<i>Empty room</i>"
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user