// SPDX-FileCopyrightText: 2019 Black Hat // SPDX-FileCopyrightText: 2020 Carl Schwan // SPDX-License-Identifier: GPL-3.0-only import QtQuick 2.15 import QtQuick.Controls 2.15 as QQC2 import QtQuick.Layouts 1.15 import Qt.labs.qmlmodels 1.0 import org.kde.kirigami 2.19 as Kirigami import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents import org.kde.neochat 1.0 Kirigami.ScrollablePage { id: root property var connection property alias keyword: identifierField.text property string server title: i18n("Explore Rooms") Component.onCompleted: identifierField.forceActiveFocus() header: QQC2.Control { padding: Kirigami.Units.largeSpacing background: Rectangle { Kirigami.Theme.colorSet: Kirigami.Theme.Window Kirigami.Theme.inherit: false color: Kirigami.Theme.backgroundColor } contentItem: RowLayout { Kirigami.SearchField { id: identifierField property bool isRoomAlias: text.match(/#(.+):(.+)/g) property NeoChatRoom room: isRoomAlias ? connection.roomByAlias(text) : null property bool isJoined: room != null Layout.fillWidth: true placeholderText: i18n("Find a room...") } QQC2.Button { id: joinButton visible: identifierField.isRoomAlias text: identifierField.isJoined ? i18n("View") : i18n("Join") highlighted: true onClicked: { if (!identifierField.isJoined) { Controller.joinRoom(identifierField.text); // When joining the room, the room will be opened } applicationWindow().pageStack.layers.pop(); } } QQC2.ComboBox { id: serverField // TODO: in KF6 we should be able to switch to using implicitContentWidthPolicy Layout.preferredWidth: Kirigami.Units.gridUnit * 10 Component.onCompleted: currentIndex = 0 textRole: "url" valueRole: "url" model: ServerListModel { id: serverListModel } delegate: Kirigami.BasicListItem { id: serverItem label: isAddServerDelegate ? i18n("Add New Server") : url subtitle: isHomeServer ? i18n("Home Server") : "" onClicked: if (isAddServerDelegate) { addServerSheet.open() } trailing: QQC2.ToolButton { visible: isAddServerDelegate || isDeletable icon.name: isAddServerDelegate ? "list-add" : "dialog-close" text: i18n("Add new server") Accessible.name: text display: QQC2.AbstractButton.IconOnly onClicked: { if (serverField.currentIndex === index && isDeletable) { serverField.currentIndex = 0 server = serverField.currentValue serverField.popup.close() } if (isAddServerDelegate) { addServerSheet.open() serverItem.clicked() } else { serverListModel.removeServerAtIndex(index) } } } } onActivated: { if (currentIndex !== count - 1) { server = currentValue } } Kirigami.OverlaySheet { id: addServerSheet parent: applicationWindow().overlay title: i18nc("@title:window", "Add server") onSheetOpenChanged: if (!serverUrlField.isValidServer && !sheetOpen) { serverField.currentIndex = 0 server = serverField.currentValue } else if (sheetOpen) { serverUrlField.forceActiveFocus() } contentItem: Kirigami.FormLayout { QQC2.Label { Layout.minimumWidth: Kirigami.Units.gridUnit * 20 text: serverUrlField.length > 0 ? (serverUrlField.acceptableInput ? (serverUrlField.isValidServer ? i18n("Valid server entered") : i18n("This server cannot be resolved or has already been added")) : i18n("The entered text is not a valid url")) : i18n("Enter server url e.g. kde.org") color: serverUrlField.length > 0 ? (serverUrlField.acceptableInput ? (serverUrlField.isValidServer ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.negativeTextColor) : Kirigami.Theme.negativeTextColor) : Kirigami.Theme.textColor } QQC2.TextField { id: serverUrlField property bool isValidServer: false Kirigami.FormData.label: i18n("Server URL") onTextChanged: { if(acceptableInput) { serverListModel.checkServer(text) } } validator: RegularExpressionValidator { regularExpression: /^[a-zA-Z0-9-]{1,61}\.([a-zA-Z]{2,}|[a-zA-Z0-9-]{2,}\.[a-zA-Z]{2,3})$/ } Connections { target: serverListModel function onServerCheckComplete(url, valid) { if (url == serverUrlField.text && valid) { serverUrlField.isValidServer = true } } } } QQC2.Button { id: okButton text: i18nc("@action:button", "Ok") enabled: serverUrlField.acceptableInput && serverUrlField.isValidServer onClicked: { serverListModel.addServer(serverUrlField.text) serverField.currentIndex = serverField.indexOfValue(serverUrlField.text) // console.log(serverField.delegate.label) server = serverField.currentValue serverUrlField.text = "" addServerSheet.close(); } } } } } } Kirigami.Separator { z: 999 anchors { left: parent.left right: parent.right top: parent.bottom } } } 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(roomID) justJoined = true; } else { RoomManager.enterRoom(connection.room(roomID)) } applicationWindow().pageStack.layers.pop(); } contentItem: RowLayout { KirigamiComponents.Avatar { Layout.preferredWidth: Kirigami.Units.gridUnit * 2 Layout.preferredHeight: Kirigami.Units.gridUnit * 2 source: model.avatar ? ("image://mxc/" + model.avatar) : "" name: model.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 } QQC2.Label { visible: isJoined || justJoined text: i18n("Joined") color: Kirigami.Theme.linkColor } } QQC2.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 } QQC2.Label { text: memberCount + " " + (alias ?? roomID) color: Kirigami.Theme.disabledTextColor elide: Text.ElideRight Layout.fillWidth: true } } } } } footer: RowLayout { width: parent.width QQC2.ProgressBar { visible: publicRoomsListView.model.loading && publicRoomsListView.count !== 0 indeterminate: true padding: Kirigami.Units.largeSpacing * 2 Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.topMargin: Kirigami.Units.largeSpacing Layout.bottomMargin: Kirigami.Units.largeSpacing Layout.leftMargin: Kirigami.Units.largeSpacing Layout.rightMargin: Kirigami.Units.largeSpacing } } Kirigami.LoadingPlaceholder { anchors.centerIn: parent visible: publicRoomsListView.model.loading && publicRoomsListView.count === 0 } Kirigami.PlaceholderMessage { anchors.centerIn: parent visible: !publicRoomsListView.model.loading && publicRoomsListView.count === 0 text: i18nc("@info:label", "No rooms found") } } }