Warning, /network/neochat/src/qml/JoinRoomPage.qml is written in an unsupported language. File is not indexed.

0001 // SPDX-FileCopyrightText: 2019 Black Hat <bhat@encom.eu.org>
0002 // SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
0003 // SPDX-License-Identifier: GPL-3.0-only
0004 
0005 import QtQuick
0006 import QtQuick.Controls as QQC2
0007 import QtQuick.Layouts
0008 import Qt.labs.qmlmodels
0009 
0010 import org.kde.kirigami as Kirigami
0011 import org.kde.kirigamiaddons.delegates as Delegates
0012 
0013 import org.kde.neochat
0014 
0015 Kirigami.ScrollablePage {
0016     id: root
0017 
0018     required property NeoChatConnection connection
0019 
0020     property bool showOnlySpaces: false
0021 
0022     property alias keyword: identifierField.text
0023     property string server
0024 
0025     /**
0026      * @brief Signal emitted when a room is selected.
0027      *
0028      * The signal contains all the room's info so that it can be acted
0029      * upon as required, e.g. joinng or entering the room or adding the room as
0030      * the child of a space.
0031      */
0032     signal roomSelected(string roomId,
0033                         string displayName,
0034                         url avatarUrl,
0035                         string alias,
0036                         string topic,
0037                         int memberCount,
0038                         bool isJoined)
0039 
0040     title: i18n("Explore Rooms")
0041 
0042     Component.onCompleted: identifierField.forceActiveFocus()
0043 
0044     header: QQC2.Control {
0045         padding: Kirigami.Units.largeSpacing
0046 
0047         background: Rectangle {
0048             Kirigami.Theme.colorSet: Kirigami.Theme.Window
0049             Kirigami.Theme.inherit: false
0050 
0051             color: Kirigami.Theme.backgroundColor
0052         }
0053 
0054         contentItem: RowLayout {
0055             Kirigami.SearchField {
0056                 id: identifierField
0057                 Layout.fillWidth: true
0058                 placeholderText: i18n("Find a room...")
0059             }
0060             QQC2.ComboBox {
0061                 id: serverField
0062 
0063                 // TODO: in KF6 we should be able to switch to using implicitContentWidthPolicy
0064                 Layout.preferredWidth: Kirigami.Units.gridUnit * 10
0065 
0066                 Component.onCompleted: currentIndex = 0
0067 
0068                 textRole: "url"
0069                 valueRole: "url"
0070                 model: ServerListModel {
0071                     id: serverListModel
0072                     connection: root.connection
0073                 }
0074 
0075                 delegate: Delegates.RoundedItemDelegate {
0076                     id: serverItem
0077 
0078                     required property int index
0079                     required property string url
0080                     required property bool isAddServerDelegate
0081                     required property bool isHomeServer
0082                     required property bool isDeletable
0083 
0084                     text: isAddServerDelegate ? i18n("Add New Server") : url
0085                     highlighted: false
0086 
0087                     topInset: index === 0 ? Kirigami.Units.smallSpacing : Math.round(Kirigami.Units.smallSpacing / 2)
0088                     bottomInset: index === ListView.view.count - 1 ? Kirigami.Units.smallSpacing : Math.round(Kirigami.Units.smallSpacing / 2)
0089 
0090                     onClicked: if (isAddServerDelegate) {
0091                         addServerSheet.open()
0092                     }
0093 
0094                     contentItem: RowLayout {
0095                         spacing: Kirigami.Units.smallSpacing
0096 
0097                         Delegates.SubtitleContentItem {
0098                             itemDelegate: serverItem
0099                             subtitle: serverItem.isHomeServer ? i18n("Home Server") : ""
0100                             Layout.fillWidth: true
0101                         }
0102 
0103                         QQC2.ToolButton {
0104                             visible: serverItem.isAddServerDelegate || serverItem.isDeletable
0105                             icon.name: serverItem.isAddServerDelegate ? "list-add" : "dialog-close"
0106                             text: i18nc("@action:button", "Add new server")
0107                             Accessible.name: text
0108                             display: QQC2.AbstractButton.IconOnly
0109 
0110                             onClicked: {
0111                                 if (serverField.currentIndex === serverItem.index && serverItem.isDeletable) {
0112                                     serverField.currentIndex = 0;
0113                                     server = serverField.currentValue;
0114                                     serverField.popup.close();
0115                                 }
0116                                 if (serverItem.isAddServerDelegate) {
0117                                     addServerSheet.open();
0118                                     serverItem.clicked();
0119                                 } else {
0120                                     serverListModel.removeServerAtIndex(serverItem.index);
0121                                 }
0122                             }
0123                         }
0124                     }
0125                 }
0126 
0127                 onActivated: {
0128                     if (currentIndex !== count - 1) {
0129                         server = currentValue
0130                     }
0131                 }
0132 
0133                 Kirigami.OverlaySheet {
0134                     id: addServerSheet
0135 
0136                     parent: applicationWindow().overlay
0137 
0138                     title: i18nc("@title:window", "Add server")
0139 
0140                     onOpened: if (!serverUrlField.isValidServer && !addServerSheet.opened) {
0141                         serverField.currentIndex = 0
0142                         server = serverField.currentValue
0143                     } else if (addServerSheet.opened) {
0144                         serverUrlField.forceActiveFocus()
0145                     }
0146 
0147                     contentItem: Kirigami.FormLayout {
0148                         QQC2.Label {
0149                             Layout.minimumWidth: Kirigami.Units.gridUnit * 20
0150 
0151                             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")
0152                             color: serverUrlField.length > 0 ? (serverUrlField.acceptableInput ? (serverUrlField.isValidServer ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.negativeTextColor) : Kirigami.Theme.negativeTextColor) : Kirigami.Theme.textColor
0153                         }
0154                         QQC2.TextField {
0155                             id: serverUrlField
0156 
0157                             property bool isValidServer: false
0158 
0159                             Kirigami.FormData.label: i18n("Server URL")
0160                             onTextChanged: {
0161                                 if(acceptableInput) {
0162                                     serverListModel.checkServer(text)
0163                                 }
0164                             }
0165 
0166                             validator: RegularExpressionValidator {
0167                                 regularExpression: /^[a-zA-Z0-9-]{1,61}\.([a-zA-Z]{2,}|[a-zA-Z0-9-]{2,}\.[a-zA-Z]{2,3})$/
0168                             }
0169 
0170                             Connections {
0171                                 target: serverListModel
0172                                 function onServerCheckComplete(url, valid) {
0173                                     if (url == serverUrlField.text && valid) {
0174                                         serverUrlField.isValidServer = true
0175                                     }
0176                                 }
0177                             }
0178                         }
0179 
0180                         QQC2.Button {
0181                             id: okButton
0182 
0183                             text: i18nc("@action:button", "Ok")
0184                             enabled: serverUrlField.acceptableInput && serverUrlField.isValidServer
0185                             onClicked: {
0186                                 serverListModel.addServer(serverUrlField.text)
0187                                 serverField.currentIndex = serverField.indexOfValue(serverUrlField.text)
0188                                 server = serverField.currentValue
0189                                 serverUrlField.text = ""
0190                                 addServerSheet.close();
0191                             }
0192                         }
0193                     }
0194                 }
0195 
0196             }
0197         }
0198 
0199         Kirigami.Separator {
0200             z: 999
0201             anchors {
0202                 left: parent.left
0203                 right: parent.right
0204                 top: parent.bottom
0205             }
0206         }
0207     }
0208 
0209     ListView {
0210         id: publicRoomsListView
0211 
0212         topMargin: Math.round(Kirigami.Units.smallSpacing / 2)
0213         bottomMargin: Math.round(Kirigami.Units.smallSpacing / 2)
0214 
0215         model: PublicRoomListModel {
0216             id: publicRoomListModel
0217 
0218             connection: root.connection
0219             server: root.server
0220             keyword: root.keyword
0221             showOnlySpaces: root.showOnlySpaces
0222         }
0223 
0224         onContentYChanged: {
0225             if(publicRoomListModel.hasMore && contentHeight - contentY < publicRoomsListView.height + 200)
0226                 publicRoomListModel.next();
0227         }
0228         delegate: ExplorerDelegate {
0229             onRoomSelected: (roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
0230                 root.roomSelected(roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined);
0231                 root.closeDialog();
0232             }
0233         }
0234 
0235         header: Delegates.RoundedItemDelegate {
0236             Layout.fillWidth: true
0237             onClicked: _private.openManualRoomDialog()
0238 
0239             text: i18n("Enter a room address")
0240             icon.name: "compass"
0241             icon.width: Kirigami.Units.gridUnit * 2
0242             icon.height: Kirigami.Units.gridUnit * 2
0243         }
0244 
0245         footer: QQC2.ProgressBar {
0246             width: parent.width
0247             visible: publicRoomsListView.count !== 0 && publicRoomsListView.model.loading
0248             indeterminate: true
0249             padding: Kirigami.Units.largeSpacing * 2
0250             Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
0251             Layout.topMargin: Kirigami.Units.largeSpacing
0252             Layout.bottomMargin: Kirigami.Units.largeSpacing
0253             Layout.leftMargin: Kirigami.Units.largeSpacing
0254             Layout.rightMargin: Kirigami.Units.largeSpacing
0255         }
0256 
0257         Kirigami.LoadingPlaceholder {
0258             anchors.centerIn: parent
0259             visible: publicRoomsListView.model.loading && publicRoomsListView.count === 0
0260         }
0261 
0262         Kirigami.PlaceholderMessage {
0263             anchors.centerIn: parent
0264             visible: !publicRoomsListView.model.loading && publicRoomsListView.count === 0
0265             text: i18nc("@info:label", "No public rooms found")
0266         }
0267     }
0268 
0269     Component {
0270         id: manualRoomDialog
0271         ManualRoomDialog {}
0272     }
0273 
0274     QtObject {
0275         id: _private
0276         function openManualRoomDialog() {
0277             let dialog = manualRoomDialog.createObject(applicationWindow().overlay, {connection: root.connection});
0278             dialog.roomSelected.connect((roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
0279                 root.roomSelected(roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined);
0280                 root.closeDialog();
0281             });
0282             dialog.open();
0283         }
0284     }
0285 }