From cfa80435965427a37e9df1440b1c7b653f36730c Mon Sep 17 00:00:00 2001 From: Black Hat Date: Fri, 24 Aug 2018 13:25:41 +0800 Subject: [PATCH] A lot of improvements. Fix laggish RoomListView when dragging. Remove per-room timer and add timer in RoomForm. Remove singleton module and use file as singleton. Minor UI tweak in RoomListView. Pass room to RoomListView via "currentRoom" delegate property and remove RoomListForm-wide currentRoom. Put menu files in a separate folder. Show initial image in ImageStatus when avatar is not loaded. Add about page. Merge all setting pages into Setting.qml. Add option to rearrange rooms by activity. Add option to use RichText parser. Add document url. --- matrique.pro | 2 +- org.eu.encom.matrique.appdata.xml | 1 + qml/Login.qml | 8 +- .../MatriqueSettings.qml | 1 + qml/MatriqueSettings/plugins.qmltypes | 26 ---- qml/MatriqueSettings/qmldir | 2 - qml/Room.qml | 14 +-- qml/Setting.qml | 119 +++++++++++++++++- qml/component/AutoMouseArea.qml | 7 +- qml/component/ImageStatus.qml | 3 +- qml/component/MaterialIcon.qml | 4 +- qml/component/MessageDelegate.qml | 13 +- qml/component/SideNav.qml | 8 -- qml/component/TextDelegate.qml | 4 +- qml/form/RoomForm.qml | 38 +++++- qml/form/RoomListForm.qml | 74 +++-------- qml/form/SettingAccountForm.qml | 48 ------- qml/form/SettingAppearanceForm.qml | 21 ---- qml/form/SettingGeneralForm.qml | 38 ------ qml/main.qml | 13 +- .../MessageContextMenu.qml | 0 qml/menu/RoomContextMenu.qml | 31 +++++ res.qrc | 11 +- src/main.cpp | 6 +- src/matriqueroom.cpp | 22 +--- src/matriqueroom.h | 15 --- src/roomlistmodel.cpp | 2 + src/roomlistmodel.h | 3 +- 28 files changed, 247 insertions(+), 287 deletions(-) rename qml/{MatriqueSettings => }/MatriqueSettings.qml (87%) delete mode 100644 qml/MatriqueSettings/plugins.qmltypes delete mode 100644 qml/MatriqueSettings/qmldir delete mode 100644 qml/component/SideNav.qml delete mode 100644 qml/form/SettingAccountForm.qml delete mode 100644 qml/form/SettingAppearanceForm.qml delete mode 100644 qml/form/SettingGeneralForm.qml rename qml/{component => menu}/MessageContextMenu.qml (100%) create mode 100644 qml/menu/RoomContextMenu.qml diff --git a/matrique.pro b/matrique.pro index f107b4e..d1ed1dd 100644 --- a/matrique.pro +++ b/matrique.pro @@ -32,7 +32,7 @@ RESOURCES += \ res.qrc # Additional import path used to resolve QML modules in Qt Creator's code model -QML_IMPORT_PATH += qml/MatriqueSettings +QML_IMPORT_PATH = # Additional import path used to resolve QML modules just for Qt Quick Designer QML_DESIGNER_IMPORT_PATH = diff --git a/org.eu.encom.matrique.appdata.xml b/org.eu.encom.matrique.appdata.xml index 621378b..aff4017 100644 --- a/org.eu.encom.matrique.appdata.xml +++ b/org.eu.encom.matrique.appdata.xml @@ -40,6 +40,7 @@ https://gitlab.com/b0/matrique https://gitlab.com/b0/matrique/issues + https://doc.matrique.encom.eu.org intense intense diff --git a/qml/Login.qml b/qml/Login.qml index e86dc20..19f6342 100644 --- a/qml/Login.qml +++ b/qml/Login.qml @@ -4,6 +4,8 @@ import QtGraphicalEffects 1.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.2 import Qt.labs.settings 1.0 +import Matrique.Settings 0.1 + import "qrc:/qml/component" Page { @@ -76,7 +78,7 @@ Page { background: Rectangle { implicitHeight: 48 - color: Material.theme == Material.Light ? "#eaeaea" : "#242424" + color: MSettings.darkTheme ? "#242424" : "#eaeaea" border.color: parent.activeFocus ? Material.accent : "transparent" border.width: 2 } @@ -96,7 +98,7 @@ Page { background: Rectangle { implicitHeight: 48 - color: Material.theme == Material.Light ? "#eaeaea" : "#242424" + color: MSettings.darkTheme ? "#242424" : "#eaeaea" border.color: parent.activeFocus ? Material.accent : "transparent" border.width: 2 } @@ -117,7 +119,7 @@ Page { background: Rectangle { implicitHeight: 48 - color: Material.theme == Material.Light ? "#eaeaea" : "#242424" + color: MSettings.darkTheme ? "#242424" : "#eaeaea" border.color: parent.activeFocus ? Material.accent : "transparent" border.width: 2 } diff --git a/qml/MatriqueSettings/MatriqueSettings.qml b/qml/MatriqueSettings.qml similarity index 87% rename from qml/MatriqueSettings/MatriqueSettings.qml rename to qml/MatriqueSettings.qml index 32edabe..6bcdbb5 100644 --- a/qml/MatriqueSettings/MatriqueSettings.qml +++ b/qml/MatriqueSettings.qml @@ -7,6 +7,7 @@ Settings { property bool asyncMessageDelegate property bool richText property bool pressAndHold + property bool rearrangeByActivity property bool darkTheme property bool miniMode diff --git a/qml/MatriqueSettings/plugins.qmltypes b/qml/MatriqueSettings/plugins.qmltypes deleted file mode 100644 index 904ebd9..0000000 --- a/qml/MatriqueSettings/plugins.qmltypes +++ /dev/null @@ -1,26 +0,0 @@ -import QtQuick.tooling 1.2 - -// This file describes the plugin-supplied types contained in the library. -// It is used for QML tooling purposes only. -// -// This file was auto-generated by: -// 'qmlplugindump -nonrelocatable MatriqueSettings 0.1 qml/' - -Module { - dependencies: ["Qt.labs.settings 1.0", "QtQuick 2.9"] - Component { - prototype: "QQmlSettings" - name: "MatriqueSettings 0.1" - exports: ["MatriqueSettings 0.1"] - exportMetaObjectRevisions: [1] - isComposite: true - isCreatable: false - isSingleton: true - Property { name: "lazyLoad"; type: "bool" } - Property { name: "asyncMessageDelegate"; type: "bool" } - Property { name: "richText"; type: "bool" } - Property { name: "pressAndHold"; type: "bool" } - Property { name: "darkTheme"; type: "bool" } - Property { name: "miniMode"; type: "bool" } - } -} diff --git a/qml/MatriqueSettings/qmldir b/qml/MatriqueSettings/qmldir deleted file mode 100644 index 8ce28a2..0000000 --- a/qml/MatriqueSettings/qmldir +++ /dev/null @@ -1,2 +0,0 @@ -module MatriqueSettings -singleton MatriqueSettings 0.1 MatriqueSettings.qml diff --git a/qml/Room.qml b/qml/Room.qml index 04c9e32..9272548 100644 --- a/qml/Room.qml +++ b/qml/Room.qml @@ -2,7 +2,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import Matrique 0.1 -import MatriqueSettings 0.1 +import Matrique.Settings 0.1 import "qrc:/qml/form" @@ -14,10 +14,8 @@ Page { RoomListModel { id: roomListModel - onRoomAdded: MatriqueSettings.lazyLoad ? {} : room.getPreviousContent(20) - onNewMessage: window.active ? {} : matriqueController.showMessage(roomName, content, icon) - - onDataChanged: roomListForm.rawCurrentIndex = -1 + onRoomAdded: if (!MSettings.lazyLoad) room.getPreviousContent(20) + onNewMessage: if (!window.active) matriqueController.showMessage(roomName, content, icon) } RowLayout { @@ -28,13 +26,11 @@ Page { id: roomListForm Layout.fillHeight: true - Layout.preferredWidth: MatriqueSettings.miniMode ? 80 : page.width * 0.35 + Layout.preferredWidth: MSettings.miniMode ? 80 : page.width * 0.35 Layout.minimumWidth: 80 Layout.maximumWidth: 360 listModel: roomListModel - - onEnterRoom: roomForm.currentRoom = currentRoom } RoomForm { @@ -42,6 +38,8 @@ Page { Layout.fillWidth: true Layout.fillHeight: true + + currentRoom: roomListForm.enteredRoom } } } diff --git a/qml/Setting.qml b/qml/Setting.qml index d6ead88..1b739f4 100644 --- a/qml/Setting.qml +++ b/qml/Setting.qml @@ -2,6 +2,7 @@ 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 import "component" import "form" @@ -9,24 +10,133 @@ import "form" Page { property var connection - SettingAccountForm { + Page { id: accountForm parent: null + + padding: 64 + + ColumnLayout { + RowLayout { + Layout.preferredHeight: 60 + + ImageStatus { + Layout.preferredWidth: height + Layout.fillHeight: true + + 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 : "" + } + + ColumnLayout { + Layout.fillWidth: true + Layout.fillHeight: true + + Label { + font.pointSize: 18 + text: matriqueController.isLogin ? connection.localUser.displayName : "" + } + + Label { + font.pointSize: 12 + text: matriqueController.isLogin ? connection.localUser.id : "" + } + } + } + + Button { + text: "Logout" + highlighted: true + + onClicked: { + matriqueController.logout() + Qt.quit() + } + } + } } - SettingGeneralForm { + Page { id: generalForm parent: null + Column { + Switch { + text: "Lazy load at initial sync" + 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() + } + } } - SettingAppearanceForm { + 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 + } + } + } + + Page { + id: aboutForm + parent: null + + padding: 64 + + ColumnLayout { + spacing: 16 + Image { + Layout.preferredWidth: 64 + Layout.preferredHeight: 64 + + 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." + } + } } RowLayout { ColumnLayout { - Material.elevation: 10 Layout.preferredWidth: 240 Layout.fillHeight: true @@ -57,6 +167,7 @@ Page { Layout.fillWidth: true text: "About" + onClicked: pushToStack(aboutForm) } } diff --git a/qml/component/AutoMouseArea.qml b/qml/component/AutoMouseArea.qml index 23e3657..270ee25 100644 --- a/qml/component/AutoMouseArea.qml +++ b/qml/component/AutoMouseArea.qml @@ -1,12 +1,11 @@ import QtQuick 2.9 -import MatriqueSettings 0.1 +import Matrique.Settings 0.1 MouseArea { signal primaryClicked() signal secondaryClicked() - propagateComposedEvents: true - acceptedButtons: MatriqueSettings.pressAndHold ? Qt.LeftButton : (Qt.LeftButton | Qt.RightButton) + acceptedButtons: MSettings.pressAndHold ? Qt.LeftButton : (Qt.LeftButton | Qt.RightButton) onClicked: mouse.button == Qt.RightButton ? secondaryClicked() : primaryClicked() - onPressAndHold: MatriqueSettings.pressAndHold ? secondaryClicked() : {} + onPressAndHold: MSettings.pressAndHold ? secondaryClicked() : {} } diff --git a/qml/component/ImageStatus.qml b/qml/component/ImageStatus.qml index adbc366..7fbfada 100644 --- a/qml/component/ImageStatus.qml +++ b/qml/component/ImageStatus.qml @@ -8,7 +8,7 @@ Item { property string source: "" property string displayText: "" readonly property bool showImage: source - readonly property bool showInitial: !showImage && displayText + readonly property bool showInitial: !showImage && displayText || avatar.status != Image.Ready id: item @@ -55,6 +55,7 @@ Item { } function getInitials(text) { + if (!text) return "N" return text.toUpperCase().replace(/[^a-zA-Z- ]/g, "").match(/\b\w/g); } diff --git a/qml/component/MaterialIcon.qml b/qml/component/MaterialIcon.qml index 68394aa..bfb4ca6 100644 --- a/qml/component/MaterialIcon.qml +++ b/qml/component/MaterialIcon.qml @@ -1,11 +1,11 @@ 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 Item { property alias icon: iconText.text - property var color: Material.theme == Material.Light ? "black" : "white" + property var color: MSettings.darkTheme ? "white" : "black" id: item diff --git a/qml/component/MessageDelegate.qml b/qml/component/MessageDelegate.qml index 014e8f5..ce947bf 100644 --- a/qml/component/MessageDelegate.qml +++ b/qml/component/MessageDelegate.qml @@ -2,14 +2,11 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.2 import Matrique 0.1 -import MatriqueSettings 0.1 +import Matrique.Settings 0.1 Item { readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden - - readonly property bool darkTheme: Material.theme == Material.Dark - readonly property color background: darkTheme ? "#242424" : "lightgrey" - + readonly property color background: MSettings.darkTheme ? "#242424" : "lightgrey" readonly property bool sentByMe: author === currentRoom.localUser readonly property bool isState: eventType === "state" || eventType === "emote" @@ -24,13 +21,15 @@ Item { AutoMouseArea { anchors.fill: parent - onSecondaryClicked: Qt.createComponent("MessageContextMenu.qml").createObject(this) + + propagateComposedEvents: true + onSecondaryClicked: Qt.createComponent("qrc:/qml/menu/MessageContextMenu.qml").createObject(this) } Loader { id: delegateLoader - asynchronous: MatriqueSettings.asyncMessageDelegate + asynchronous: MSettings.asyncMessageDelegate source: { if (eventType == "redaction" || hidden) return "" diff --git a/qml/component/SideNav.qml b/qml/component/SideNav.qml deleted file mode 100644 index f61198e..0000000 --- a/qml/component/SideNav.qml +++ /dev/null @@ -1,8 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Layouts 1.3 -import QtQuick.Controls.Material 2.2 - -Rectangle { - color: Material.accent -} diff --git a/qml/component/TextDelegate.qml b/qml/component/TextDelegate.qml index d2dd443..f007732 100644 --- a/qml/component/TextDelegate.qml +++ b/qml/component/TextDelegate.qml @@ -2,7 +2,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Controls.Material 2.2 import QtQuick.Layouts 1.3 -import MatriqueSettings 0.1 +import Matrique.Settings 0.1 Rectangle { property bool flat: false @@ -46,7 +46,7 @@ Rectangle { wrapMode: Label.Wrap linkColor: darkBackground ? "white" : Material.accent - textFormat: MatriqueSettings.richText ? Text.RichText : Text.StyledText + textFormat: MSettings.richText ? Text.RichText : Text.StyledText onLinkActivated: Qt.openUrlExternally(link) } diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml index b73142d..c482b3d 100644 --- a/qml/form/RoomForm.qml +++ b/qml/form/RoomForm.qml @@ -5,13 +5,16 @@ import QtQuick.Layouts 1.3 import QtQuick.Controls.Material 2.2 import QtGraphicalEffects 1.0 import Matrique 0.1 +import Matrique.Settings 0.1 + import "qrc:/qml/component" import "qrc:/js/md.js" as Markdown Item { - id: item property var currentRoom: null + id: item + Drawer { id: roomDrawer @@ -114,7 +117,7 @@ Item { Layout.fillWidth: true Layout.preferredHeight: 80 - color: Material.theme == Material.Light ? "#eaeaea" : "#242424" + color: MSettings.darkTheme ? "#242424" : "#eaeaea" MouseArea { anchors.fill: parent @@ -185,7 +188,7 @@ Item { boundsBehavior: Flickable.DragOverBounds - model: MessageEventModel{ + model: MessageEventModel { id: messageEventModel room: currentRoom } @@ -293,6 +296,26 @@ Item { Layout.fillWidth: true Layout.preferredHeight: 80 + 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) + } + RowLayout { anchors.fill: parent spacing: 0 @@ -320,7 +343,8 @@ Item { text: currentRoom ? currentRoom.cachedInput : "" onTextChanged: { - currentRoom.isTyping = true + timeoutTimer.restart() + repeatTimer.start() currentRoom.cachedInput = text } @@ -332,7 +356,7 @@ Item { } background: Rectangle { - color: Material.theme == Material.Light ? "#eaeaea" : "#242424" + color: MSettings.darkTheme ? "#242424" : "#eaeaea" } ToolTip.visible: currentRoom && currentRoom.hasUsersTyping @@ -395,7 +419,7 @@ Item { contentItem: MaterialIcon { icon: "\ue24e" } - background: Rectangle { color: Material.theme == Material.Light ? "#eaeaea" : "#242424" } + background: Rectangle { color: MSettings.darkTheme ? "#242424" : "#eaeaea" } onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.open() @@ -417,4 +441,6 @@ Item { } } } + + onCurrentRoomChanged: if (currentRoom && currentRoom.timelineSize === 0) currentRoom.getPreviousContent(20) } diff --git a/qml/form/RoomListForm.qml b/qml/form/RoomListForm.qml index 3a16be6..6ba013f 100644 --- a/qml/form/RoomListForm.qml +++ b/qml/form/RoomListForm.qml @@ -6,17 +6,13 @@ import QtQuick.Controls.Material 2.2 import QtQml.Models 2.3 import Matrique 0.1 import SortFilterProxyModel 0.2 -import MatriqueSettings 0.1 +import Matrique.Settings 0.1 import "qrc:/qml/component" Item { property alias listModel: roomListProxyModel.sourceModel - property alias rawCurrentIndex: listView.currentIndex - readonly property int currentIndex: roomListProxyModel.mapToSource(listView.currentIndex) - readonly property var currentRoom: currentIndex != -1 ? listModel.roomAt(currentIndex) : null - readonly property bool mini: MatriqueSettings.miniMode // Used as an indicator of whether the listform should be displayed as "Mini mode". - signal enterRoom() + property var enteredRoom: null ColumnLayout { anchors.fill: parent @@ -33,7 +29,7 @@ Item { width: parent.width - 18 height: 36 color: "white" - leftPadding: mini ? 4 : 32 + leftPadding: MSettings.miniMode ? 4 : 32 topPadding: 0 bottomPadding: 0 anchors.centerIn: parent @@ -45,13 +41,13 @@ Item { icon: "\ue8b6" color: "white" - width: mini ? parent.width : parent.height + width: MSettings.miniMode ? parent.width : parent.height height: parent.height } Label { height: parent.height - visible: !mini + visible: !MSettings.miniMode text: "Search" color: "white" font.pointSize: 12 @@ -66,11 +62,11 @@ Item { Layout.fillWidth: true Layout.fillHeight: true - color: Material.theme == Material.Light ? "#eaeaea" : "#242424" + color: MSettings.darkTheme ? "#242424" : "#eaeaea" Label { z: 10 - text: mini ? "Empty" : "Here? No, not here." + text: MSettings.miniMode ? "Empty" : "Here? No, not here." anchors.centerIn: parent visible: listView.count === 0 } @@ -98,6 +94,7 @@ Item { sorters: [ RoleSorter { roleName: "category" }, RoleSorter { + enabled: MSettings.rearrangeByActivity roleName: "unreadCount" sortOrder: Qt.DescendingOrder }, @@ -111,34 +108,26 @@ Item { model: roomListProxyModel - highlight: Rectangle { - color: Material.accent - opacity: 0.2 - } - highlightMoveDuration: 250 - highlightResizeDuration: 0 - currentIndex: -1 boundsBehavior: Flickable.DragOverBounds ScrollBar.vertical: ScrollBar { id: scrollBar } - delegate: Item { + delegate: Rectangle { + id: swipeDelegate width: parent.width height: 80 + color: currentRoom === enteredRoom ? Material.background : "transparent" + AutoMouseArea { anchors.fill: parent - onPressed: listView.currentIndex = index - onSecondaryClicked: roomListMenu.popup() - onPrimaryClicked: category === RoomType.Invited ? inviteDialog.open() : enterRoom() + onSecondaryClicked: Qt.createComponent("qrc:/qml/menu/RoomContextMenu.qml").createObject(this) + onPrimaryClicked: category === RoomType.Invited ? inviteDialog.open() : enteredRoom = currentRoom } - ToolTip.visible: mini && hovered - ToolTip.text: name - Rectangle { width: 4 height: parent.height @@ -186,6 +175,9 @@ Item { } } } + + ToolTip.visible: MSettings.miniMode && hovered + ToolTip.text: name } section.property: "display" @@ -195,13 +187,13 @@ Item { height: 24 text: section color: "grey" - leftPadding: mini ? undefined : 16 + leftPadding: MSettings.miniMode ? undefined : 16 elide: Text.ElideRight verticalAlignment: Text.AlignVCenter - horizontalAlignment: mini ? Text.AlignHCenter : undefined + horizontalAlignment: MSettings.miniMode ? Text.AlignHCenter : undefined background: Rectangle { anchors.fill: parent - color: Material.theme == Material.Light ? "#dbdbdb" : "#363636" + color: MSettings.darkTheme ? "#363636" : "#dbdbdb" } } @@ -222,32 +214,6 @@ Item { onAccepted: currentRoom.acceptInvitation() onRejected: currentRoom.forget() } - - Menu { - id: roomListMenu - - MenuItem { - 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() - } - } } } } diff --git a/qml/form/SettingAccountForm.qml b/qml/form/SettingAccountForm.qml deleted file mode 100644 index 021c6d3..0000000 --- a/qml/form/SettingAccountForm.qml +++ /dev/null @@ -1,48 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Layouts 1.3 - -import "qrc:/qml/component" - -Page { - padding: 64 - - ColumnLayout { - RowLayout { - Layout.preferredHeight: 60 - - ImageStatus { - Layout.preferredWidth: height - Layout.fillHeight: true - - 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 : "N" - } - - ColumnLayout { - Layout.fillWidth: true - Layout.fillHeight: true - - Label { - font.pointSize: 18 - text: matriqueController.isLogin ? connection.localUser.displayName : "" - } - - Label { - font.pointSize: 12 - text: matriqueController.isLogin ? connection.localUser.id : "" - } - } - } - - Button { - text: "Logout" - highlighted: true - - onClicked: { - matriqueController.logout() - Qt.quit() - } - } - } -} diff --git a/qml/form/SettingAppearanceForm.qml b/qml/form/SettingAppearanceForm.qml deleted file mode 100644 index 315360c..0000000 --- a/qml/form/SettingAppearanceForm.qml +++ /dev/null @@ -1,21 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import MatriqueSettings 0.1 - -Page { - Column { - Switch { - id: themeSwitch - text: "Dark theme" - checked: MatriqueSettings.darkTheme - onCheckedChanged: MatriqueSettings.darkTheme = checked - } - - Switch { - id: miniModeSwitch - text: "Mini Room List" - checked: MatriqueSettings.miniMode - onCheckedChanged: MatriqueSettings.miniMode = checked - } - } -} diff --git a/qml/form/SettingGeneralForm.qml b/qml/form/SettingGeneralForm.qml deleted file mode 100644 index 40c4d27..0000000 --- a/qml/form/SettingGeneralForm.qml +++ /dev/null @@ -1,38 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import MatriqueSettings 0.1 - -Page { - Column { - Switch { - id: lazyLoadSwitch - text: "Lazy load at initial sync" - checked: MatriqueSettings.lazyLoad - onCheckedChanged: MatriqueSettings.lazyLoad = checked - } - Switch { - id: asyncMessageDelegateSwitch - text: "Force loading message delegates asynchronously" - checked: MatriqueSettings.asyncMessageDelegate - onCheckedChanged: MatriqueSettings.asyncMessageDelegate = checked - } - Switch { - id: richTextSwitch - text: "Use RichText instead of StyledText" - checked: MatriqueSettings.richText - onCheckedChanged: MatriqueSettings.richText = checked - } - Switch { - id: pressAndHoldSwitch - text: "Use press and hold instead of right click" - checked: MatriqueSettings.pressAndHold - onCheckedChanged: MatriqueSettings.pressAndHold = checked - } - - Button { - text: "Invoke GC" - highlighted: true - onClicked: gc() - } - } -} diff --git a/qml/main.qml b/qml/main.qml index 22b8af2..83d917d 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -2,10 +2,10 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import QtQuick.Controls.Material 2.2 -import Qt.labs.settings 1.0 as Labs +import Qt.labs.settings 1.0 import QtGraphicalEffects 1.0 import Matrique 0.1 -import MatriqueSettings 0.1 +import Matrique.Settings 0.1 import "component" import "form" @@ -21,9 +21,9 @@ ApplicationWindow { minimumHeight: 480 title: qsTr("Matrique") - Material.theme: MatriqueSettings.darkTheme ? Material.Dark : Material.Light + Material.theme: MSettings.darkTheme ? Material.Dark : Material.Light - Labs.Settings { + Settings { property alias homeserver: matriqueController.homeserver property alias userID: matriqueController.userID property alias token: matriqueController.token @@ -80,10 +80,11 @@ ApplicationWindow { anchors.fill: parent spacing: 0 - SideNav { + Rectangle { id: sideNav Layout.preferredWidth: 80 Layout.fillHeight: true + color: Material.accent ColumnLayout { anchors.fill: parent @@ -96,7 +97,7 @@ ApplicationWindow { anchors.margins: 15 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 : "N" + displayText: matriqueController.isLogin && connection.localUser.displayName ? connection.localUser.displayName : "" } page: roomPage diff --git a/qml/component/MessageContextMenu.qml b/qml/menu/MessageContextMenu.qml similarity index 100% rename from qml/component/MessageContextMenu.qml rename to qml/menu/MessageContextMenu.qml diff --git a/qml/menu/RoomContextMenu.qml b/qml/menu/RoomContextMenu.qml new file mode 100644 index 0000000..280947b --- /dev/null +++ b/qml/menu/RoomContextMenu.qml @@ -0,0 +1,31 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 + +Menu { + id: roomListMenu + + MenuItem { + 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() + } + + Component.onCompleted: popup() + onClosed: roomListMenu.destroy() +} diff --git a/res.qrc b/res.qrc index e0a2235..e2c99a1 100644 --- a/res.qrc +++ b/res.qrc @@ -7,7 +7,6 @@ qml/Login.qml qml/main.qml qml/component/ImageStatus.qml - qml/component/SideNav.qml qml/form/RoomForm.qml qml/Room.qml qml/component/SideNavButton.qml @@ -24,19 +23,15 @@ qml/form/RoomListForm.qml qml/component/AudioBubble.qml qml/Setting.qml - qml/form/SettingAccountForm.qml - qml/form/SettingAppearanceForm.qml qml/component/TextDelegate.qml - qml/component/MessageContextMenu.qml - qml/form/SettingGeneralForm.qml qml/component/EmojiPicker.qml qml/component/EmojiButton.qml qml/component/AutoImage.qml asset/img/icon.ico asset/img/icon.icns qml/component/AutoMouseArea.qml - qml/MatriqueSettings/MatriqueSettings.qml - qml/MatriqueSettings/qmldir - qml/MatriqueSettings/plugins.qmltypes + qml/MatriqueSettings.qml + qml/menu/MessageContextMenu.qml + qml/menu/RoomContextMenu.qml diff --git a/src/main.cpp b/src/main.cpp index ddff03c..1268d22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,10 +6,10 @@ #include "controller.h" #include "emojimodel.h" #include "imageprovider.h" +#include "matriqueroom.h" #include "messageeventmodel.h" #include "room.h" #include "roomlistmodel.h" -#include "matriqueroom.h" #include "csapi/joining.h" #include "csapi/leaving.h" @@ -28,6 +28,7 @@ int main(int argc, char *argv[]) { qRegisterMetaType("MatriqueRoom*"); qRegisterMetaType("User*"); qRegisterMetaType("MessageEventType"); + qRegisterMetaType("MatriqueRoom"); qmlRegisterType("Matrique", 0, 1, "Controller"); qmlRegisterType("Matrique", 0, 1, "RoomListModel"); @@ -36,9 +37,10 @@ int main(int argc, char *argv[]) { qmlRegisterUncreatableType("Matrique", 0, 1, "RoomMessageEvent", "ENUM"); qmlRegisterUncreatableType("Matrique", 0, 1, "RoomType", "ENUM"); + qmlRegisterSingletonType(QUrl("qrc:/qml/MatriqueSettings.qml"), + "Matrique.Settings", 0, 1, "MSettings"); QQmlApplicationEngine engine; - engine.addImportPath("qrc:/qml"); ImageProvider *m_provider = new ImageProvider(); diff --git a/src/matriqueroom.cpp b/src/matriqueroom.cpp index b96e915..dcd79ae 100644 --- a/src/matriqueroom.cpp +++ b/src/matriqueroom.cpp @@ -12,25 +12,7 @@ MatriqueRoom::MatriqueRoom(Connection* connection, QString roomId, JoinState joinState) - : Room(connection, std::move(roomId), joinState) { - m_timeoutTimer->setSingleShot(true); - m_timeoutTimer->setInterval(2000); - m_repeatTimer->setInterval(5000); - connect(m_timeoutTimer, &QTimer::timeout, [=] { setIsTyping(false); }); - connect(m_repeatTimer, &QTimer::timeout, - [=] { sendTypingNotification(true); }); - connect(this, &MatriqueRoom::isTypingChanged, [=] { - if (m_isTyping) { - m_timeoutTimer->start(); - m_repeatTimer->start(); - sendTypingNotification(true); - } else { - m_timeoutTimer->stop(); - m_repeatTimer->stop(); - sendTypingNotification(false); - } - }); -} + : Room(connection, std::move(roomId), joinState) {} void MatriqueRoom::chooseAndUploadFile() { auto localFile = QFileDialog::getOpenFileUrl(Q_NULLPTR, tr("Save File as")); @@ -88,7 +70,7 @@ QString MatriqueRoom::getUsersTyping() { for (User* user : users) { usersTypingStr += user->displayname() + " "; } - usersTypingStr += users.count() == 1 ? "is" : "are"; + usersTypingStr += users.count() < 2 ? "is" : "are"; usersTypingStr += " typing."; return usersTypingStr; } diff --git a/src/matriqueroom.h b/src/matriqueroom.h index b44cbb5..32f13b0 100644 --- a/src/matriqueroom.h +++ b/src/matriqueroom.h @@ -10,8 +10,6 @@ using namespace QMatrixClient; class MatriqueRoom : public Room { Q_OBJECT - Q_PROPERTY( - bool isTyping READ isTyping WRITE setIsTyping NOTIFY isTypingChanged) Q_PROPERTY(bool hasUsersTyping READ hasUsersTyping NOTIFY typingChanged) Q_PROPERTY(QString usersTyping READ getUsersTyping NOTIFY typingChanged) Q_PROPERTY(QString cachedInput READ cachedInput WRITE setCachedInput NOTIFY @@ -20,15 +18,6 @@ class MatriqueRoom : public Room { explicit MatriqueRoom(Connection* connection, QString roomId, JoinState joinState = {}); - bool isTyping() { return m_isTyping; } - void setIsTyping(bool isTyping) { - if (isTyping) m_timeoutTimer->start(); - if (isTyping != m_isTyping) { - m_isTyping = isTyping; - emit isTypingChanged(); - } - } - const QString& cachedInput() const { return m_cachedInput; } void setCachedInput(const QString& input) { if (input != m_cachedInput) { @@ -44,15 +33,11 @@ class MatriqueRoom : public Room { private: QString m_cachedInput; - bool m_isTyping; - QTimer* m_timeoutTimer = new QTimer(); - QTimer* m_repeatTimer = new QTimer(); QString getMIME(const QUrl& fileUrl) const; void postFile(const QUrl& localFile, const QUrl& mxcUrl); signals: - void isTypingChanged(); void cachedInputChanged(); public slots: diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp index f780e33..062ffed 100644 --- a/src/roomlistmodel.cpp +++ b/src/roomlistmodel.cpp @@ -153,6 +153,7 @@ QVariant RoomListModel::data(const QModelIndex& index, int role) const { } if (role == UnreadCountRole) return room->unreadCount(); if (role == LastEventRole) return room->lastEvent(); + if (role == CurrentRoomRole) return QVariant::fromValue(room); return QVariant(); } @@ -184,5 +185,6 @@ QHash RoomListModel::roleNames() const { roles[CategoryRole] = "category"; roles[UnreadCountRole] = "unreadCount"; roles[LastEventRole] = "lastEvent"; + roles[CurrentRoomRole] = "currentRoom"; return roles; } diff --git a/src/roomlistmodel.h b/src/roomlistmodel.h index ee1c663..6fa57e9 100644 --- a/src/roomlistmodel.h +++ b/src/roomlistmodel.h @@ -35,7 +35,8 @@ class RoomListModel : public QAbstractListModel { TopicRole, CategoryRole, UnreadCountRole, - LastEventRole + LastEventRole, + CurrentRoomRole, }; RoomListModel(QObject* parent = 0);