diff --git a/TODO.md b/TODO.md
index d3204b89..6cfbfbf1 100644
--- a/TODO.md
+++ b/TODO.md
@@ -33,7 +33,7 @@
- Terrible performance using `QT_QPA_PLATFORM=wayland-egl`, must use `xcb`
- UI
- - Highlight selected account/room
+ - Remove first html lists left margin
- Popup:
- label size
diff --git a/src/python/backend.py b/src/python/backend.py
index a164c1d7..b7281534 100644
--- a/src/python/backend.py
+++ b/src/python/backend.py
@@ -165,16 +165,18 @@ class Backend:
for account in sorted(self.models[Account].values()):
data.append({
- "type": "Account",
- "id": account.user_id,
- "data": account.__dict__,
+ "type": "Account",
+ "id": account.user_id,
+ "user_id": account.user_id,
+ "data": account.__dict__,
})
for room in sorted(self.models[Room, account.user_id].values()):
data.append({
- "type": "Room",
- "id": (account.user_id, room.room_id),
- "data": room.__dict__,
+ "type": "Room",
+ "id": "/".join((account.user_id, room.room_id)),
+ "user_id": account.user_id,
+ "data": room.__dict__,
})
return data
diff --git a/src/qml/Base/HCheckBox.qml b/src/qml/Base/HCheckBox.qml
index 00c0ecd8..ed8e1ca6 100644
--- a/src/qml/Base/HCheckBox.qml
+++ b/src/qml/Base/HCheckBox.qml
@@ -26,7 +26,7 @@ CheckBox {
anchors.centerIn: parent
dimension: parent.width - 2
svgName: "check-mark"
- colorize: theme.colors.accentText
+ colorize: theme.colors.strongAccentBackground
visible: scale > 0
scale: box.checked ? 1 : 0
diff --git a/src/qml/SidePane/AccountDelegate.qml b/src/qml/SidePane/AccountDelegate.qml
deleted file mode 100644
index 6d4afa0e..00000000
--- a/src/qml/SidePane/AccountDelegate.qml
+++ /dev/null
@@ -1,94 +0,0 @@
-import QtQuick 2.12
-import QtQuick.Layouts 1.12
-import "../Base"
-
-Column {
- id: accountDelegate
- width: parent.width
- spacing: theme.spacing / 2
-
- opacity:
- paneToolBar.roomFilter && roomList.model.count < 1 ? 0.3 : 1
- Behavior on opacity { HNumberAnimation {} }
-
- property alias roomList: roomList
-
- property bool forceExpand: paneToolBar.roomFilter && roomList.model.count
- property bool expanded: true
- readonly property var modelItem: model
-
- readonly property bool isCurrent:
- window.uiState.page == "Pages/EditAccount/EditAccount.qml" &&
- window.uiState.pageProperties.userId == model.user_id
-
- Component.onCompleted:
- expanded = ! window.uiState.collapseAccounts[model.user_id]
-
- onExpandedChanged: {
- window.uiState.collapseAccounts[model.user_id] = ! expanded
- window.uiStateChanged()
- }
-
- function activate() {
- pageStack.showPage(
- "EditAccount/EditAccount", { "userId": model.user_id }
- )
- }
-
- HInteractiveRectangle {
- id: rectangle
- width: parent.width
- height: childrenRect.height
- color: theme.sidePane.account.background
-
- checked: accountDelegate.isCurrent
-
- TapHandler { onTapped: accountDelegate.activate() }
-
- HRowLayout {
- id: row
- width: parent.width
-
- HUserAvatar {
- id: avatar
- userId: model.user_id
- displayName: model.display_name
- avatarUrl: model.avatar_url
- }
-
- HLabel {
- id: accountLabel
- color: theme.sidePane.account.name
- text: model.display_name || model.user_id
- font.pixelSize: theme.fontSize.big
- elide: HLabel.ElideRight
- leftPadding: sidePane.currentSpacing
- rightPadding: leftPadding
-
- Layout.fillWidth: true
- Layout.fillHeight: true
- }
-
- ExpandButton {
- id: expandButton
- opacity: paneToolBar.roomFilter ? 0 : 1
- expandableItem: accountDelegate
- Layout.preferredHeight: row.height
- }
- }
- }
-
- RoomList {
- id: roomList
- visible: height > 0
- width: parent.width
- height:
- childrenRect.height *
- (accountDelegate.expanded || accountDelegate.forceExpand ? 1 : 0)
- clip: heightAnimation.running
-
- userId: modelItem.user_id
-
- Behavior on height { HNumberAnimation { id: heightAnimation } }
- }
-}
diff --git a/src/qml/SidePane/AccountList.qml b/src/qml/SidePane/AccountList.qml
deleted file mode 100644
index 229bbc54..00000000
--- a/src/qml/SidePane/AccountList.qml
+++ /dev/null
@@ -1,15 +0,0 @@
-import QtQuick 2.12
-import QtQuick.Layouts 1.12
-import "../Base"
-
-HListView {
- id: accountList
- clip: true
-
- model: HListModel {
- keyField: "user_id"
- source: modelSources["Account"] || []
- }
-
- delegate: AccountDelegate {}
-}
diff --git a/src/qml/SidePane/AccountRoomList.qml b/src/qml/SidePane/AccountRoomList.qml
new file mode 100644
index 00000000..4dbc386a
--- /dev/null
+++ b/src/qml/SidePane/AccountRoomList.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import "../Base"
+
+HListView {
+ id: accountRoomList
+
+ // property bool forceExpand: paneToolBar.roomFilter && roomList.model.count
+ property bool forceExpand: false
+
+ model: HListModel {
+ keyField: "id"
+ source: window.sidePaneModelSource
+ }
+
+ delegate: Loader {
+ width: accountRoomList.width
+ source: "Delegate" +
+ (model.type == "Account" ? "Account.qml" : "Room.qml")
+ }
+}
diff --git a/src/qml/SidePane/DelegateAccount.qml b/src/qml/SidePane/DelegateAccount.qml
new file mode 100644
index 00000000..18cdd92e
--- /dev/null
+++ b/src/qml/SidePane/DelegateAccount.qml
@@ -0,0 +1,93 @@
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import "../Base"
+
+HInteractiveRectangle {
+ id: accountDelegate
+ height: row.height
+ color: theme.sidePane.account.background
+
+ checked: accountDelegate.isCurrent
+ readonly property bool isCurrent:
+ window.uiState.page == "Pages/EditAccount/EditAccount.qml" &&
+ window.uiState.pageProperties.userId == model.data.user_id
+
+ readonly property bool collapsed:
+ ! accountRoomList.forceExpand &&
+ window.uiState.collapseAccounts[model.data.user_id] || false
+
+ function toggleCollapse() {
+ window.uiState.collapseAccounts[model.data.user_id] = ! collapsed
+ window.uiStateChanged()
+ }
+
+ function activate() {
+ pageStack.showPage(
+ "EditAccount/EditAccount", { "userId": model.data.user_id }
+ )
+ }
+
+ TapHandler { onTapped: accountDelegate.activate() }
+
+ 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 ? theme.sidePane.account.collapsedOpacity : 1
+ Behavior on opacity { HNumberAnimation {} }
+
+ Layout.topMargin: model.index > 0 ? sidePane.currentSpacing / 2 : 0
+ Layout.bottomMargin: Layout.topMargin
+ }
+
+ 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
+
+ leftPadding: sidePane.currentSpacing
+ verticalAlignment: Text.AlignVCenter
+
+ opacity: collapsed ? theme.sidePane.account.collapsedOpacity : 1
+ Behavior on opacity { HNumberAnimation {} }
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+
+ HUIButton {
+ id: expandButton
+ iconName: "expand"
+ iconDimension: 16
+ backgroundColor: "transparent"
+ leftPadding: sidePane.currentSpacing
+ rightPadding: leftPadding
+ onClicked: accountDelegate.toggleCollapse()
+
+ visible: opacity > 0
+ opacity:
+ accountRoomList.forceExpand ? 0 :
+ collapsed ? theme.sidePane.account.collapsedOpacity + 0.2 :
+ 1
+ Behavior on opacity { HNumberAnimation {} }
+
+ iconTransform: Rotation {
+ origin.x: expandButton.iconDimension / 2
+ origin.y: expandButton.iconDimension / 2
+
+ angle: collapsed ? 180 : 90
+ Behavior on angle { HNumberAnimation {} }
+ }
+
+ Layout.fillHeight: true
+ }
+ }
+}
diff --git a/src/qml/SidePane/RoomDelegate.qml b/src/qml/SidePane/DelegateRoom.qml
similarity index 67%
rename from src/qml/SidePane/RoomDelegate.qml
rename to src/qml/SidePane/DelegateRoom.qml
index ef5f992f..d1e2bb2c 100644
--- a/src/qml/SidePane/RoomDelegate.qml
+++ b/src/qml/SidePane/DelegateRoom.qml
@@ -5,49 +5,58 @@ import "../utils.js" as Utils
HInteractiveRectangle {
id: roomDelegate
- width: roomList.width
- height: rowLayout.height
color: theme.sidePane.room.background
- opacity: model.left ? theme.sidePane.room.leftRoomOpacity : 1
+ readonly property bool collapsed:
+ ! accountRoomList.forceExpand &&
+ window.uiState.collapseAccounts[model.user_id] || false
+
+ visible: height > 0
+ height: collapsed ? 0 : rowLayout.height
+ Behavior on height { HNumberAnimation {} }
+
+ opacity: model.data.left ? theme.sidePane.room.leftRoomOpacity : 1
Behavior on opacity { HNumberAnimation {} }
checked: isCurrent
readonly property bool isCurrent:
window.uiState.page == "Chat/Chat.qml" &&
- window.uiState.pageProperties.userId == userId &&
- window.uiState.pageProperties.roomId == model.room_id
+ window.uiState.pageProperties.userId == model.user_id &&
+ window.uiState.pageProperties.roomId == model.data.room_id
- function activate() { pageStack.showRoom(userId, model.room_id) }
+ function activate() {
+ pageStack.showRoom(model.user_id, model.data.room_id)
+ print(model.user_id, model.data.room_id)
+ }
TapHandler { onTapped: activate() }
HRowLayout {
id: rowLayout
- x: sidePane.currentSpacing
- width: parent.width - sidePane.currentSpacing * 1.5
- height: roomName.height + subtitle.height +
- sidePane.currentSpacing
spacing: sidePane.currentSpacing
+ x: spacing
+ width: parent.width - spacing * 1.75
+ height: roomName.height + subtitle.height + spacing
HRoomAvatar {
id: roomAvatar
- displayName: model.display_name
- avatarUrl: model.avatar_url
+ displayName: model.data.display_name
+ avatarUrl: model.data.avatar_url
}
HColumnLayout {
Layout.fillWidth: true
HRowLayout {
- spacing: theme.spacing / 2
+ spacing: rowLayout.spacing
HLabel {
id: roomName
color: theme.sidePane.room.name
- text: model.display_name || "Empty room"
+ text: model.data.display_name || "Empty room"
textFormat:
- model.display_name? Text.PlainText : Text.StyledText
+ model.data.display_name?
+ Text.PlainText : Text.StyledText
elide: Text.ElideRight
verticalAlignment: Qt.AlignVCenter
@@ -59,13 +68,15 @@ HInteractiveRectangle {
visible: Layout.maximumWidth > 0
Layout.maximumWidth:
- model.inviter_id && ! model.left ? implicitWidth : 0
+ model.data.inviter_id && ! model.data.left ?
+ implicitWidth : 0
Behavior on Layout.maximumWidth { HNumberAnimation {} }
}
HLabel {
readonly property var evDate:
- model.last_event ? model.last_event.date : null
+ model.data.last_event ?
+ model.data.last_event.date : null
id: lastEventDate
font.pixelSize: theme.fontSize.small
@@ -97,9 +108,9 @@ HInteractiveRectangle {
elide: Text.ElideRight
text: {
- if (! model.last_event) { return "" }
+ if (! model.data.last_event) { return "" }
- let ev = model.last_event
+ let ev = model.data.last_event
if (ev.event_type === "RoomMessageEmote" ||
! ev.event_type.startsWith("RoomMessage")) {
diff --git a/src/qml/SidePane/ExpandButton.qml b/src/qml/SidePane/ExpandButton.qml
deleted file mode 100644
index c2f169c6..00000000
--- a/src/qml/SidePane/ExpandButton.qml
+++ /dev/null
@@ -1,23 +0,0 @@
-import QtQuick 2.12
-import "../Base"
-
-HUIButton {
- property var expandableItem: null
-
- id: expandButton
- iconName: "expand"
- iconDimension: 16
- backgroundColor: "transparent"
- onClicked: expandableItem.expanded = ! expandableItem.expanded
-
- visible: opacity > 0
- opacity: expandableItem.forceExpand ? 0 : 1
- Behavior on opacity { HNumberAnimation {} }
-
- iconTransform: Rotation {
- origin.x: expandButton.iconDimension / 2
- origin.y: expandButton.iconDimension / 2
- angle: expandableItem.expanded || expandableItem.forceExpand ? 90 : 180
- Behavior on angle { HNumberAnimation {} }
- }
-}
diff --git a/src/qml/SidePane/RoomList.qml b/src/qml/SidePane/RoomList.qml
deleted file mode 100644
index d84671cd..00000000
--- a/src/qml/SidePane/RoomList.qml
+++ /dev/null
@@ -1,19 +0,0 @@
-import QtQuick 2.12
-import "../Base"
-import "../utils.js" as Utils
-
-HFixedListView {
- id: roomList
-
- property string userId: ""
-
- model: HListModel {
- source: Utils.filterModelSource(
- modelSources[["Room", userId]] || [],
- paneToolBar.roomFilter,
- )
- keyField: "room_id"
- }
-
- delegate: RoomDelegate {}
-}
diff --git a/src/qml/SidePane/SidePane.qml b/src/qml/SidePane/SidePane.qml
index bba0cd2c..621ae65e 100644
--- a/src/qml/SidePane/SidePane.qml
+++ b/src/qml/SidePane/SidePane.qml
@@ -5,13 +5,13 @@ import "../utils.js" as Utils
HRectangle {
id: sidePane
- clip: true // Avoid artifacts when collapsed
+ clip: true
opacity: mainUI.accountsPresent && ! reduce ? 1 : 0
visible: opacity > 0
color: theme.sidePane.background
- property alias accountList: accountList
+ property alias accountRoomList: accountRoomList
property alias paneToolBar: paneToolBar
property real autoWidthRatio: theme.sidePane.autoWidthRatio
@@ -142,13 +142,12 @@ HRectangle {
HColumnLayout {
anchors.fill: parent
- AccountList {
- id: accountList
+ AccountRoomList {
+ id: accountRoomList
+ clip: true
+
Layout.fillWidth: true
Layout.fillHeight: true
-
- spacing: currentSpacing
- bottomMargin: currentSpacing
}
PaneToolBar {
diff --git a/src/qml/Window.qml b/src/qml/Window.qml
index 93936d00..e3ff75de 100644
--- a/src/qml/Window.qml
+++ b/src/qml/Window.qml
@@ -15,6 +15,7 @@ ApplicationWindow {
// Note: For JS object variables, the corresponding method to notify
// key/value changes must be called manually, e.g. settingsChanged().
property var modelSources: ({})
+ property var sidePaneModelSource: []
property var mainUI: null
diff --git a/src/qml/event_handlers.js b/src/qml/event_handlers.js
index ed9495c0..e0465b92 100644
--- a/src/qml/event_handlers.js
+++ b/src/qml/event_handlers.js
@@ -22,7 +22,7 @@ function onCoroutineDone(uuid, result) {
function onModelUpdated(syncId, data, serializedSyncId) {
if (serializedSyncId == ["Account"] || serializedSyncId[0] == "Room") {
py.callCoro("get_flat_sidepane_data", [], data => {
- print( JSON.stringify( data, null, 4))
+ window.sidePaneModelSource = data
})
}
diff --git a/src/themes/Default.qpl b/src/themes/Default.qpl
index 573153dc..cbe9cbcc 100644
--- a/src/themes/Default.qpl
+++ b/src/themes/Default.qpl
@@ -48,6 +48,12 @@ colors:
color inputBackground:
hsluv(hue, saturation, intensity * 2, Math.min(0.6, opacity))
+ color accentBackground:
+ hsluv(hue, saturation * 1.25, intensity * 42, Math.min(0.6, opacity))
+
+ color strongAccentBackground:
+ hsluv(hue, saturation * 2, intensity * 52, Math.min(0.6, opacity))
+
color brightText: hsluv(0, 0, intensity * 100)
color text: hsluv(0, 0, intensity * 80)
color halfDimText: hsluv(0, 0, intensity * 70)
@@ -83,10 +89,9 @@ controls:
button:
color background: colors.inputBackground
+ color checkedBackground: colors.accentBackground
color disabledBackground:
hsluv(0, 0, colors.intensity * 2, Math.min(0.6, opacity))
- color checkedBackground:
- hsluv(0, 0, colors.intensity * 40, Math.min(0.6, opacity))
color hoveredOverlay: hsluv(0, 0, 100)
color text: colors.text
@@ -95,13 +100,13 @@ controls:
interactiveRectangle:
color background: "transparent"
- color hoveredOverlay: hsluv(0, 0, 100)
- color pressedOverlay: hsluv(0, 0, 100)
- color checkedOverlay: hsluv(0, 0, 100)
+ color hoveredOverlay: hsluv(0, 0, 50)
+ color pressedOverlay: hsluv(0, 0, 50)
+ color checkedOverlay: hsluv(0, 0, 50)
- real hoveredOpacity: 0.1
+ real hoveredOpacity: 0.3
real pressedOpacity: 0.2
- real checkedOpacity: 0.08
+ real checkedOpacity: 0.2
textField:
color background: colors.inputBackground
@@ -109,7 +114,7 @@ controls:
int borderWidth: 1
color border: "transparent"
- color focusedBorder: colors.accentText
+ color focusedBorder: colors.strongAccentBackground
color text: colors.text
color focusedText: colors.text
@@ -158,8 +163,9 @@ sidePane:
color background: colors.strongBackground
account:
- color background: "transparent"
- color name: colors.text
+ real collapsedOpacity: 0.3
+ color background: "transparent"
+ color name: colors.text
room:
real leftRoomOpacity: 0.65