From 64749ba32fc5956d6580dc8862c71e513a675963 Mon Sep 17 00:00:00 2001 From: Black Hat Date: Sun, 2 Sep 2018 21:26:42 +0800 Subject: [PATCH 1/6] First UI redesign. --- qml/Room.qml | 37 ++-- qml/component/SideNavButton.qml | 36 ++-- qml/component/TextDelegate.qml | 4 +- qml/form/RoomForm.qml | 282 +++++++++++++++-------------- qml/form/RoomListForm.qml | 310 ++++++++++++++------------------ qml/main.qml | 45 ++++- qtquickcontrols2.conf | 6 +- 7 files changed, 354 insertions(+), 366 deletions(-) diff --git a/qml/Room.qml b/qml/Room.qml index 5e7217503..702f69ec3 100644 --- a/qml/Room.qml +++ b/qml/Room.qml @@ -18,28 +18,35 @@ Page { onNewMessage: if (!window.active) matriqueController.showMessage(roomName, content, icon) } - RowLayout { + Rectangle { anchors.fill: parent - spacing: 0 - RoomListForm { - id: roomListForm + color: MSettings.darkTheme ? "#363636" : "#f3f3f3" - Layout.fillHeight: true - Layout.preferredWidth: MSettings.miniMode ? 80 : page.width * 0.35 - Layout.minimumWidth: 80 - Layout.maximumWidth: 360 + RowLayout { + anchors.fill: parent - listModel: roomListModel - } + spacing: 0 - RoomForm { - id: roomForm + RoomListForm { + id: roomListForm - Layout.fillWidth: true - Layout.fillHeight: true + Layout.fillHeight: true + Layout.preferredWidth: MSettings.miniMode ? 64 : page.width * 0.35 + Layout.minimumWidth: 64 + Layout.maximumWidth: 360 - currentRoom: roomListForm.enteredRoom + listModel: roomListModel + } + + RoomForm { + id: roomForm + + Layout.fillWidth: true + Layout.fillHeight: true + + currentRoom: roomListForm.enteredRoom + } } } } diff --git a/qml/component/SideNavButton.qml b/qml/component/SideNavButton.qml index e57d1bce9..8c9bf2749 100644 --- a/qml/component/SideNavButton.qml +++ b/qml/component/SideNavButton.qml @@ -3,41 +3,29 @@ import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import QtQuick.Controls.Material 2.2 -Item { +ItemDelegate { property var page - property alias contentItem: buttonDelegate.contentItem - signal clicked - - id: sideNavButton - - Layout.fillWidth: true - Layout.preferredHeight: width + readonly property bool selected: stackView.currentItem === page Rectangle { - width: stackView.currentItem === page ? parent.width : 0 + width: selected ? 4 : 0 height: parent.height - anchors.bottom: buttonDelegate.bottom - color: Qt.lighter(Material.accent) + + color: Material.accent Behavior on width { PropertyAnimation { easing.type: Easing.InOutCubic; duration: 200 } } } - ItemDelegate { - id: buttonDelegate - anchors.fill: parent - - onClicked: { - if(page && stackView.currentItem !== page) { - if(stackView.depth === 1) { - stackView.replace(page) - } else { - stackView.clear() - stackView.push(page) - } + onClicked: { + if(page && stackView.currentItem !== page) { + if(stackView.depth === 1) { + stackView.replace(page) + } else { + stackView.clear() + stackView.push(page) } - sideNavButton.clicked() } } } diff --git a/qml/component/TextDelegate.qml b/qml/component/TextDelegate.qml index f0077324b..947017868 100644 --- a/qml/component/TextDelegate.qml +++ b/qml/component/TextDelegate.qml @@ -20,8 +20,8 @@ Rectangle { width: Math.min(Math.max(messageText.implicitWidth, (timeText.visible ? timeText.implicitWidth : 0), (authorLabelVisible ? authorText.implicitWidth : 0)) + 24, maximumWidth) height: (authorText.visible ? authorText.implicitHeight : 0) + messageText.implicitHeight + (timeText.visible ? timeText.implicitHeight : 0) + 24 - color: flat ? "transparent" : highlighted ? Material.accent : background - border.color: Material.accent + color: flat ? "transparent" : highlighted ? Material.primary : background + border.color: Material.primary border.width: flat ? 2 : 0 ColumnLayout { diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml index 6e9335331..92a00c7c7 100644 --- a/qml/form/RoomForm.qml +++ b/qml/form/RoomForm.qml @@ -39,7 +39,6 @@ Item { ColumnLayout { anchors.fill: parent anchors.margins: 32 - spacing: 16 ImageStatus { Layout.preferredWidth: 64 @@ -116,7 +115,7 @@ Item { RowLayout { anchors.fill: parent anchors.margins: 8 - spacing: 16 + spacing: 12 ImageStatus { Layout.preferredWidth: height @@ -159,9 +158,9 @@ Item { Rectangle { Layout.fillWidth: true - Layout.preferredHeight: 80 + Layout.preferredHeight: 64 - color: MSettings.darkTheme ? "#242424" : "#eaeaea" + color: Material.accent ItemDelegate { anchors.fill: parent @@ -170,9 +169,9 @@ Item { RowLayout { anchors.fill: parent - anchors.margins: 16 + anchors.margins: 12 - spacing: 16 + spacing: 12 ImageStatus { Layout.preferredWidth: height @@ -186,14 +185,15 @@ Item { Layout.fillHeight: true Layout.alignment: Qt.AlignHCenter - visible: parent.width > 80 + visible: parent.width > 64 Label { Layout.fillWidth: true Layout.fillHeight: true text: currentRoom ? currentRoom.displayName : "" - font.pointSize: 16 + color: "white" + font.pointSize: 12 elide: Text.ElideRight wrapMode: Text.NoWrap } @@ -203,6 +203,7 @@ Item { Layout.fillHeight: true text: currentRoom ? currentRoom.topic : "" + color: "white" elide: Text.ElideRight wrapMode: Text.NoWrap } @@ -304,7 +305,7 @@ Item { RoundButton { id: goTopFab - width: height + width: 64 height: 64 visible: !parent.atYEnd @@ -313,12 +314,12 @@ Item { contentItem: MaterialIcon { anchors.fill: parent + icon: "\ue313" color: "white" } - opacity: pressed ? 1 : hovered ? 0.7 : 0.4 - Material.background: Qt.lighter(Material.accent) + Material.background: Material.accent onClicked: parent.positionViewAtBeginning() @@ -334,152 +335,149 @@ Item { } } - Pane { - padding: 16 - + RowLayout { Layout.fillWidth: true - Layout.preferredHeight: 80 + Layout.preferredHeight: 48 + Layout.margins: 16 - Timer { - id: timeoutTimer + spacing: 0 - repeat: false - interval: 2000 - onTriggered: { - repeatTimer.stop() - currentRoom.sendTypingNotification(false) + ItemDelegate { + Layout.preferredWidth: 48 + Layout.preferredHeight: 48 + + contentItem: MaterialIcon { icon: "\ue226" } + + onClicked: currentRoom.chooseAndUploadFile() + } + + TextField { + property real progress: 0 + + id: inputField + Layout.fillWidth: true + Layout.preferredHeight: 48 + placeholderText: "Send a Message" + leftPadding: 16 + topPadding: 0 + bottomPadding: 0 + selectByMouse: true + + text: currentRoom ? currentRoom.cachedInput : "" + + onTextChanged: { + timeoutTimer.restart() + repeatTimer.start() + currentRoom.cachedInput = text + } + + Keys.onReturnPressed: { + if (inputField.text) { + inputField.postMessage(inputField.text) + inputField.text = "" + } + } + + background: Rectangle { + color: MSettings.darkTheme ? "#242424" : "#eaeaea" + } + + ToolTip.visible: currentRoom && currentRoom.hasUsersTyping + ToolTip.text: currentRoom ? currentRoom.usersTyping : "" + + Timer { + id: timeoutTimer + + repeat: false + interval: 2000 + onTriggered: { + repeatTimer.stop() + currentRoom.sendTypingNotification(false) + } + } + + Timer { + id: repeatTimer + + repeat: true + interval: 5000 + triggeredOnStart: true + onTriggered: currentRoom.sendTypingNotification(true) + } + + function postMessage(text) { + if (text.trim().length === 0) { return } + if(!currentRoom) { return } + + var PREFIX_ME = '/me ' + var PREFIX_NOTICE = '/notice ' + var PREFIX_RAINBOW = '/rainbow ' + var PREFIX_HTML = '/html ' + var PREFIX_MARKDOWN = '/md ' + + if (text.indexOf(PREFIX_ME) === 0) { + text = text.substr(PREFIX_ME.length) + currentRoom.postMessage(text, RoomMessageEvent.Emote) + return + } + if (text.indexOf(PREFIX_NOTICE) === 0) { + text = text.substr(PREFIX_NOTICE.length) + currentRoom.postMessage(text, RoomMessageEvent.Notice) + return + } + if (text.indexOf(PREFIX_RAINBOW) === 0) { + text = text.substr(PREFIX_RAINBOW.length) + + var parsedText = "" + var rainbowColor = ["#ff2b00", "#ff5500", "#ff8000", "#ffaa00", "#ffd500", "#ffff00", "#d4ff00", "#aaff00", "#80ff00", "#55ff00", "#2bff00", "#00ff00", "#00ff2b", "#00ff55", "#00ff80", "#00ffaa", "#00ffd5", "#00ffff", "#00d4ff", "#00aaff", "#007fff", "#0055ff", "#002bff", "#0000ff", "#2a00ff", "#5500ff", "#7f00ff", "#aa00ff", "#d400ff", "#ff00ff", "#ff00d4", "#ff00aa", "#ff0080", "#ff0055", "#ff002b", "#ff0000"] + for (var i = 0; i < text.length; i++) { + parsedText = parsedText + "" + text.charAt(i) + "" + } + currentRoom.postHtmlMessage(text, parsedText, RoomMessageEvent.Text) + return + } + if (text.indexOf(PREFIX_HTML) === 0) { + text = text.substr(PREFIX_HTML.length) + var re = new RegExp("<.*?>") + var plainText = text.replace(re, "") + currentRoom.postHtmlMessage(plainText, text, RoomMessageEvent.Text) + return + } + if (text.indexOf(PREFIX_MARKDOWN) === 0) { + text = text.substr(PREFIX_MARKDOWN.length) + var parsedText = Markdown.markdown_parser(text) + currentRoom.postHtmlMessage(text, parsedText, RoomMessageEvent.Text) + return + } + + currentRoom.postPlainText(text) } } - Timer { - id: repeatTimer + ItemDelegate { + id: emojiButton - repeat: true - interval: 5000 - triggeredOnStart: true - onTriggered: currentRoom.sendTypingNotification(true) - } + Layout.preferredWidth: 48 + Layout.preferredHeight: 48 - RowLayout { - anchors.fill: parent - spacing: 0 + contentItem: MaterialIcon { icon: "\ue24e" } - ItemDelegate { - Layout.preferredWidth: height - Layout.fillHeight: true + background: Rectangle { color: MSettings.darkTheme ? "#242424" : "#eaeaea" } - contentItem: MaterialIcon { icon: "\ue226" } + onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.open() - onClicked: currentRoom.chooseAndUploadFile() - } + EmojiPicker { + id: emojiPicker - TextField { - property real progress: 0 + parent: ApplicationWindow.overlay - id: inputField - Layout.fillWidth: true - Layout.fillHeight: true - placeholderText: "Send a Message" - leftPadding: 16 - topPadding: 0 - bottomPadding: 0 - selectByMouse: true + x: window.width - 370 + y: window.height - 440 - text: currentRoom ? currentRoom.cachedInput : "" - onTextChanged: { - timeoutTimer.restart() - repeatTimer.start() - currentRoom.cachedInput = text - } + width: 360 + height: 360 - Keys.onReturnPressed: { - if (inputField.text) { - inputField.postMessage(inputField.text) - inputField.text = "" - } - } - - background: Rectangle { - color: MSettings.darkTheme ? "#242424" : "#eaeaea" - } - - ToolTip.visible: currentRoom && currentRoom.hasUsersTyping - ToolTip.text: currentRoom ? currentRoom.usersTyping : "" - - function postMessage(text) { - if (text.trim().length === 0) { return } - if(!currentRoom) { return } - - var PREFIX_ME = '/me ' - var PREFIX_NOTICE = '/notice ' - var PREFIX_RAINBOW = '/rainbow ' - var PREFIX_HTML = '/html ' - var PREFIX_MARKDOWN = '/md ' - - if (text.indexOf(PREFIX_ME) === 0) { - text = text.substr(PREFIX_ME.length) - currentRoom.postMessage(text, RoomMessageEvent.Emote) - return - } - if (text.indexOf(PREFIX_NOTICE) === 0) { - text = text.substr(PREFIX_NOTICE.length) - currentRoom.postMessage(text, RoomMessageEvent.Notice) - return - } - if (text.indexOf(PREFIX_RAINBOW) === 0) { - text = text.substr(PREFIX_RAINBOW.length) - - var parsedText = "" - var rainbowColor = ["#ff2b00", "#ff5500", "#ff8000", "#ffaa00", "#ffd500", "#ffff00", "#d4ff00", "#aaff00", "#80ff00", "#55ff00", "#2bff00", "#00ff00", "#00ff2b", "#00ff55", "#00ff80", "#00ffaa", "#00ffd5", "#00ffff", "#00d4ff", "#00aaff", "#007fff", "#0055ff", "#002bff", "#0000ff", "#2a00ff", "#5500ff", "#7f00ff", "#aa00ff", "#d400ff", "#ff00ff", "#ff00d4", "#ff00aa", "#ff0080", "#ff0055", "#ff002b", "#ff0000"] - for (var i = 0; i < text.length; i++) { - parsedText = parsedText + "" + text.charAt(i) + "" - } - currentRoom.postHtmlMessage(text, parsedText, RoomMessageEvent.Text) - return - } - if (text.indexOf(PREFIX_HTML) === 0) { - text = text.substr(PREFIX_HTML.length) - var re = new RegExp("<.*?>") - var plainText = text.replace(re, "") - currentRoom.postHtmlMessage(plainText, text, RoomMessageEvent.Text) - return - } - if (text.indexOf(PREFIX_MARKDOWN) === 0) { - text = text.substr(PREFIX_MARKDOWN.length) - var parsedText = Markdown.markdown_parser(text) - currentRoom.postHtmlMessage(text, parsedText, RoomMessageEvent.Text) - return - } - - currentRoom.postPlainText(text) - } - } - - ItemDelegate { - id: emojiButton - - Layout.preferredWidth: height - Layout.fillHeight: true - - contentItem: MaterialIcon { icon: "\ue24e" } - - background: Rectangle { color: MSettings.darkTheme ? "#242424" : "#eaeaea" } - - onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.open() - - EmojiPicker { - id: emojiPicker - - parent: ApplicationWindow.overlay - - x: window.width - 370 - y: window.height - 440 - - width: 360 - height: 360 - - textArea: inputField - } + textArea: inputField } } } diff --git a/qml/form/RoomListForm.qml b/qml/form/RoomListForm.qml index bab3097ab..f9943b593 100644 --- a/qml/form/RoomListForm.qml +++ b/qml/form/RoomListForm.qml @@ -14,215 +14,183 @@ Item { property alias listModel: roomListProxyModel.sourceModel property var enteredRoom: null + Label { + z: 10 + text: MSettings.miniMode ? "Empty" : "Here? No, not here." + anchors.centerIn: parent + visible: listView.count === 0 + } + ColumnLayout { anchors.fill: parent spacing: 0 - Rectangle { - z: 10 + TextField { + id: searchField Layout.fillWidth: true - Layout.preferredHeight: 80 - color: Qt.tint(Material.accent, "#20FFFFFF") + Layout.preferredHeight: 40 + Layout.margins: 12 + leftPadding: MSettings.miniMode ? 4 : 32 + topPadding: 0 + bottomPadding: 0 + placeholderText: "Search..." - TextField { - id: searchField - width: parent.width - 18 - height: 36 - color: "white" - leftPadding: MSettings.miniMode ? 4 : 32 - topPadding: 0 - bottomPadding: 0 - anchors.centerIn: parent + background: Rectangle { + color: MSettings.darkTheme ? "#242424" : "#fafafa" + } - background: Row { - visible: !parent.text - - MaterialIcon { - icon: "\ue8b6" - color: "white" - - width: MSettings.miniMode ? parent.width : parent.height - height: parent.height - } - - Label { - height: parent.height - visible: !MSettings.miniMode - text: "Search" - color: "white" - font.pointSize: 12 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - } - - Shortcut { - sequence: StandardKey.Find - onActivated: searchField.forceActiveFocus() - } + Shortcut { + sequence: StandardKey.Find + onActivated: searchField.forceActiveFocus() } } - Rectangle { + SortFilterProxyModel { + id: roomListProxyModel + filters: RegExpFilter { + roleName: "name" + pattern: searchField.text + caseSensitivity: Qt.CaseInsensitive + } + 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 Priorities" + } + } + } + + sorters: [ + RoleSorter { roleName: "category" }, + RoleSorter { + enabled: MSettings.rearrangeByActivity + roleName: "unreadCount" + sortOrder: Qt.DescendingOrder + }, + StringSorter { roleName: "name" } + ] + } + + ListView { Layout.fillWidth: true Layout.fillHeight: true - color: MSettings.darkTheme ? "#242424" : "#eaeaea" + id: listView - Label { - z: 10 - text: MSettings.miniMode ? "Empty" : "Here? No, not here." - anchors.centerIn: parent - visible: listView.count === 0 - } + spacing: 1 + clip: true - SortFilterProxyModel { - id: roomListProxyModel - filters: RegExpFilter { - roleName: "name" - pattern: searchField.text - caseSensitivity: Qt.CaseInsensitive - } - 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 Priorities" - } - } + model: roomListProxyModel + + currentIndex: -1 + + boundsBehavior: Flickable.DragOverBounds + + ScrollBar.vertical: ScrollBar {} + + delegate: Rectangle { + readonly property bool highlighted: currentRoom === enteredRoom + + width: parent.width + height: 64 + + color: "#fafafa" + + AutoMouseArea { + anchors.fill: parent + + hoverEnabled: MSettings.miniMode + + onSecondaryClicked: Qt.createComponent("qrc:/qml/menu/RoomContextMenu.qml").createObject(this) + onPrimaryClicked: category === RoomType.Invited ? inviteDialog.open() : enteredRoom = currentRoom + + ToolTip.visible: MSettings.miniMode && containsMouse + ToolTip.text: name } - sorters: [ - RoleSorter { roleName: "category" }, - RoleSorter { - enabled: MSettings.rearrangeByActivity - roleName: "unreadCount" - sortOrder: Qt.DescendingOrder - }, - StringSorter { roleName: "name" } - ] - } + Rectangle { + width: 4 + height: parent.height + color: Material.accent + visible: unreadCount > 0 || highlighted + } - ListView { - id: listView - anchors.fill: parent + RowLayout { + anchors.fill: parent + anchors.margins: 12 + spacing: 12 - model: roomListProxyModel + ImageStatus { + Layout.preferredWidth: height + Layout.fillHeight: true - currentIndex: -1 - - boundsBehavior: Flickable.DragOverBounds - - ScrollBar.vertical: ScrollBar { id: scrollBar } - - delegate: Rectangle { - readonly property bool highlighted: currentRoom === enteredRoom - - id: swipeDelegate - width: parent.width - height: 80 - - color: highlighted ? Material.background : "transparent" - - AutoMouseArea { - anchors.fill: parent - - hoverEnabled: MSettings.miniMode - - onSecondaryClicked: Qt.createComponent("qrc:/qml/menu/RoomContextMenu.qml").createObject(this) - onPrimaryClicked: category === RoomType.Invited ? inviteDialog.open() : enteredRoom = currentRoom - - ToolTip.visible: MSettings.miniMode && containsMouse - ToolTip.text: name + source: avatar ? "image://mxc/" + avatar : "" + displayText: name } - Rectangle { - width: 4 - height: parent.height - color: Qt.tint(Material.accent, "#20FFFFFF") - visible: unreadCount > 0 || highlighted - } + ColumnLayout { + Layout.fillWidth: true + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter - RowLayout { - anchors.fill: parent - anchors.margins: 16 - spacing: 16 + visible: parent.width > 64 - ImageStatus { - Layout.preferredWidth: height - Layout.fillHeight: true - - source: avatar ? "image://mxc/" + avatar : "" - displayText: name - } - - ColumnLayout { + Label { Layout.fillWidth: true Layout.fillHeight: true - Layout.alignment: Qt.AlignHCenter - visible: parent.width > 80 + text: name || "No Name" + font.pointSize: 12 + elide: Text.ElideRight + wrapMode: Text.NoWrap + } - Label { - Layout.fillWidth: true - Layout.fillHeight: true + Label { + Layout.fillWidth: true + Layout.fillHeight: true - text: name || "No Name" - font.pointSize: 16 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: lastEvent || topic - elide: Text.ElideRight - wrapMode: Text.NoWrap - } + text: (lastEvent || topic).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 - background: Rectangle { - anchors.fill: parent - color: MSettings.darkTheme ? "#363636" : "#dbdbdb" - } - } + 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 + } - Dialog { - id: inviteDialog - parent: ApplicationWindow.overlay + Dialog { + id: inviteDialog + parent: ApplicationWindow.overlay - x: (window.width - width) / 2 - y: (window.height - height) / 2 - width: 360 + x: (window.width - width) / 2 + y: (window.height - height) / 2 + width: 360 - title: "Action Required" - modal: true - standardButtons: Dialog.Ok | Dialog.Cancel + title: "Action Required" + modal: true + standardButtons: Dialog.Ok | Dialog.Cancel - contentItem: Label { text: "Accept this invitation?" } + contentItem: Label { text: "Accept this invitation?" } - onAccepted: currentRoom.acceptInvitation() - onRejected: currentRoom.forget() - } + onAccepted: currentRoom.acceptInvitation() + onRejected: currentRoom.forget() } } } diff --git a/qml/main.qml b/qml/main.qml index 83d917d98..1f06ca1d0 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -82,19 +82,21 @@ ApplicationWindow { Rectangle { id: sideNav - Layout.preferredWidth: 80 + Layout.preferredWidth: 64 Layout.fillHeight: true - color: Material.accent + color: Material.primary ColumnLayout { anchors.fill: parent spacing: 0 SideNavButton { - id: statusNavButton - contentItem: ImageStatus { + Layout.fillWidth: true + Layout.preferredHeight: width + + ImageStatus { anchors.fill: parent - anchors.margins: 15 + anchors.margins: 12 source: matriqueController.isLogin ? connection.localUser && connection.localUser.avatarUrl ? "image://mxc/" + connection.localUser.avatarUrl : "" : "qrc:/asset/img/avatar.png" displayText: matriqueController.isLogin && connection.localUser.displayName ? connection.localUser.displayName : "" @@ -109,7 +111,16 @@ ApplicationWindow { } SideNavButton { - contentItem: MaterialIcon { icon: "\ue145"; color: "white" } + Layout.fillWidth: true + Layout.preferredHeight: width + + MaterialIcon { + anchors.fill: parent + + icon: "\ue145" + color: "white" + } + onClicked: addRoomMenu.popup() Menu { @@ -171,6 +182,7 @@ ApplicationWindow { onAccepted: matriqueController.joinRoom(joinRoomDialogTextField.text) } } + MenuItem { text: "Direct Chat" onTriggered: directChatDialog.open() @@ -199,12 +211,29 @@ ApplicationWindow { } SideNavButton { - contentItem: MaterialIcon { icon: "\ue8b8"; color: "white" } + Layout.fillWidth: true + Layout.preferredHeight: width + + MaterialIcon { + anchors.fill: parent + + icon: "\ue8b8" + color: parent.highlighted ? Material.accent : "white" + } page: settingPage } SideNavButton { - contentItem: MaterialIcon { icon: "\ue879"; color: "white" } + Layout.fillWidth: true + Layout.preferredHeight: width + + MaterialIcon { + anchors.fill: parent + + icon: "\ue879" + color: "white" + } + onClicked: Qt.quit() } } diff --git a/qtquickcontrols2.conf b/qtquickcontrols2.conf index fdec96c3a..0cc53197c 100644 --- a/qtquickcontrols2.conf +++ b/qtquickcontrols2.conf @@ -7,9 +7,7 @@ Style=Material [Material] Theme=Light -Primary=#00695c -Accent=#00695c -;Primary=#1565c0 -;Accent=#1565c0 +Primary=#344955 +Accent=#498882 ;Foreground=Black ;Background=#161616 From 104e194cfb5e6e90310bdd318cedb2b4802f7c08 Mon Sep 17 00:00:00 2001 From: Black Hat Date: Mon, 3 Sep 2018 07:13:39 +0800 Subject: [PATCH 2/6] Change some color. --- qml/Room.qml | 8 +++++++- qml/Setting.qml | 20 +++++++++----------- qml/form/RoomForm.qml | 5 +++-- qml/form/RoomListForm.qml | 16 ++++++++++++++-- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/qml/Room.qml b/qml/Room.qml index 702f69ec3..ed1f17b56 100644 --- a/qml/Room.qml +++ b/qml/Room.qml @@ -21,7 +21,7 @@ Page { Rectangle { anchors.fill: parent - color: MSettings.darkTheme ? "#363636" : "#f3f3f3" + color: MSettings.darkTheme ? "#323232" : "#f3f3f3" RowLayout { anchors.fill: parent @@ -39,6 +39,12 @@ Page { listModel: roomListModel } + Rectangle { + Layout.preferredWidth: 1 + Layout.fillHeight: true + color: MSettings.darkTheme ? "#363636" : "#ececec" + } + RoomForm { id: roomForm diff --git a/qml/Setting.qml b/qml/Setting.qml index 1b739f419..968ee5b4d 100644 --- a/qml/Setting.qml +++ b/qml/Setting.qml @@ -65,32 +65,24 @@ Page { checked: MSettings.lazyLoad onCheckedChanged: MSettings.lazyLoad = checked } + Switch { text: "Force loading message delegates asynchronously" checked: MSettings.asyncMessageDelegate onCheckedChanged: MSettings.asyncMessageDelegate = checked } + Switch { text: "Use RichText instead of StyledText" checked: MSettings.richText onCheckedChanged: MSettings.richText = checked } + Switch { text: "Use press and hold instead of right click" checked: MSettings.pressAndHold onCheckedChanged: MSettings.pressAndHold = checked } - Switch { - text: "Rearrange rooms by activity" - checked: MSettings.rearrangeByActivity - onCheckedChanged: MSettings.rearrangeByActivity = checked - } - - Button { - text: "Invoke GC" - highlighted: true - onClicked: gc() - } } } @@ -109,6 +101,12 @@ Page { checked: MSettings.miniMode onCheckedChanged: MSettings.miniMode = checked } + + Switch { + text: "Rearrange rooms by activity" + checked: MSettings.rearrangeByActivity + onCheckedChanged: MSettings.rearrangeByActivity = checked + } } } diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml index 92a00c7c7..c94ec1289 100644 --- a/qml/form/RoomForm.qml +++ b/qml/form/RoomForm.qml @@ -226,6 +226,7 @@ Item { Layout.fillWidth: true Layout.fillHeight: true + clip: true displayMarginBeginning: 40 displayMarginEnd: 40 verticalLayoutDirection: ListView.BottomToTop @@ -379,7 +380,7 @@ Item { } background: Rectangle { - color: MSettings.darkTheme ? "#242424" : "#eaeaea" + color: MSettings.darkTheme ? "#282828" : "#eaeaea" } ToolTip.visible: currentRoom && currentRoom.hasUsersTyping @@ -462,7 +463,7 @@ Item { contentItem: MaterialIcon { icon: "\ue24e" } - background: Rectangle { color: MSettings.darkTheme ? "#242424" : "#eaeaea" } + background: Rectangle { color: MSettings.darkTheme ? "#282828" : "#eaeaea" } onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.open() diff --git a/qml/form/RoomListForm.qml b/qml/form/RoomListForm.qml index f9943b593..1b0aad7f0 100644 --- a/qml/form/RoomListForm.qml +++ b/qml/form/RoomListForm.qml @@ -36,7 +36,7 @@ Item { placeholderText: "Search..." background: Rectangle { - color: MSettings.darkTheme ? "#242424" : "#fafafa" + color: MSettings.darkTheme ? "#282828" : "#fafafa" } Shortcut { @@ -89,6 +89,11 @@ Item { currentIndex: -1 + highlightFollowsCurrentItem: true + + highlightMoveDuration: 200 + highlightResizeDuration: 0 + boundsBehavior: Flickable.DragOverBounds ScrollBar.vertical: ScrollBar {} @@ -99,7 +104,7 @@ Item { width: parent.width height: 64 - color: "#fafafa" + color: MSettings.darkTheme ? "#282828" : "#fafafa" AutoMouseArea { anchors.fill: parent @@ -113,6 +118,13 @@ Item { ToolTip.text: name } + Rectangle { + anchors.fill: parent + visible: highlighted + color: Material.accent + opacity: 0.1 + } + Rectangle { width: 4 height: parent.height From 0301590b44d2d3e229b288128a17ca0c9b2c89e5 Mon Sep 17 00:00:00 2001 From: Black Hat Date: Mon, 3 Sep 2018 09:56:21 +0800 Subject: [PATCH 3/6] Fix image delegate color && fix lastEvent. --- qml/component/ImageBubble.qml | 2 +- qml/form/RoomListForm.qml | 2 +- src/matriqueroom.cpp | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/qml/component/ImageBubble.qml b/qml/component/ImageBubble.qml index 887b37e31..979c67021 100644 --- a/qml/component/ImageBubble.qml +++ b/qml/component/ImageBubble.qml @@ -12,7 +12,7 @@ AvatarContainer { width: messageImage.width + 24 height: messageImage.height + 24 - color: sentByMe ? background : Material.accent + color: sentByMe ? background : Material.primary DownloadableContent { id: downloadable diff --git a/qml/form/RoomListForm.qml b/qml/form/RoomListForm.qml index 1b0aad7f0..ef7a0a610 100644 --- a/qml/form/RoomListForm.qml +++ b/qml/form/RoomListForm.qml @@ -166,7 +166,7 @@ Item { Layout.fillWidth: true Layout.fillHeight: true - text: (lastEvent || topic).replace(/(\r\n\t|\n|\r\t)/gm,""); + text: (lastEvent == "" ? topic : lastEvent).replace(/(\r\n\t|\n|\r\t)/gm,""); elide: Text.ElideRight wrapMode: Text.NoWrap } diff --git a/src/matriqueroom.cpp b/src/matriqueroom.cpp index dcd79ae2d..faa36c836 100644 --- a/src/matriqueroom.cpp +++ b/src/matriqueroom.cpp @@ -83,6 +83,7 @@ void MatriqueRoom::sendTypingNotification(bool isTyping) { QString MatriqueRoom::lastEvent() { if (timelineSize() == 0) return ""; const RoomEvent* lastEvent = messageEvents().rbegin()->get(); + if (lastEvent->contentJson().value("body").toString() == "") return ""; return user(lastEvent->senderId())->displayname() + ": " + lastEvent->contentJson().value("body").toString(); } From 2f080f21ced81fc88162c14e32020132d5d06243 Mon Sep 17 00:00:00 2001 From: Black Hat Date: Tue, 4 Sep 2018 14:58:41 +0800 Subject: [PATCH 4/6] Rewrite MessageDelegate. --- matrique.pro | 7 +- qml/MatriqueSettings.qml | 1 - qml/Setting.qml | 6 - qml/component/AudioBubble.qml | 50 -------- qml/component/AutoLabel.qml | 15 +++ qml/component/AvatarContainer.qml | 26 ---- qml/component/FileBubble.qml | 28 ----- qml/component/GenericBubble.qml | 24 ++++ qml/component/ImageBubble.qml | 34 ------ qml/component/MessageBubble.qml | 20 --- qml/component/MessageDelegate.qml | 195 +++++++++++++++++++++++++----- qml/component/StateBubble.qml | 12 -- qml/component/StateDelegate.qml | 23 ++++ qml/component/TextDelegate.qml | 61 ---------- qml/form/RoomForm.qml | 77 ++++++------ qml/main.qml | 2 +- qml/menu/MessageContextMenu.qml | 4 +- res.qrc | 10 +- 18 files changed, 272 insertions(+), 323 deletions(-) delete mode 100644 qml/component/AudioBubble.qml create mode 100644 qml/component/AutoLabel.qml delete mode 100644 qml/component/AvatarContainer.qml delete mode 100644 qml/component/FileBubble.qml create mode 100644 qml/component/GenericBubble.qml delete mode 100644 qml/component/ImageBubble.qml delete mode 100644 qml/component/MessageBubble.qml delete mode 100644 qml/component/StateBubble.qml create mode 100644 qml/component/StateDelegate.qml delete mode 100644 qml/component/TextDelegate.qml diff --git a/matrique.pro b/matrique.pro index 5a6d65a2a..f27d296f3 100644 --- a/matrique.pro +++ b/matrique.pro @@ -1,7 +1,9 @@ QT += quick widgets multimedia CONFIG += c++14 CONFIG += object_parallel_to_source -CONFIG += qtquickcompiler + +# Enable this to use QtQuick Compiler. +#CONFIG += qtquickcompiler TARGET = matrique @@ -75,10 +77,9 @@ DISTFILES += \ ButtonDelegate.qml \ SideNav.qml \ RoomListForm.qml \ - RoomDetailForm.qml \ Room.qml \ Setting.qml \ - qml/js/md.js + qml/js/md.js \ HEADERS += \ src/controller.h \ diff --git a/qml/MatriqueSettings.qml b/qml/MatriqueSettings.qml index 6bcdbb560..1c8ead167 100644 --- a/qml/MatriqueSettings.qml +++ b/qml/MatriqueSettings.qml @@ -4,7 +4,6 @@ import Qt.labs.settings 1.0 Settings { property bool lazyLoad: true - property bool asyncMessageDelegate property bool richText property bool pressAndHold property bool rearrangeByActivity diff --git a/qml/Setting.qml b/qml/Setting.qml index 968ee5b4d..d26815930 100644 --- a/qml/Setting.qml +++ b/qml/Setting.qml @@ -66,12 +66,6 @@ Page { onCheckedChanged: MSettings.lazyLoad = checked } - Switch { - text: "Force loading message delegates asynchronously" - checked: MSettings.asyncMessageDelegate - onCheckedChanged: MSettings.asyncMessageDelegate = checked - } - Switch { text: "Use RichText instead of StyledText" checked: MSettings.richText diff --git a/qml/component/AudioBubble.qml b/qml/component/AudioBubble.qml deleted file mode 100644 index e01f5aeca..000000000 --- a/qml/component/AudioBubble.qml +++ /dev/null @@ -1,50 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.Material 2.2 -import QtMultimedia 5.9 -import Qt.labs.platform 1.0 - -AvatarContainer { - readonly property var downloadAndOpen: downloadable.downloadAndOpen - readonly property var saveFileAs: downloadable.saveFileAs - - property bool playOnFinished: false - - id: messageRow - - DownloadableContent { - id: downloadable - - width: downloadDelegate.width - height: downloadDelegate.height - - TextDelegate { - id: downloadDelegate - - maximumWidth: messageListView.width - highlighted: !sentByMe - timeLabelVisible: false - authorLabelVisible: false - - displayText: content.info.duration / 1000 + '"' - - MouseArea { - anchors.fill: parent - - propagateComposedEvents: true - - onClicked: { - if (downloadable.downloaded) - matriqueController.playAudio(progressInfo.localPath) - else - { - playOnFinished = true - currentRoom.downloadFile(eventId, StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_") + ".tmp") - } - } - } - } - onDownloadedChanged: downloaded && playOnFinished ? matriqueController.playAudio(progressInfo.localPath) : {} - } - -} diff --git a/qml/component/AutoLabel.qml b/qml/component/AutoLabel.qml new file mode 100644 index 000000000..238c83117 --- /dev/null +++ b/qml/component/AutoLabel.qml @@ -0,0 +1,15 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.2 +import Matrique.Settings 0.1 + +Label { + property bool coloredBackground + + color: coloredBackground ? "white": Material.foreground + + wrapMode: Label.Wrap + linkColor: coloredBackground ? "white" : Material.accent + textFormat: MSettings.richText ? Text.RichText : Text.StyledText + onLinkActivated: Qt.openUrlExternally(link) +} diff --git a/qml/component/AvatarContainer.qml b/qml/component/AvatarContainer.qml deleted file mode 100644 index 64c4599be..000000000 --- a/qml/component/AvatarContainer.qml +++ /dev/null @@ -1,26 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 - -Row { - readonly property bool avatarVisible: !(sentByMe || (aboveAuthor === author && section === aboveSection)) - - spacing: 6 - - ImageStatus { - id: avatar - - width: height - height: 40 - round: false - visible: avatarVisible - source: author.avatarUrl != "" ? "image://mxc/" + author.avatarUrl : null - displayText: author.displayName - } - - Rectangle { - width: height - height: 40 - color: "transparent" - visible: !avatarVisible - } -} diff --git a/qml/component/FileBubble.qml b/qml/component/FileBubble.qml deleted file mode 100644 index 4ff77bd21..000000000 --- a/qml/component/FileBubble.qml +++ /dev/null @@ -1,28 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.Material 2.2 - -AvatarContainer { - readonly property var downloadAndOpen: downloadable.downloadAndOpen - readonly property var saveFileAs: downloadable.saveFileAs - - id: messageRow - - DownloadableContent { - id: downloadable - - width: downloadDelegate.width - height: downloadDelegate.height - - TextDelegate { - id: downloadDelegate - - maximumWidth: messageListView.width - highlighted: !sentByMe - timeLabelVisible: false - authorLabelVisible: false - - displayText: "File: " + content.body - } - } -} diff --git a/qml/component/GenericBubble.qml b/qml/component/GenericBubble.qml new file mode 100644 index 000000000..369423ec2 --- /dev/null +++ b/qml/component/GenericBubble.qml @@ -0,0 +1,24 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.2 +import Matrique.Settings 0.1 + +Control { + property bool highlighted: false + property bool colored: false + + readonly property bool darkBackground: highlighted ? true : MSettings.darkTheme + readonly property color backgroundColor: MSettings.darkTheme ? "#242424" : "lightgrey" + + padding: 12 + + background: Rectangle { + color: colored ? Material.accent : highlighted ? Material.primary : backgroundColor + } + + AutoMouseArea { + anchors.fill: parent + + onSecondaryClicked: Qt.createComponent("qrc:/qml/menu/MessageContextMenu.qml").createObject(this) + } +} diff --git a/qml/component/ImageBubble.qml b/qml/component/ImageBubble.qml deleted file mode 100644 index 979c67021..000000000 --- a/qml/component/ImageBubble.qml +++ /dev/null @@ -1,34 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.Material 2.2 - -AvatarContainer { - readonly property var downloadAndOpen: downloadable.downloadAndOpen - readonly property var saveFileAs: downloadable.saveFileAs - - Rectangle { - id: messageRect - - width: messageImage.width + 24 - height: messageImage.height + 24 - - color: sentByMe ? background : Material.primary - - DownloadableContent { - id: downloadable - - width: messageImage.width - height: messageImage.height - anchors.centerIn: parent - - AutoImage { - id: messageImage - z: -4 - sourceSize: 128 - source: "image://mxc/" + (content.thumbnail_url ? content.thumbnail_url : content.url) - - onClicked: downloadAndOpen() - } - } - } -} diff --git a/qml/component/MessageBubble.qml b/qml/component/MessageBubble.qml deleted file mode 100644 index 7e87caef1..000000000 --- a/qml/component/MessageBubble.qml +++ /dev/null @@ -1,20 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Layouts 1.3 -import QtQuick.Controls.Material 2.2 - -AvatarContainer { - readonly property bool isNotice: eventType === "notice" - - id: messageRow - - TextDelegate { - maximumWidth: messageListView.width - (!sentByMe ? 40 + messageRow.spacing : 0) - flat: isNotice - highlighted: !sentByMe - timeLabelVisible: Math.abs(time - aboveTime) > 600000 || index == 0 - authorLabelVisible: messageRow.avatarVisible - - displayText: display - } -} diff --git a/qml/component/MessageDelegate.qml b/qml/component/MessageDelegate.qml index e007cbf33..a78ab3547 100644 --- a/qml/component/MessageDelegate.qml +++ b/qml/component/MessageDelegate.qml @@ -1,53 +1,184 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 import QtQuick.Controls.Material 2.2 import Matrique 0.1 import Matrique.Settings 0.1 -Item { - readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden - readonly property color background: MSettings.darkTheme ? "#242424" : "lightgrey" +RowLayout { + readonly property bool avatarVisible: !(sentByMe || (aboveAuthor === author && section === aboveSection)) + readonly property bool highlighted: !sentByMe readonly property bool sentByMe: author === currentRoom.localUser - readonly property bool isState: eventType === "state" || eventType === "emote" + readonly property bool isText: eventType === "notice" || eventType === "message" - id: messageDelegate + signal saveFileAs() + signal openExternally() + + id: messageRow z: -5 - width: delegateLoader.width - height: delegateLoader.height - anchors.right: !isState && sentByMe ? parent.right : undefined - anchors.horizontalCenter: isState ? parent.horizontalCenter : undefined + Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft - AutoMouseArea { - anchors.fill: parent + spacing: 6 - onSecondaryClicked: Qt.createComponent("qrc:/qml/menu/MessageContextMenu.qml").createObject(this) + ImageStatus { + Layout.preferredWidth: 40 + Layout.preferredHeight: 40 + Layout.alignment: Qt.AlignTop + + round: false + visible: avatarVisible + source: author.avatarUrl != "" ? "image://mxc/" + author.avatarUrl : null + displayText: author.displayName } - Loader { - id: delegateLoader + Rectangle { + Layout.preferredWidth: 40 + Layout.preferredHeight: 40 + Layout.alignment: Qt.AlignTop - asynchronous: MSettings.asyncMessageDelegate + color: "transparent" + visible: !(sentByMe || avatarVisible) + } - source: { - if (eventType == "redaction" || hidden) return "" - switch (eventType) { - case "state": - case "emote": - return "StateBubble.qml" - case "message": - case "notice": - return "MessageBubble.qml" - case "image": - return "ImageBubble.qml" - case "audio": - return "AudioBubble.qml" - case "video": - case "file": - return "FileBubble.qml" + GenericBubble { + Layout.maximumWidth: messageListView.width - (!sentByMe ? 40 + messageRow.spacing : 0) + + id: genericBubble + + highlighted: !sentByMe + colored: highlighted && eventType === "notice" + + contentItem: ColumnLayout { + id: messageColumn + + spacing: 0 + + AutoLabel { + visible: messageRow.avatarVisible + text: author.displayName + Material.foreground: Material.accent + coloredBackground: highlighted + font.bold: true + } + + AutoLabel { + Layout.fillWidth: true + + text: display + visible: isText + coloredBackground: highlighted + } + + Loader { + sourceComponent: { + switch (eventType) { + case "image": + return imageComponent + case "file": + return fileComponent + case "audio": + return audioComponent + } + } + + active: eventType === "image" || eventType === "file" || eventType === "audio" + } + + AutoLabel { + Layout.alignment: Qt.AlignRight + visible: Math.abs(time - aboveTime) > 600000 || index == 0 + text: Qt.formatTime(time, "hh:mm") + coloredBackground: highlighted + Material.foreground: "grey" + font.pointSize: 8 + } + } + + Component { + id: imageComponent + + DownloadableContent { + id: downloadable + + width: messageImage.width + height: messageImage.height + + AutoImage { + id: messageImage + z: -4 + sourceSize: 128 + source: "image://mxc/" + (content.thumbnail_url ? content.thumbnail_url : content.url) + + onClicked: downloadAndOpen() + } + + Component.onCompleted: { + messageRow.saveFileAs.connect(saveFileAs) + messageRow.openExternally.connect(downloadAndOpen) + } + } + } + + Component { + id: fileComponent + + AutoLabel { + Layout.fillWidth: true + + id: downloadDelegate + + text: "File: " + content.body + coloredBackground: highlighted + + background: DownloadableContent { + id: downloadable + + Component.onCompleted: { + messageRow.saveFileAs.connect(saveFileAs) + messageRow.openExternally.connect(downloadAndOpen) + } + } + } + } + + Component { + id: audioComponent + + AutoLabel { + id: downloadDelegate + + text: content.info.duration / 1000 + '"' + coloredBackground: highlighted + + MouseArea { + anchors.fill: parent + + propagateComposedEvents: true + + onClicked: { + if (downloadable.downloaded) + matriqueController.playAudio(progressInfo.localPath) + else + { + playOnFinished = true + currentRoom.downloadFile(eventId, StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_") + ".tmp") + } + } + } + + background: DownloadableContent { + id: downloadable + + onDownloadedChanged: downloaded && playOnFinished ? matriqueController.playAudio(progressInfo.localPath) : {} + + Component.onCompleted: { + messageRow.saveFileAs.connect(saveFileAs) + messageRow.openExternally.connect(downloadAndOpen) + } + } } - return "" } } } diff --git a/qml/component/StateBubble.qml b/qml/component/StateBubble.qml deleted file mode 100644 index 693c6770c..000000000 --- a/qml/component/StateBubble.qml +++ /dev/null @@ -1,12 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.Material 2.2 - -TextDelegate { - maximumWidth: messageListView.width - highlighted: eventType === "emote" - timeLabelVisible: false - authorLabelVisible: false - - displayText: "" + author.displayName + " " + display -} diff --git a/qml/component/StateDelegate.qml b/qml/component/StateDelegate.qml new file mode 100644 index 000000000..376763fed --- /dev/null +++ b/qml/component/StateDelegate.qml @@ -0,0 +1,23 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 +import QtQuick.Controls.Material 2.2 +import Matrique.Settings 0.1 + +Label { + Layout.alignment: Qt.AlignHCenter + + text: "" + author.displayName + " " + display + color: "white" + + padding: 8 + + wrapMode: Label.Wrap + linkColor: "white" + textFormat: MSettings.richText ? Text.RichText : Text.StyledText + onLinkActivated: Qt.openUrlExternally(link) + + background: Rectangle { + color: MSettings.darkTheme ? "#484848" : "grey" + } +} diff --git a/qml/component/TextDelegate.qml b/qml/component/TextDelegate.qml deleted file mode 100644 index 947017868..000000000 --- a/qml/component/TextDelegate.qml +++ /dev/null @@ -1,61 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.Material 2.2 -import QtQuick.Layouts 1.3 -import Matrique.Settings 0.1 - -Rectangle { - property bool flat: false - property bool highlighted: false - property string displayText: "" - property alias timeLabelVisible: timeText.visible - property alias authorLabelVisible: authorText.visible - - property int maximumWidth - - readonly property bool darkBackground: highlighted && !flat - - id: messageRect - - width: Math.min(Math.max(messageText.implicitWidth, (timeText.visible ? timeText.implicitWidth : 0), (authorLabelVisible ? authorText.implicitWidth : 0)) + 24, maximumWidth) - height: (authorText.visible ? authorText.implicitHeight : 0) + messageText.implicitHeight + (timeText.visible ? timeText.implicitHeight : 0) + 24 - - color: flat ? "transparent" : highlighted ? Material.primary : background - border.color: Material.primary - border.width: flat ? 2 : 0 - - ColumnLayout { - id: messageColumn - - anchors.fill: parent - anchors.margins: 12 - spacing: 0 - - Label { - id: authorText - text: author.displayName - color: darkBackground ? "white" : Material.accent - font.bold: true - } - - Label { - id: messageText - Layout.maximumWidth: parent.width - text: displayText - color: darkBackground ? "white": Material.foreground - - wrapMode: Label.Wrap - linkColor: darkBackground ? "white" : Material.accent - textFormat: MSettings.richText ? Text.RichText : Text.StyledText - onLinkActivated: Qt.openUrlExternally(link) - } - - Label { - id: timeText - Layout.alignment: Qt.AlignRight - text: Qt.formatTime(time, "hh:mm") - color: darkBackground ? "white" : "grey" - font.pointSize: 8 - } - } -} diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml index c94ec1289..c8faaecb2 100644 --- a/qml/form/RoomForm.qml +++ b/qml/form/RoomForm.qml @@ -233,70 +233,67 @@ Item { spacing: 8 boundsBehavior: Flickable.DragOverBounds + maximumFlickVelocity: 2048 model: MessageEventModel { id: messageEventModel room: currentRoom } - delegate: Column { + delegate: ColumnLayout { readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden + id: delegateColumn + width: parent.width height: hidden ? -8 : undefined + spacing: 8 - RowLayout { - width: parent.width * 0.8 + Label { + Layout.alignment: Qt.AlignHCenter + visible: section !== aboveSection && !hidden - anchors.horizontalCenter: parent.horizontalCenter - spacing: 8 - Rectangle { - Layout.fillWidth: true - height:2 - color: Material.accent - } + text: section + color: "white" + verticalAlignment: Text.AlignVCenter + leftPadding: 8 + rightPadding: 8 + topPadding: 4 + bottomPadding: 4 - Label { - text: section - color: Material.accent - verticalAlignment: Text.AlignVCenter - } - - Rectangle { - Layout.fillWidth: true - height:2 - color: Material.accent + background: Rectangle { + color: MSettings.darkTheme ? "#484848" : "grey" } } - RowLayout { - width: parent.width * 0.8 + Label { + Layout.alignment: Qt.AlignHCenter + visible: readMarker === true && index !== 0 - anchors.horizontalCenter: parent.horizontalCenter - spacing: 8 - Rectangle { - Layout.fillWidth: true - height:2 - color: Material.accent - } + text: "And Now" + color: "white" + verticalAlignment: Text.AlignVCenter + leftPadding: 8 + rightPadding: 8 + topPadding: 4 + bottomPadding: 4 - Label { - text: "And Now" - color: Material.accent - verticalAlignment: Text.AlignVCenter - } - - Rectangle { - Layout.fillWidth: true - height:2 - color: Material.accent + background: Rectangle { + color: MSettings.darkTheme ? "#484848" : "grey" } } - MessageDelegate {} + MessageDelegate { + visible: eventType === "notice" || eventType === "message" || eventType === "image" || eventType === "video" || eventType === "audio" || eventType === "file" + } + + StateDelegate { + Layout.maximumWidth: messageListView.width * 0.8 + visible: eventType === "emote" || eventType === "state" + } } ScrollBar.vertical: messageListViewScrollBar diff --git a/qml/main.qml b/qml/main.qml index 1f06ca1d0..a2d4186da 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -65,7 +65,7 @@ ApplicationWindow { parent: null - connection: matriqueController.isLogin ? window.connection : null + connection: window.connection } Setting { diff --git a/qml/menu/MessageContextMenu.qml b/qml/menu/MessageContextMenu.qml index dd2b92de2..91c8e0359 100644 --- a/qml/menu/MessageContextMenu.qml +++ b/qml/menu/MessageContextMenu.qml @@ -18,13 +18,13 @@ Menu { visible: isFile height: visible ? undefined : 0 text: "Open Externally" - onTriggered: delegateLoader.item.downloadAndOpen() + onTriggered: messageRow.openExternally() } MenuItem { visible: isFile height: visible ? undefined : 0 text: "Save As" - onTriggered: delegateLoader.item.saveFileAs() + onTriggered: messageRow.saveFileAs() } MenuItem { visible: sentByMe diff --git a/res.qrc b/res.qrc index e2c99a155..71c1cf500 100644 --- a/res.qrc +++ b/res.qrc @@ -14,16 +14,9 @@ asset/img/icon.png js/md.js qml/component/MessageDelegate.qml - qml/component/MessageBubble.qml - qml/component/ImageBubble.qml - qml/component/StateBubble.qml qml/component/DownloadableContent.qml - qml/component/FileBubble.qml - qml/component/AvatarContainer.qml qml/form/RoomListForm.qml - qml/component/AudioBubble.qml qml/Setting.qml - qml/component/TextDelegate.qml qml/component/EmojiPicker.qml qml/component/EmojiButton.qml qml/component/AutoImage.qml @@ -33,5 +26,8 @@ qml/MatriqueSettings.qml qml/menu/MessageContextMenu.qml qml/menu/RoomContextMenu.qml + qml/component/GenericBubble.qml + qml/component/StateDelegate.qml + qml/component/AutoLabel.qml From 412b5201bf879c66b8cd2e7accf8444c28858f1b Mon Sep 17 00:00:00 2001 From: Black Hat Date: Tue, 4 Sep 2018 20:49:53 +0800 Subject: [PATCH 5/6] Fix redacted message issue. --- qml/form/RoomForm.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml index c8faaecb2..60be6d9a4 100644 --- a/qml/form/RoomForm.qml +++ b/qml/form/RoomForm.qml @@ -248,6 +248,8 @@ Item { width: parent.width height: hidden ? -8 : undefined + clip: true + spacing: 8 Label { From aa29f5252d1fdb70a35673da205dc732634ad220 Mon Sep 17 00:00:00 2001 From: Black Hat Date: Tue, 4 Sep 2018 21:13:14 +0800 Subject: [PATCH 6/6] Reformat code. --- qml/Login.qml | 20 ++++++----- qml/Room.qml | 9 ++--- qml/Setting.qml | 18 ++++++---- qml/component/AutoImage.qml | 12 +++---- qml/component/AutoLabel.qml | 1 + qml/component/AutoMouseArea.qml | 1 + qml/component/DownloadableContent.qml | 17 ++++----- qml/component/EmojiPicker.qml | 1 + qml/component/GenericBubble.qml | 6 ++-- qml/component/ImageStatus.qml | 5 ++- qml/component/MaterialIcon.qml | 3 +- qml/component/MessageDelegate.qml | 12 ++++--- qml/form/RoomForm.qml | 52 +++++++++++++++------------ qml/form/RoomListForm.qml | 14 +++++--- qml/main.qml | 49 ++++++++++++++++--------- qml/menu/MessageContextMenu.qml | 5 +++ qml/menu/RoomContextMenu.qml | 4 +++ 17 files changed, 139 insertions(+), 90 deletions(-) diff --git a/qml/Login.qml b/qml/Login.qml index 811955bd6..25b6db972 100644 --- a/qml/Login.qml +++ b/qml/Login.qml @@ -57,17 +57,19 @@ Page { Pane { width: parent.width / 2 height: parent.height + padding: 64 ColumnLayout { - id: mainCol width: parent.width - TextField { - id: serverField + id: mainCol + TextField { Layout.fillWidth: true + id: serverField + leftPadding: 16 topPadding: 0 bottomPadding: 0 @@ -85,10 +87,10 @@ Page { } TextField { - id: usernameField - Layout.fillWidth: true + id: usernameField + leftPadding: 16 topPadding: 0 bottomPadding: 0 @@ -105,10 +107,10 @@ Page { } TextField { - id: passwordField - Layout.fillWidth: true + id: passwordField + leftPadding: 16 topPadding: 0 bottomPadding: 0 @@ -126,10 +128,10 @@ Page { } Button { - id: loginButton - Layout.fillWidth: true + id: loginButton + text: "LOGIN" highlighted: true diff --git a/qml/Room.qml b/qml/Room.qml index ed1f17b56..3c16583f4 100644 --- a/qml/Room.qml +++ b/qml/Room.qml @@ -29,28 +29,29 @@ Page { spacing: 0 RoomListForm { - id: roomListForm - Layout.fillHeight: true Layout.preferredWidth: MSettings.miniMode ? 64 : page.width * 0.35 Layout.minimumWidth: 64 Layout.maximumWidth: 360 + id: roomListForm + listModel: roomListModel } Rectangle { Layout.preferredWidth: 1 Layout.fillHeight: true + color: MSettings.darkTheme ? "#363636" : "#ececec" } RoomForm { - id: roomForm - Layout.fillWidth: true Layout.fillHeight: true + id: roomForm + currentRoom: roomListForm.enteredRoom } } diff --git a/qml/Setting.qml b/qml/Setting.qml index d26815930..2fcf0806a 100644 --- a/qml/Setting.qml +++ b/qml/Setting.qml @@ -58,23 +58,28 @@ Page { Page { id: generalForm + parent: null + Column { Switch { text: "Lazy load at initial sync" checked: MSettings.lazyLoad + onCheckedChanged: MSettings.lazyLoad = checked } Switch { text: "Use RichText instead of StyledText" checked: MSettings.richText + onCheckedChanged: MSettings.richText = checked } Switch { text: "Use press and hold instead of right click" checked: MSettings.pressAndHold + onCheckedChanged: MSettings.pressAndHold = checked } } @@ -82,23 +87,28 @@ Page { Page { id: appearanceForm + parent: null + Column { Switch { text: "Dark theme" checked: MSettings.darkTheme + onCheckedChanged: MSettings.darkTheme = checked } Switch { text: "Mini Room List" checked: MSettings.miniMode + onCheckedChanged: MSettings.miniMode = checked } Switch { text: "Rearrange rooms by activity" checked: MSettings.rearrangeByActivity + onCheckedChanged: MSettings.rearrangeByActivity = checked } } @@ -118,12 +128,8 @@ Page { source: "qrc:/asset/img/icon.png" } - Label { - text: "Matrique, an IM client for the Matrix protocol." - } - Label { - text: "Released under GNU General Public License, version 3." - } + Label { text: "Matrique, an IM client for the Matrix protocol." } + Label { text: "Released under GNU General Public License, version 3." } } } diff --git a/qml/component/AutoImage.qml b/qml/component/AutoImage.qml index 75fbc618f..c7050de5a 100644 --- a/qml/component/AutoImage.qml +++ b/qml/component/AutoImage.qml @@ -6,22 +6,22 @@ Item { property alias sourceSize: baseImage.sourceSize.width readonly property bool loading: baseImage.status == Image.Loading - signal clicked() - id: rekt + signal clicked() width: loading ? 128 : baseImage.implicitWidth height: loading ? progressBar.height : baseImage.implicitHeight - Image { - id: baseImage - } + id: rekt + + Image { id: baseImage } ProgressBar { - id: progressBar width: parent.width visible: loading + id: progressBar + indeterminate: true } diff --git a/qml/component/AutoLabel.qml b/qml/component/AutoLabel.qml index 238c83117..684f8927c 100644 --- a/qml/component/AutoLabel.qml +++ b/qml/component/AutoLabel.qml @@ -11,5 +11,6 @@ Label { wrapMode: Label.Wrap linkColor: coloredBackground ? "white" : Material.accent textFormat: MSettings.richText ? Text.RichText : Text.StyledText + onLinkActivated: Qt.openUrlExternally(link) } diff --git a/qml/component/AutoMouseArea.qml b/qml/component/AutoMouseArea.qml index 270ee255c..7d0cc0e26 100644 --- a/qml/component/AutoMouseArea.qml +++ b/qml/component/AutoMouseArea.qml @@ -6,6 +6,7 @@ MouseArea { signal secondaryClicked() acceptedButtons: MSettings.pressAndHold ? Qt.LeftButton : (Qt.LeftButton | Qt.RightButton) + onClicked: mouse.button == Qt.RightButton ? secondaryClicked() : primaryClicked() onPressAndHold: MSettings.pressAndHold ? secondaryClicked() : {} } diff --git a/qml/component/DownloadableContent.qml b/qml/component/DownloadableContent.qml index a0f10720b..e2bbaea95 100644 --- a/qml/component/DownloadableContent.qml +++ b/qml/component/DownloadableContent.qml @@ -11,20 +11,18 @@ Item { z: -2 height: parent.height width: progressInfo.active && !progressInfo.completed ? progressInfo.progress / progressInfo.total * parent.width : 0 + color: Material.accent opacity: 0.4 } - onDownloadedChanged: downloaded && openOnFinished ? openSavedFile() : {} + onDownloadedChanged: if (downloaded && openOnFinished) openSavedFile() - function saveFileAs() { - currentRoom.saveFileAs(eventId) - } + function saveFileAs() { currentRoom.saveFileAs(eventId) } function downloadAndOpen() { - if (downloaded) - openSavedFile() + if (downloaded) openSavedFile() else { openOnFinished = true @@ -34,10 +32,7 @@ Item { function openSavedFile() { - if (Qt.openUrlExternally(progressInfo.localPath)) - return; - - if (Qt.openUrlExternally(progressInfo.localDir)) - return; + if (Qt.openUrlExternally(progressInfo.localPath)) return; + if (Qt.openUrlExternally(progressInfo.localDir)) return; } } diff --git a/qml/component/EmojiPicker.qml b/qml/component/EmojiPicker.qml index 78605392f..f58189a87 100644 --- a/qml/component/EmojiPicker.qml +++ b/qml/component/EmojiPicker.qml @@ -52,6 +52,7 @@ Popup { Rectangle { Layout.fillWidth: true Layout.preferredHeight: 2 + color: Material.accent } diff --git a/qml/component/GenericBubble.qml b/qml/component/GenericBubble.qml index 369423ec2..3c754be2d 100644 --- a/qml/component/GenericBubble.qml +++ b/qml/component/GenericBubble.qml @@ -12,13 +12,11 @@ Control { padding: 12 - background: Rectangle { - color: colored ? Material.accent : highlighted ? Material.primary : backgroundColor - } - AutoMouseArea { anchors.fill: parent onSecondaryClicked: Qt.createComponent("qrc:/qml/menu/MessageContextMenu.qml").createObject(this) } + + background: Rectangle { color: colored ? Material.accent : highlighted ? Material.primary : backgroundColor } } diff --git a/qml/component/ImageStatus.qml b/qml/component/ImageStatus.qml index 137bb0645..21447838d 100644 --- a/qml/component/ImageStatus.qml +++ b/qml/component/ImageStatus.qml @@ -13,9 +13,11 @@ Item { id: item Image { - id: avatar width: item.width height: item.width + + id: avatar + visible: showImage source: item.source @@ -40,6 +42,7 @@ Item { Label { anchors.fill: parent + color: "white" visible: showInitial text: showInitial ? getInitials(displayText)[0] : "" diff --git a/qml/component/MaterialIcon.qml b/qml/component/MaterialIcon.qml index bfb4ca6b2..d1b2f0ed6 100644 --- a/qml/component/MaterialIcon.qml +++ b/qml/component/MaterialIcon.qml @@ -10,8 +10,9 @@ Item { id: item Text { - id: iconText anchors.fill: parent + + id: iconText font.pointSize: 16 font.family: materialFont.name color: item.color diff --git a/qml/component/MessageDelegate.qml b/qml/component/MessageDelegate.qml index a78ab3547..745212d53 100644 --- a/qml/component/MessageDelegate.qml +++ b/qml/component/MessageDelegate.qml @@ -14,10 +14,10 @@ RowLayout { signal saveFileAs() signal openExternally() - id: messageRow - z: -5 + id: messageRow + Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft spacing: 6 @@ -100,14 +100,16 @@ RowLayout { id: imageComponent DownloadableContent { - id: downloadable - width: messageImage.width height: messageImage.height + id: downloadable + AutoImage { - id: messageImage z: -4 + + id: messageImage + sourceSize: 128 source: "image://mxc/" + (content.thumbnail_url ? content.thumbnail_url : content.url) diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml index 60be6d9a4..4ec648d22 100644 --- a/qml/form/RoomForm.qml +++ b/qml/form/RoomForm.qml @@ -22,11 +22,11 @@ Item { } Drawer { - id: roomDrawer - width: Math.min(item.width * 0.7, 480) height: item.height + id: roomDrawer + edge: Qt.RightEdge interactive: false @@ -51,12 +51,14 @@ Item { Label { Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter text: currentRoom && currentRoom.id ? currentRoom.id : "" } Label { Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter text: currentRoom && currentRoom.canonicalAlias ? currentRoom.canonicalAlias : "No Canonical Alias" } @@ -65,8 +67,9 @@ Item { Layout.fillWidth: true TextField { - id: roomNameField Layout.fillWidth: true + + id: roomNameField text: currentRoom && currentRoom.name ? currentRoom.name : "" } @@ -84,9 +87,10 @@ Item { Layout.fillWidth: true TextField { + Layout.fillWidth: true + id: roomTopicField - Layout.fillWidth: true text: currentRoom && currentRoom.topic ? currentRoom.topic : "" } @@ -176,6 +180,7 @@ Item { ImageStatus { Layout.preferredWidth: height Layout.fillHeight: true + source: currentRoom && currentRoom.avatarUrl != "" ? "image://mxc/" + currentRoom.avatarUrl : null displayText: currentRoom ? currentRoom.displayName : "" } @@ -222,10 +227,11 @@ Item { spacing: 0 ListView { - id: messageListView - Layout.fillWidth: true Layout.fillHeight: true + + id: messageListView + clip: true displayMarginBeginning: 40 displayMarginEnd: 40 @@ -243,13 +249,12 @@ Item { delegate: ColumnLayout { readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden - id: delegateColumn - width: parent.width height: hidden ? -8 : undefined - clip: true + id: delegateColumn + clip: true spacing: 8 Label { @@ -283,9 +288,7 @@ Item { topPadding: 4 bottomPadding: 4 - background: Rectangle { - color: MSettings.darkTheme ? "#484848" : "grey" - } + background: Rectangle { color: MSettings.darkTheme ? "#484848" : "grey" } } MessageDelegate { @@ -294,6 +297,7 @@ Item { StateDelegate { Layout.maximumWidth: messageListView.width * 0.8 + visible: eventType === "emote" || eventType === "state" } } @@ -304,9 +308,11 @@ Item { onAtYEndChanged: atYEnd && currentRoom ? currentRoom.markAllMessagesAsRead() : {} RoundButton { - id: goTopFab width: 64 height: 64 + + id: goTopFab + visible: !parent.atYEnd anchors.right: parent.right @@ -328,10 +334,10 @@ Item { } ScrollBar { - id: messageListViewScrollBar - Layout.preferredWidth: 16 Layout.fillHeight: true + + id: messageListViewScrollBar } } @@ -354,9 +360,11 @@ Item { TextField { property real progress: 0 - id: inputField Layout.fillWidth: true Layout.preferredHeight: 48 + + id: inputField + placeholderText: "Send a Message" leftPadding: 16 topPadding: 0 @@ -455,11 +463,11 @@ Item { } ItemDelegate { - id: emojiButton - Layout.preferredWidth: 48 Layout.preferredHeight: 48 + id: emojiButton + contentItem: MaterialIcon { icon: "\ue24e" } background: Rectangle { color: MSettings.darkTheme ? "#282828" : "#eaeaea" } @@ -467,16 +475,16 @@ Item { onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.open() EmojiPicker { - id: emojiPicker - - parent: ApplicationWindow.overlay - x: window.width - 370 y: window.height - 440 width: 360 height: 360 + id: emojiPicker + + parent: ApplicationWindow.overlay + textArea: inputField } } diff --git a/qml/form/RoomListForm.qml b/qml/form/RoomListForm.qml index ef7a0a610..8448898ea 100644 --- a/qml/form/RoomListForm.qml +++ b/qml/form/RoomListForm.qml @@ -16,6 +16,7 @@ Item { Label { z: 10 + text: MSettings.miniMode ? "Empty" : "Here? No, not here." anchors.centerIn: parent visible: listView.count === 0 @@ -26,18 +27,18 @@ Item { spacing: 0 TextField { - id: searchField 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 ? "#282828" : "#fafafa" - } + background: Rectangle { color: MSettings.darkTheme ? "#282828" : "#fafafa" } Shortcut { sequence: StandardKey.Find @@ -47,6 +48,7 @@ Item { SortFilterProxyModel { id: roomListProxyModel + filters: RegExpFilter { roleName: "name" pattern: searchField.text @@ -120,6 +122,7 @@ Item { Rectangle { anchors.fill: parent + visible: highlighted color: Material.accent opacity: 0.1 @@ -128,6 +131,7 @@ Item { Rectangle { width: 4 height: parent.height + color: Material.accent visible: unreadCount > 0 || highlighted } @@ -135,6 +139,7 @@ Item { RowLayout { anchors.fill: parent anchors.margins: 12 + spacing: 12 ImageStatus { @@ -179,6 +184,7 @@ Item { section.delegate: Label { width: parent.width height: 24 + text: section color: "grey" leftPadding: MSettings.miniMode ? undefined : 16 diff --git a/qml/main.qml b/qml/main.qml index a2d4186da..a0a3d0a2c 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -13,12 +13,14 @@ import "form" ApplicationWindow { readonly property var connection: matriqueController.connection - id: window - visible: true width: 960 height: 640 minimumWidth: 800 minimumHeight: 480 + + id: window + + visible: true title: qsTr("Matrique") Material.theme: MSettings.darkTheme ? Material.Dark : Material.Light @@ -40,10 +42,11 @@ ApplicationWindow { Popup { property bool busy: matriqueController.busy - id: busyPopup - x: (window.width - width) / 2 y: (window.height - height) / 2 + + id: busyPopup + modal: true focus: true @@ -81,9 +84,11 @@ ApplicationWindow { spacing: 0 Rectangle { - id: sideNav Layout.preferredWidth: 64 Layout.fillHeight: true + + id: sideNav + color: Material.primary ColumnLayout { @@ -106,8 +111,9 @@ ApplicationWindow { } Rectangle { - color: "transparent" Layout.fillHeight: true + + color: "transparent" } SideNavButton { @@ -125,6 +131,7 @@ ApplicationWindow { Menu { id: addRoomMenu + MenuItem { text:"New Room" onTriggered: addRoomDialog.open() @@ -143,14 +150,17 @@ ApplicationWindow { contentItem: Column { TextField { - id: addRoomDialogNameTextField width: parent.width + id: addRoomDialogNameTextField + placeholderText: "Name" } TextField { - id: addRoomDialogTopicTextField width: parent.width + + id: addRoomDialogTopicTextField + placeholderText: "Topic" } } @@ -160,16 +170,18 @@ ApplicationWindow { } MenuItem { text: "Join Room" + onTriggered: joinRoomDialog.open() Dialog { - id: joinRoomDialog - parent: ApplicationWindow.overlay - x: (window.width - width) / 2 y: (window.height - height) / 2 width: 360 + id: joinRoomDialog + + parent: ApplicationWindow.overlay + title: "Input Room Alias or ID" modal: true standardButtons: Dialog.Ok | Dialog.Cancel @@ -185,16 +197,18 @@ ApplicationWindow { MenuItem { text: "Direct Chat" + onTriggered: directChatDialog.open() Dialog { - id: directChatDialog - parent: ApplicationWindow.overlay - x: (window.width - width) / 2 y: (window.height - height) / 2 width: 360 + id: directChatDialog + + parent: ApplicationWindow.overlay + title: "Input User ID" modal: true standardButtons: Dialog.Ok | Dialog.Cancel @@ -240,11 +254,12 @@ ApplicationWindow { } StackView { - id: stackView - initialItem: roomPage - Layout.fillWidth: true Layout.fillHeight: true + + id: stackView + + initialItem: roomPage } } diff --git a/qml/menu/MessageContextMenu.qml b/qml/menu/MessageContextMenu.qml index 91c8e0359..1fbfa1194 100644 --- a/qml/menu/MessageContextMenu.qml +++ b/qml/menu/MessageContextMenu.qml @@ -8,28 +8,33 @@ Menu { MenuItem { text: "Copy" + onTriggered: matriqueController.copyToClipboard(plainText) } MenuItem { text: "Copy Source" + onTriggered: matriqueController.copyToClipboard(toolTip) } MenuItem { visible: isFile height: visible ? undefined : 0 text: "Open Externally" + onTriggered: messageRow.openExternally() } MenuItem { visible: isFile height: visible ? undefined : 0 text: "Save As" + onTriggered: messageRow.saveFileAs() } MenuItem { visible: sentByMe height: visible ? undefined : 0 text: "Redact" + onTriggered: currentRoom.redactEvent(eventId) } diff --git a/qml/menu/RoomContextMenu.qml b/qml/menu/RoomContextMenu.qml index 280947b28..9aff67fab 100644 --- a/qml/menu/RoomContextMenu.qml +++ b/qml/menu/RoomContextMenu.qml @@ -8,21 +8,25 @@ Menu { text: "Favourite" checkable: true checked: currentRoom && currentRoom.isFavourite + onTriggered: currentRoom.isFavourite ? currentRoom.removeTag("m.favourite") : currentRoom.addTag("m.favourite", "1") } MenuItem { text: "Deprioritize" checkable: true checked: currentRoom && currentRoom.isLowPriority + onTriggered: currentRoom.isLowPriority ? currentRoom.removeTag("m.lowpriority") : currentRoom.addTag("m.lowpriority", "1") } MenuSeparator {} MenuItem { text: "Mark as Read" + onTriggered: currentRoom.markAllMessagesAsRead() } MenuItem { text: "Leave Room" + onTriggered: currentRoom.forget() }