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);