import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import QtQuick.Controls.Material 2.2 import QtQml.Models 2.3 import Spectral 0.1 import SortFilterProxyModel 0.2 import Spectral.Settings 0.1 import "../component" import "../menu" import "qrc:/js/util.js" as Util Rectangle { property alias listModel: sortedRoomListModel.sourceModel property int filter: 0 property var enteredRoom: null color: MSettings.darkTheme ? "#323232" : "#f3f3f3" Label { text: MSettings.miniMode ? "Empty" : "Here? No, not here." anchors.centerIn: parent visible: listView.count === 0 } ColumnLayout { anchors.fill: parent spacing: 0 TextField { Layout.fillWidth: true Layout.preferredHeight: 40 Layout.margins: 12 id: searchField leftPadding: MSettings.miniMode ? 4 : 32 topPadding: 0 bottomPadding: 0 placeholderText: "Search..." background: Rectangle { color: MSettings.darkTheme ? "#303030" : "#fafafa" layer.enabled: true layer.effect: ElevationEffect { elevation: searchField.focus ? 2 : 1 } } Shortcut { sequence: StandardKey.Find onActivated: searchField.forceActiveFocus() } } SortFilterProxyModel { id: sortedRoomListModel proxyRoles: ExpressionRole { name: "display" expression: { switch (category) { case 1: return "Invited" case 2: return "Favorites" case 3: return "Rooms" case 4: return "People" case 5: return "Low Priority" } } } sorters: [ RoleSorter { roleName: "category" }, RoleSorter { roleName: "lastActiveTime" sortOrder: Qt.DescendingOrder } ] } SortFilterProxyModel { id: roomListProxyModel sourceModel: sortedRoomListModel filters: [ RegExpFilter { roleName: "name" pattern: searchField.text caseSensitivity: Qt.CaseInsensitive }, ExpressionFilter { enabled: filter === 1 expression: unreadCount > 0 }, ExpressionFilter { enabled: filter === 2 expression: category === 1 || category === 2 || category === 4 }, ExpressionFilter { enabled: filter === 3 expression: category === 3 || category === 5 } ] } ListView { Layout.fillWidth: true Layout.fillHeight: true id: listView spacing: 1 clip: true model: roomListProxyModel currentIndex: -1 highlightFollowsCurrentItem: true highlightMoveDuration: 200 highlightResizeDuration: 0 boundsBehavior: Flickable.DragOverBounds ScrollBar.vertical: ScrollBar {} delegate: Rectangle { readonly property bool highlighted: currentRoom === enteredRoom width: parent.width height: 64 color: MSettings.darkTheme ? "#303030" : "#fafafa" AutoMouseArea { anchors.fill: parent hoverEnabled: MSettings.miniMode onSecondaryClicked: { roomContextMenu.model = model roomContextMenu.popup() } onPrimaryClicked: { if (category === RoomType.Invited) { inviteDialog.currentRoom = currentRoom inviteDialog.open() } else { enteredRoom = currentRoom } } ToolTip.visible: MSettings.miniMode && containsMouse ToolTip.text: name } Rectangle { anchors.fill: parent visible: highlightCount > 0 || highlighted color: Material.accent opacity: 0.1 } Rectangle { width: unreadCount > 0 || highlighted ? 4 : 0 height: parent.height color: Material.accent Behavior on width { PropertyAnimation { easing.type: Easing.InOutCubic; duration: 200 } } } RowLayout { anchors.fill: parent anchors.margins: 12 spacing: 12 ImageItem { id: imageItem Layout.preferredWidth: height Layout.fillHeight: true hint: name || "No Name" image: avatar } ColumnLayout { Layout.fillWidth: true Layout.fillHeight: true Layout.alignment: Qt.AlignHCenter visible: parent.width > 64 Label { Layout.fillWidth: true Layout.fillHeight: true text: name || "No Name" font.pointSize: 12 elide: Text.ElideRight wrapMode: Text.NoWrap } Label { Layout.fillWidth: true Layout.fillHeight: true text: (lastEvent == "" ? topic : lastEvent).replace(/(\r\n\t|\n|\r\t)/gm,"") elide: Text.ElideRight wrapMode: Text.NoWrap } } } } section.property: "display" section.criteria: ViewSection.FullString section.delegate: Label { width: parent.width height: 24 text: section color: "grey" leftPadding: MSettings.miniMode ? undefined : 16 elide: Text.ElideRight verticalAlignment: Text.AlignVCenter horizontalAlignment: MSettings.miniMode ? Text.AlignHCenter : undefined } RoomContextMenu { id: roomContextMenu } Dialog { property var currentRoom id: inviteDialog parent: ApplicationWindow.overlay x: (window.width - width) / 2 y: (window.height - height) / 2 width: 360 title: "Action Required" modal: true standardButtons: Dialog.Ok | Dialog.Cancel contentItem: Label { text: "Accept this invitation?" } onAccepted: currentRoom.acceptInvitation() onRejected: currentRoom.forget() } } } }