From b0700726f90a8d64c53f51522e7088b0aa7d930f Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Tue, 10 Nov 2020 17:08:13 +0000 Subject: [PATCH] Add join room page --- imports/NeoChat/Dialog/JoinRoomDialog.qml | 269 ---------------------- imports/NeoChat/Dialog/qmldir | 1 - imports/NeoChat/Page/JoinRoomPage.qml | 173 ++++++++++++++ imports/NeoChat/Page/RoomListPage.qml | 10 +- imports/NeoChat/Page/qmldir | 1 + imports/NeoChat/RoomManager.qml | 40 ++++ imports/NeoChat/qmldir | 1 + qml/main.qml | 40 ++-- res.qrc | 4 +- src/publicroomlistmodel.cpp | 7 + src/publicroomlistmodel.h | 1 + 11 files changed, 244 insertions(+), 303 deletions(-) delete mode 100644 imports/NeoChat/Dialog/JoinRoomDialog.qml create mode 100644 imports/NeoChat/Page/JoinRoomPage.qml create mode 100644 imports/NeoChat/RoomManager.qml create mode 100644 imports/NeoChat/qmldir diff --git a/imports/NeoChat/Dialog/JoinRoomDialog.qml b/imports/NeoChat/Dialog/JoinRoomDialog.qml deleted file mode 100644 index 3f7feae02..000000000 --- a/imports/NeoChat/Dialog/JoinRoomDialog.qml +++ /dev/null @@ -1,269 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.12 -import org.kde.kirigami 2.13 as Kirigami - -import NeoChat.Component 2.0 -import NeoChat.Effect 2.0 -import NeoChat.Setting 0.1 - -import org.kde.neochat 0.1 - -Dialog { - property var connection - - property string keyword - property string server - - anchors.centerIn: parent - width: 480 - height: Math.min(window.height - 100, 800) - - id: root - - title: "Explore Rooms" - - contentItem: ColumnLayout { - spacing: 0 - - RowLayout { - Layout.fillWidth: true - - AutoTextField { - property bool isRoomAlias: text.match(/#(.+):(.+)/g) - property var room: isRoomAlias ? connection.roomByAlias(text) : null - property bool isJoined: room != null - - Layout.fillWidth: true - - id: identifierField - - placeholderText: "Find a room..." - - onEditingFinished: { - keyword = text - } - } - - Button { - id: joinButton - - visible: identifierField.isRoomAlias - - text: identifierField.isJoined ? "View" : "Join" - highlighted: true - flat: identifierField.isJoined - - onClicked: { - if (identifierField.isJoined) { - roomListForm.joinRoom(identifierField.room) - } else { - Controller.joinRoom(connection, identifierField.text) - } - } - } - - ComboBox { - Layout.maximumWidth: 120 - - id: serverField - - editable: currentIndex == 1 - - model: ["Local", "Global", "matrix.org"] - - onCurrentIndexChanged: { - if (currentIndex == 0) { - server = "" - } else if (currentIndex == 2) { - server = "matrix.org" - } - } - - Keys.onReturnPressed: { - if (currentIndex == 1) { - server = editText - } - } - } - } - - MenuSeparator { - Layout.fillWidth: true - } - - AutoListView { - Layout.fillWidth: true - Layout.fillHeight: true - - id: publicRoomsListView - - clip: true - - spacing: 4 - - model: PublicRoomListModel { - id: publicRoomListModel - - connection: root.connection - server: root.server - keyword: root.keyword - } - - delegate: Control { - width: publicRoomsListView.width - height: 48 - - padding: 8 - - contentItem: RowLayout { - spacing: 8 - - Kirigami.Avatar { - Layout.preferredWidth: height - Layout.fillHeight: true - - source: model.avatarMediaId ? "image://mxc/" + model.avatarMediaId : "" - hint: name - } - - ColumnLayout { - Layout.fillWidth: true - Layout.fillHeight: true - - spacing: 0 - - RowLayout { - Layout.fillWidth: true - Layout.fillHeight: true - - spacing: 4 - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: name - color: MPalette.foreground - font.pixelSize: 13 - textFormat: Text.PlainText - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - - Label { - visible: allowGuests - - text: "GUESTS CAN JOIN" - color: MPalette.lighter - font.pixelSize: 10 - padding: 4 - - background: Rectangle { - color: MPalette.banner - } - } - - Label { - visible: worldReadable - - text: "WORLD READABLE" - color: MPalette.lighter - font.pixelSize: 10 - padding: 4 - - background: Rectangle { - color: MPalette.banner - } - } - } - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - visible: text - - text: topic ? topic.replace(/(\r\n\t|\n|\r\t)/gm," ") : "" - color: MPalette.lighter - font.pixelSize: 10 - textFormat: Text.PlainText - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - } - - MaterialIcon { - Layout.preferredWidth: 16 - Layout.preferredHeight: 16 - - icon: "\ue7fc" - color: MPalette.lighter - font.pixelSize: 16 - } - - Label { - Layout.preferredWidth: 36 - - text: memberCount - color: MPalette.lighter - font.pixelSize: 12 - } - - Control { - Layout.preferredWidth: 32 - Layout.preferredHeight: 32 - - visible: isJoined - - contentItem: MaterialIcon { - icon: "\ue89e" - color: MPalette.lighter - font.pixelSize: 20 - } - - background: RippleEffect { - circular: true - - onClicked: { - roomListForm.joinRoom(connection.room(roomID)) - root.close() - } - } - } - - Control { - Layout.preferredWidth: 32 - Layout.preferredHeight: 32 - - visible: !isJoined - - contentItem: MaterialIcon { - icon: "\ue7f0" - color: MPalette.lighter - font.pixelSize: 20 - } - - background: RippleEffect { - circular: true - - onClicked: { - Controller.joinRoom(connection, roomID) - root.close() - } - } - } - } - } - - ScrollBar.vertical: ScrollBar {} - - onContentYChanged: { - if(publicRoomListModel.hasMore && contentHeight - contentY < publicRoomsListView.height + 200) - publicRoomListModel.next(); - } - } - } - - onClosed: destroy() -} diff --git a/imports/NeoChat/Dialog/qmldir b/imports/NeoChat/Dialog/qmldir index 1c69fde11..4ee0b1eb2 100644 --- a/imports/NeoChat/Dialog/qmldir +++ b/imports/NeoChat/Dialog/qmldir @@ -4,7 +4,6 @@ UserDetailDialog 2.0 UserDetailDialog.qml MessageSourceDialog 2.0 MessageSourceDialog.qml LoginDialog 2.0 LoginDialog.qml CreateRoomDialog 2.0 CreateRoomDialog.qml -JoinRoomDialog 2.0 JoinRoomDialog.qml InviteUserDialog 2.0 InviteUserDialog.qml AcceptInvitationDialog 2.0 AcceptInvitationDialog.qml FontFamilyDialog 2.0 FontFamilyDialog.qml diff --git a/imports/NeoChat/Page/JoinRoomPage.qml b/imports/NeoChat/Page/JoinRoomPage.qml new file mode 100644 index 000000000..0ee193d54 --- /dev/null +++ b/imports/NeoChat/Page/JoinRoomPage.qml @@ -0,0 +1,173 @@ +/** + * SPDX-FileCopyrightText: 2019 Black Hat + * SPDX-FileCopyrightText: 2020 Carl Schwan + * + * SPDX-LicenseIdentifier: GPL-3.0-only + */ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import org.kde.kirigami 2.13 as Kirigami + +import NeoChat 2.0 +import NeoChat.Component 2.0 +import NeoChat.Effect 2.0 +import NeoChat.Setting 0.1 + +import org.kde.neochat 0.1 + +Kirigami.ScrollablePage { + id: root + property var connection + + property string keyword + property string server + + signal joinRoom(string room) + + title: i18n("Explore Rooms") + + header: Control { + padding: Kirigami.Units.largeSpacing + contentItem: RowLayout { + Kirigami.SearchField { + property bool isRoomAlias: text.match(/#(.+):(.+)/g) + property var room: isRoomAlias ? connection.roomByAlias(text) : null + property bool isJoined: room != null + + Layout.fillWidth: true + + id: identifierField + + placeholderText: i18n("Find a room...") + + onEditingFinished: { + keyword = text + } + } + + Button { + id: joinButton + + visible: identifierField.isRoomAlias + + text: identifierField.isJoined ? i18n("View") : i18n("Join") + highlighted: true + + onClicked: { + if (!identifierField.isJoined) { + Controller.joinRoom(connection, identifierField.text); + } + RoomManager.enterRoom(connection.room(identifierField.room)); + applicationWindow().pageStack.layers.pop(); + } + } + + ComboBox { + Layout.maximumWidth: 120 + + id: serverField + + editable: currentIndex == 1 + + model: [i18n("Local"), i18n("Global"), "matrix.org"] + + onCurrentIndexChanged: { + if (currentIndex == 0) { + server = "" + } else if (currentIndex == 2) { + server = "matrix.org" + } + } + + Keys.onReturnPressed: { + if (currentIndex == 1) { + server = editText + } + } + } + } + } + + ListView { + id: publicRoomsListView + clip: true + model: PublicRoomListModel { + id: publicRoomListModel + + connection: root.connection + server: root.server + keyword: root.keyword + } + + onContentYChanged: { + if(publicRoomListModel.hasMore && contentHeight - contentY < publicRoomsListView.height + 200) + publicRoomListModel.next(); + } + delegate: Kirigami.AbstractListItem { + property bool justJoined: false + width: publicRoomsListView.width + onClicked: { + if (!isJoined) { + Controller.joinRoom(connection, roomID) + justJoined = true; + } else { + RoomManager.enterRoom(connection.room(roomID)) + applicationWindow().pageStack.layers.pop(); + } + } + contentItem: RowLayout { + Kirigami.Avatar { + Layout.preferredWidth: Kirigami.Units.iconSizes.huge + Layout.preferredHeight: Kirigami.Units.iconSizes.huge + + source: model.avatar ? "image://mxc/" + model.avatar : "" + name: name + } + ColumnLayout { + Layout.fillWidth: true + RowLayout { + Layout.fillWidth: true + Kirigami.Heading { + Layout.fillWidth: true + level: 4 + text: name + font.bold: true + textFormat: Text.PlainText + elide: Text.ElideRight + wrapMode: Text.NoWrap + } + Label { + visible: isJoined || justJoined + text: i18n("Joined") + color: Kirigami.Theme.linkColor + } + } + Label { + Layout.fillWidth: true + visible: text + text: topic ? topic.replace(/(\r\n\t|\n|\r\t)/gm," ") : "" + textFormat: Text.PlainText + elide: Text.ElideRight + wrapMode: Text.NoWrap + } + RowLayout { + Layout.fillWidth: true + Kirigami.Icon { + source: "user" + color: Kirigami.Theme.disabledTextColor + implicitHeight: Kirigami.Units.iconSizes.small + implicitWidth: Kirigami.Units.iconSizes.small + } + Label { + text: memberCount + " " + (alias ?? roomID) + color: Kirigami.Theme.disabledTextColor + elide: Text.ElideRight + Layout.fillWidth: true + } + } + } + } + } + } +} diff --git a/imports/NeoChat/Page/RoomListPage.qml b/imports/NeoChat/Page/RoomListPage.qml index ee361f253..6795cf0c7 100644 --- a/imports/NeoChat/Page/RoomListPage.qml +++ b/imports/NeoChat/Page/RoomListPage.qml @@ -12,6 +12,7 @@ import org.kde.kirigami 2.13 as Kirigami import org.kde.kitemmodels 1.0 import org.kde.neochat 0.1 +import NeoChat 2.0 import NeoChat.Component 2.0 import NeoChat.Menu 2.0 @@ -121,17 +122,10 @@ Kirigami.ScrollablePage { acceptedButtons: Qt.LeftButton | Qt.RightButton anchors.fill: parent onClicked: { - console.log(mouse.button) if (mouse.button == Qt.RightButton) { roomListContextMenu.createObject(parent, {"room": currentRoom}).popup() } else { - if (enteredRoom) { - leaveRoom(enteredRoom) - } - - enteredRoom = currentRoom - - enterRoom(enteredRoom) + RoomManager.enterRoom(currentRoom) } } } diff --git a/imports/NeoChat/Page/qmldir b/imports/NeoChat/Page/qmldir index 254dc858a..adf3156b6 100644 --- a/imports/NeoChat/Page/qmldir +++ b/imports/NeoChat/Page/qmldir @@ -3,3 +3,4 @@ LoadingPage 2.0 LoadingPage.qml LoginPage 2.0 LoginPage.qml RoomListPage 2.0 RoomListPage.qml RoomPage 2.0 RoomPage.qml +JoinRoomPage 2.0 JoinRoomPage.qml diff --git a/imports/NeoChat/RoomManager.qml b/imports/NeoChat/RoomManager.qml new file mode 100644 index 000000000..fe4b14be7 --- /dev/null +++ b/imports/NeoChat/RoomManager.qml @@ -0,0 +1,40 @@ +/** + * SPDX-FileCopyrightText: 2020 Carl Schwan + * + * SPDX-LicenseIdentifier: GPL-2.0-or-later + */ + +pragma Singleton + +import QtQuick 2.14 +import NeoChat.Page 2.0 + +/** + * Manage opening and close rooms + */ +Item { + id: openRoomAction + + property var currentRoom: null + property var pageStack: null + + readonly property bool hasOpenRoom: currentRoom != null + + signal leaveRoom(string room); + signal openRoom(string room); + + function enterRoom(room) { + if (currentRoom != null) { + currentRoom = null; + pageStack.removePage(pageStack.lastItem); + } + pageStack.push(roomPage, {"currentRoom": room}); + currentRoom = room; + } + + Component { + id: roomPage + + RoomPage {} + } +} diff --git a/imports/NeoChat/qmldir b/imports/NeoChat/qmldir new file mode 100644 index 000000000..0f660f62e --- /dev/null +++ b/imports/NeoChat/qmldir @@ -0,0 +1 @@ +singleton RoomManager 2.0 RoomManager.qml diff --git a/qml/main.qml b/qml/main.qml index 1b63cd88a..d9b63e8d2 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -5,20 +5,25 @@ * SPDX-LicenseIdentifier: GPL-3.0-only */ import QtQuick 2.14 -import QtQuick.Controls 2.14 as Controls +import QtQuick.Controls 2.14 as QQC2 import QtQuick.Layouts 1.14 import org.kde.kirigami 2.12 as Kirigami import org.kde.neochat 0.1 +import NeoChat 2.0 import NeoChat.Component 2.0 import NeoChat.Panel 2.0 +import NeoChat.Dialog 2.0 +import NeoChat.Page 2.0 import NeoChat.Page 2.0 Kirigami.ApplicationWindow { id: root property var currentRoom: null + Component.onCompleted: RoomManager.pageStack = root.pageStack + contextDrawer: RoomDrawer { id: contextDrawer enabled: root.currentRoomm !== null @@ -30,16 +35,22 @@ Kirigami.ApplicationWindow { isMenu: true actions: [ Kirigami.Action { - text: i18n("About Neochat") - iconName: "help-about" - onTriggered: pageStack.layers.push(aboutPage) - enabled: pageStack.layers.currentItem.title !== i18n("About") + text: i18n("Explore rooms") + iconName: "compass" + onTriggered: pageStack.layers.push("qrc:/imports/NeoChat/Page/JoinRoomPage.qml", {"connection": Controller.connection}) + enabled: pageStack.layers.currentItem.title !== i18n("Explore Rooms") }, Kirigami.Action { text: i18n("Accounts") iconName: "im-user" onTriggered: pageStack.layers.push("qrc:/imports/NeoChat/Page/AccountsPage.qml") enabled: pageStack.layers.currentItem.title !== i18n("Accounts") + }, + Kirigami.Action { + text: i18n("About Neochat") + iconName: "help-about" + onTriggered: pageStack.layers.push(aboutPage) + enabled: pageStack.layers.currentItem.title !== i18n("About") } ] } @@ -58,17 +69,6 @@ Kirigami.ApplicationWindow { RoomListPage { id: roomList roomListModel: spectralRoomListModel - - onEnterRoom: { - applicationWindow().pageStack.push(roomPanelComponent, {"currentRoom": room}); - root.currentRoom = room; - } - onLeaveRoom: { - var stack = applicationWindow().pageStack; - roomList.enteredRoom = null; - - stack.removePage(stack.lastItem); - } } } @@ -103,12 +103,4 @@ Kirigami.ApplicationWindow { connection: Controller.connection } - - Component { - id: roomPanelComponent - - RoomPage { - currentRoom: root.currentRoom - } - } } diff --git a/res.qrc b/res.qrc index 779ecb3b2..18ad1b3f1 100644 --- a/res.qrc +++ b/res.qrc @@ -3,12 +3,15 @@ assets/img/matrix.svg assets/img/icon.png qml/main.qml + imports/NeoChat/qmldir + imports/NeoChat/RoomManager.qml imports/NeoChat/Page/qmldir imports/NeoChat/Page/LoginPage.qml imports/NeoChat/Page/LoadingPage.qml imports/NeoChat/Page/RoomListPage.qml imports/NeoChat/Page/RoomPage.qml imports/NeoChat/Page/AccountsPage.qml + imports/NeoChat/Page/JoinRoomPage.qml imports/NeoChat/Component/qmldir imports/NeoChat/Component/ChatTextInput.qml imports/NeoChat/Component/AutoMouseArea.qml @@ -47,7 +50,6 @@ imports/NeoChat/Dialog/UserDetailDialog.qml imports/NeoChat/Dialog/MessageSourceDialog.qml imports/NeoChat/Dialog/CreateRoomDialog.qml - imports/NeoChat/Dialog/JoinRoomDialog.qml imports/NeoChat/Dialog/InviteUserDialog.qml imports/NeoChat/Dialog/AcceptInvitationDialog.qml imports/NeoChat/Dialog/StartChatDialog.qml diff --git a/src/publicroomlistmodel.cpp b/src/publicroomlistmodel.cpp index 34ee3c560..f1883f243 100644 --- a/src/publicroomlistmodel.cpp +++ b/src/publicroomlistmodel.cpp @@ -177,6 +177,12 @@ QVariant PublicRoomListModel::data(const QModelIndex &index, int role) const if (role == RoomIDRole) { return room.roomId; } + if (role == AliasRole) { + if (!room.canonicalAlias.isEmpty()) { + return room.canonicalAlias; + } + return {}; + } if (role == MemberCountRole) { return room.numJoinedMembers; } @@ -208,6 +214,7 @@ QHash PublicRoomListModel::roleNames() const roles[AllowGuestsRole] = "allowGuests"; roles[WorldReadableRole] = "worldReadable"; roles[IsJoinedRole] = "isJoined"; + roles[AliasRole] = "alias"; return roles; } diff --git a/src/publicroomlistmodel.h b/src/publicroomlistmodel.h index 235c04c2e..05fdf3db9 100644 --- a/src/publicroomlistmodel.h +++ b/src/publicroomlistmodel.h @@ -24,6 +24,7 @@ public: AvatarRole, TopicRole, RoomIDRole, + AliasRole, MemberCountRole, AllowGuestsRole, WorldReadableRole,