diff --git a/imports/NeoChat/Page/RoomListPage.qml b/imports/NeoChat/Page/RoomListPage.qml
index 1f2107ef8..6bd134813 100644
--- a/imports/NeoChat/Page/RoomListPage.qml
+++ b/imports/NeoChat/Page/RoomListPage.qml
@@ -18,6 +18,24 @@ Kirigami.ScrollablePage {
id: page
property var enteredRoom
+ property bool collapsedMode: Config.roomListPageWidth === applicationWindow().collapsedPageWidth && applicationWindow().shouldUseSidebars
+
+ onCollapsedModeChanged: if (collapsedMode) {
+ sortFilterRoomListModel.filterText = "";
+ if (page.contentItem && page.contentItem.flickableItem && page.contentItem.flickableItem.QQC2.ScrollBar.vertical) {
+ page.contentItem.flickableItem.QQC2.ScrollBar.vertical.visible = false;
+ }
+ } else {
+ page.contentItem.flickableItem.QQC2.ScrollBar.vertical.visible = true;
+ }
+
+ // HACK: the scrollbar is created with a 0 timer, so we need to set the visible flag
+ // after it has been created
+ Timer {
+ running: true
+ interval: 200
+ onTriggered: page.contentItem.flickableItem.QQC2.ScrollBar.vertical.visible = !collapsedMode;
+ }
function goToNextRoom() {
do {
@@ -33,17 +51,51 @@ Kirigami.ScrollablePage {
listView.currentItem.action.trigger();
}
- title: i18n("Rooms")
+ titleDelegate: collapsedMode ? empty : searchField
- titleDelegate: Kirigami.SearchField {
- Layout.topMargin: Kirigami.Units.smallSpacing
- Layout.bottomMargin: Kirigami.Units.smallSpacing
- Layout.fillHeight: true
- Layout.fillWidth: true
- onTextChanged: sortFilterRoomListModel.filterText = text
- KeyNavigation.tab: listView
+ Component {
+ id: empty
+ Item {}
}
+ Component {
+ id: searchField
+ Kirigami.SearchField {
+ Layout.topMargin: Kirigami.Units.smallSpacing
+ Layout.bottomMargin: Kirigami.Units.smallSpacing
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ onTextChanged: sortFilterRoomListModel.filterText = text
+ KeyNavigation.tab: listView
+ }
+ }
+
+ header: QQC2.ItemDelegate {
+ visible: page.collapsedMode
+ action: Kirigami.Action {
+ id: enterRoomAction
+ onTriggered: quickView.item.open();
+ }
+ topPadding: Kirigami.Units.largeSpacing
+ leftPadding: Kirigami.Units.largeSpacing
+ rightPadding: Kirigami.Units.largeSpacing
+ bottomPadding: Kirigami.Units.largeSpacing
+ width: visible ? page.width : 0
+ height: visible ? Kirigami.Units.gridUnit * 2 : 0
+
+ Kirigami.Icon {
+ anchors.centerIn: parent
+ width: 22 * Kirigami.Units.devicePixelRatio
+ height: 22 * Kirigami.Units.devicePixelRatio
+ source: "search"
+ }
+ Kirigami.Separator {
+ width: parent.width
+ anchors.bottom: parent.bottom
+ }
+ }
+
+
ListView {
id: listView
@@ -64,6 +116,7 @@ Kirigami.ScrollablePage {
}
}
+
ItemSelectionModel {
id: itemSelection
model: roomListModel
@@ -97,11 +150,14 @@ Kirigami.ScrollablePage {
level: 3
text: roomListModel.categoryName(section)
Layout.fillWidth: true
+ elide: Text.ElideRight
+ visible: !page.collapsedMode
}
Kirigami.Icon {
- source: roomListModel.categoryVisible(section) ? "go-up" : "go-down"
+ source: page.collapsedMode ? roomListModel.categoryIconName(section) : (roomListModel.categoryVisible(section) ? "go-up" : "go-down")
implicitHeight: Kirigami.Units.iconSizes.small
implicitWidth: Kirigami.Units.iconSizes.small
+ Layout.alignment: Qt.AlignHCenter
}
}
}
@@ -109,87 +165,128 @@ Kirigami.ScrollablePage {
reuseItems: true
currentIndex: -1 // we don't want any room highlighted by default
- delegate: Kirigami.BasicListItem {
- id: roomListItem
- visible: model.categoryVisible || sortFilterRoomListModel.filterText.length > 0 || Config.mergeRoomList
- topPadding: Kirigami.Units.largeSpacing
- bottomPadding: Kirigami.Units.largeSpacing
- highlighted: listView.currentIndex === index
- focus: true
- icon: undefined
- action: Kirigami.Action {
- id: enterRoomAction
- onTriggered: {
- RoomManager.enterRoom(currentRoom);
- itemSelection.setCurrentIndex(sortFilterRoomListModel.mapToSource(
- sortFilterRoomListModel.index(index, 0)), ItemSelectionModel.SelectCurrent)
- }
- }
- Keys.onEnterPressed: enterRoomAction.trigger()
- Keys.onReturnPressed: enterRoomAction.trigger()
- bold: unreadCount > 0
- label: name ?? ""
- subtitle: {
- let txt = (lastEvent.length === 0 ? topic : lastEvent).replace(/(\r\n\t|\n|\r\t)/gm, " ")
- if (txt.length) {
- return txt
- }
- return " "
- }
+ delegate: page.collapsedMode ? collapsedModeListComponent : normalModeListComponent
- leading: Kirigami.Avatar {
- source: avatar ? "image://mxc/" + avatar : ""
- name: model.name || i18n("No Name")
- implicitWidth: visible ? height : 0
- visible: Config.showAvatarInTimeline
- sourceSize.width: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2
- sourceSize.height: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2
- }
+ Component {
+ id: collapsedModeListComponent
- trailing: RowLayout {
- QQC2.Label {
- text: notificationCount
- visible: notificationCount > 0
- padding: Kirigami.Units.smallSpacing
- color: highlightCount > 0 ? "white" : Kirigami.Theme.textColor
- Layout.minimumWidth: height
- horizontalAlignment: Text.AlignHCenter
- background: Rectangle {
- Kirigami.Theme.colorSet: Kirigami.Theme.Button
- color: highlightCount > 0 ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.backgroundColor
- radius: height / 2
+ QQC2.ItemDelegate {
+ action: Kirigami.Action {
+ id: enterRoomAction
+ onTriggered: {
+ RoomManager.enterRoom(currentRoom);
+ itemSelection.setCurrentIndex(sortFilterRoomListModel.mapToSource(
+ sortFilterRoomListModel.index(index, 0)), ItemSelectionModel.SelectCurrent)
}
}
- QQC2.Button {
- id: configButton
- visible: roomListItem.hovered || Kirigami.Settings.isMobile
- Accessible.name: i18n("Configure room")
+ Keys.onEnterPressed: enterRoomAction.trigger()
+ Keys.onReturnPressed: enterRoomAction.trigger()
+ topPadding: Kirigami.Units.largeSpacing
+ leftPadding: Kirigami.Units.largeSpacing
+ rightPadding: Kirigami.Units.largeSpacing
+ bottomPadding: Kirigami.Units.largeSpacing
+ width: ListView.view.width
+ height: ListView.view.width
- action: Kirigami.Action {
- id: optionAction
- icon.name: "configure"
- onTriggered: {
- const menu = roomListContextMenu.createObject(page, {"room": currentRoom})
- configButton.visible = true
- configButton.down = true
- menu.closed.connect(function() {
- configButton.down = undefined
- configButton.visible = Qt.binding(function() { return roomListItem.hovered || Kirigami.Settings.isMobile })
- })
- menu.popup()
+ contentItem: Kirigami.Avatar {
+ source: avatar ? "image://mxc/" + avatar : ""
+ name: model.name || i18n("No Name")
+ sourceSize.width: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2
+ sourceSize.height: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2
+ }
+
+ QQC2.ToolTip {
+ enabled: text.length !== 0
+ text: name ?? ""
+ }
+ }
+ }
+
+ Component {
+ id: roomListContextMenu
+ RoomListContextMenu {}
+ }
+
+ Component {
+ id: normalModeListComponent
+ Kirigami.BasicListItem {
+ id: roomListItem
+ visible: model.categoryVisible || sortFilterRoomListModel.filterText.length > 0 || Config.mergeRoomList
+ topPadding: Kirigami.Units.largeSpacing
+ bottomPadding: Kirigami.Units.largeSpacing
+ highlighted: listView.currentIndex === index
+ focus: true
+ icon: undefined
+ action: Kirigami.Action {
+ id: enterRoomAction
+ onTriggered: {
+ RoomManager.enterRoom(currentRoom);
+ itemSelection.setCurrentIndex(sortFilterRoomListModel.mapToSource(
+ sortFilterRoomListModel.index(index, 0)), ItemSelectionModel.SelectCurrent)
+ }
+ }
+ Keys.onEnterPressed: enterRoomAction.trigger()
+ Keys.onReturnPressed: enterRoomAction.trigger()
+ bold: unreadCount > 0
+ label: name ?? ""
+ subtitle: {
+ let txt = (lastEvent.length === 0 ? topic : lastEvent).replace(/(\r\n\t|\n|\r\t)/gm, " ")
+ if (txt.length) {
+ return txt
+ }
+ return " "
+ }
+
+ leading: Kirigami.Avatar {
+ source: avatar ? "image://mxc/" + avatar : ""
+ name: model.name || i18n("No Name")
+ implicitWidth: visible ? height : 0
+ visible: Config.showAvatarInTimeline
+ sourceSize.width: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2
+ sourceSize.height: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2
+ }
+
+ trailing: RowLayout {
+ QQC2.Label {
+ text: notificationCount
+ visible: notificationCount > 0
+ padding: Kirigami.Units.smallSpacing
+ color: highlightCount > 0 ? "white" : Kirigami.Theme.textColor
+ Layout.minimumWidth: height
+ horizontalAlignment: Text.AlignHCenter
+ background: Rectangle {
+ Kirigami.Theme.colorSet: Kirigami.Theme.Button
+ color: highlightCount > 0 ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.backgroundColor
+ radius: height / 2
+ }
+ }
+ QQC2.Button {
+ id: configButton
+ visible: roomListItem.hovered || Kirigami.Settings.isMobile
+ Accessible.name: i18n("Configure room")
+
+ action: Kirigami.Action {
+ id: optionAction
+ icon.name: "configure"
+ onTriggered: {
+ const menu = roomListContextMenu.createObject(page, {"room": currentRoom})
+ configButton.visible = true
+ configButton.down = true
+ menu.closed.connect(function() {
+ configButton.down = undefined
+ configButton.visible = Qt.binding(function() { return roomListItem.hovered || Kirigami.Settings.isMobile })
+ })
+ menu.popup()
+ }
}
}
}
}
}
- Component {
- id: roomListContextMenu
- RoomListContextMenu {}
- }
}
footer: QQC2.ToolBar {
- visible: accountList.count > 1
+ visible: accountList.count > 1 && !collapsedMode
height: visible ? implicitHeight : 0
leftPadding: 0
rightPadding: 0
diff --git a/qml/main.qml b/qml/main.qml
index 0401ab054..d01448565 100644
--- a/qml/main.qml
+++ b/qml/main.qml
@@ -166,7 +166,70 @@ Kirigami.ApplicationWindow {
handleVisible: enabled && pageStack.layers.depth < 2 && pageStack.depth < 3
}
- pageStack.columnView.columnWidth: Kirigami.Units.gridUnit * 17
+ readonly property int defaultPageWidth: Kirigami.Units.gridUnit * 17
+ readonly property int minPageWidth: Kirigami.Units.gridUnit * 10
+ readonly property int collapsedPageWidth: Kirigami.Units.gridUnit * 3 - Kirigami.Units.smallSpacing * 3
+ readonly property bool shouldUseSidebars: (Config.roomListPageWidth > minPageWidth ? root.width >= Kirigami.Units.gridUnit * 35 : root.width > Kirigami.Units.gridUnit * 27) && roomListLoaded
+ readonly property int pageWidth: {
+ if (Config.roomListPageWidth === -1) {
+ return defaultPageWidth;
+ } else if (Config.roomListPageWidth < minPageWidth) {
+ return collapsedPageWidth;
+ } else {
+ return Config.roomListPageWidth;
+ }
+ }
+
+ pageStack.defaultColumnWidth: pageWidth
+ pageStack.columnView.columnResizeMode: shouldUseSidebars ? Kirigami.ColumnView.FixedColumns : Kirigami.ColumnView.SingleColumn
+
+ MouseArea {
+ visible: root.pageStack.wideMode
+ z: 500
+
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+
+ x: root.pageStack.defaultColumnWidth - (width / 2)
+ width: Kirigami.Units.devicePixelRatio * 2
+
+ property int _lastX: -1
+ enabled: !Kirigami.Settings.isMobile
+
+ cursorShape: !Kirigami.Settings.isMobile ? Qt.SplitHCursor : undefined
+
+ onPressed: _lastX = mouseX
+ onReleased: Config.save();
+
+ onPositionChanged: {
+ if (_lastX == -1) {
+ return;
+ }
+
+ if (mouse.x > _lastX) {
+ // we moved to the right
+ if (Config.roomListPageWidth === root.collapsedPageWidth && root.pageWidth + (mouse.x - _lastX) >= root.minPageWidth) {
+ // Here we get back directly to a more wide mode.
+ Config.roomListPageWidth = root.minPageWidth;
+ if (root.width < Kirigami.Units.gridUnit * 35) {
+ root.width = Kirigami.Units.gridUnit * 35;
+ }
+ } else if (Config.roomListPageWidth !== root.collapsedPageWidth) {
+ // Increase page width
+ Config.roomListPageWidth = Math.min(root.defaultPageWidth, root.pageWidth + (mouse.x - _lastX));
+ }
+ } else if (mouse.x < _lastX) {
+ const tmpWidth = root.pageWidth - (_lastX - mouse.x);
+
+ if (tmpWidth < root.minPageWidth) {
+ Config.roomListPageWidth = root.collapsedPageWidth;
+ } else {
+ Config.roomListPageWidth = tmpWidth;
+ }
+ }
+ }
+ }
+
globalDrawer: Kirigami.GlobalDrawer {
property bool hasLayer
diff --git a/src/neochatconfig.kcfg b/src/neochatconfig.kcfg
index adccfb73c..8acba0e2a 100644
--- a/src/neochatconfig.kcfg
+++ b/src/neochatconfig.kcfg
@@ -41,6 +41,9 @@
true
+
+ -1
+
diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp
index 856a330ff..c35e96a5b 100644
--- a/src/roomlistmodel.cpp
+++ b/src/roomlistmodel.cpp
@@ -432,6 +432,24 @@ QString RoomListModel::categoryName(int section)
}
}
+QString RoomListModel::categoryIconName(int section)
+{
+ switch (section) {
+ case 1:
+ return QStringLiteral("user-invisible");
+ case 2:
+ return QStringLiteral("favorite");
+ case 3:
+ return QStringLiteral("dialog-messages");
+ case 4:
+ return QStringLiteral("group");
+ case 5:
+ return QStringLiteral("object-order-lower");
+ default:
+ return QStringLiteral("tools-report-bug");
+ }
+}
+
void RoomListModel::setCategoryVisible(int category, bool visible)
{
beginResetModel();
diff --git a/src/roomlistmodel.h b/src/roomlistmodel.h
index 924f93caa..4bcb06142 100644
--- a/src/roomlistmodel.h
+++ b/src/roomlistmodel.h
@@ -69,6 +69,7 @@ public:
[[nodiscard]] QHash roleNames() const override;
Q_INVOKABLE [[nodiscard]] static QString categoryName(int section);
+ Q_INVOKABLE [[nodiscard]] static QString categoryIconName(int section);
Q_INVOKABLE void setCategoryVisible(int category, bool visible);
Q_INVOKABLE [[nodiscard]] bool categoryVisible(int category) const;