Files
neochat/src/qml/JoinRoomPage.qml
2024-01-06 17:34:56 +01:00

286 lines
11 KiB
QML

// SPDX-FileCopyrightText: 2019 Black Hat <bhat@encom.eu.org>
// SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
// SPDX-License-Identifier: GPL-3.0-only
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
import Qt.labs.qmlmodels
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.delegates as Delegates
import org.kde.neochat
Kirigami.ScrollablePage {
id: root
required property NeoChatConnection connection
property bool showOnlySpaces: false
property alias keyword: identifierField.text
property string server
/**
* @brief Signal emitted when a room is selected.
*
* The signal contains all the room's info so that it can be acted
* upon as required, e.g. joinng or entering the room or adding the room as
* the child of a space.
*/
signal roomSelected(string roomId,
string displayName,
url avatarUrl,
string alias,
string topic,
int memberCount,
bool isJoined)
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
Layout.fillWidth: true
placeholderText: i18n("Find a room...")
}
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
connection: root.connection
}
delegate: Delegates.RoundedItemDelegate {
id: serverItem
required property int index
required property string url
required property bool isAddServerDelegate
required property bool isHomeServer
required property bool isDeletable
text: isAddServerDelegate ? i18n("Add New Server") : url
highlighted: false
topInset: index === 0 ? Kirigami.Units.smallSpacing : Math.round(Kirigami.Units.smallSpacing / 2)
bottomInset: index === ListView.view.count - 1 ? Kirigami.Units.smallSpacing : Math.round(Kirigami.Units.smallSpacing / 2)
onClicked: if (isAddServerDelegate) {
addServerSheet.open()
}
contentItem: RowLayout {
spacing: Kirigami.Units.smallSpacing
Delegates.SubtitleContentItem {
itemDelegate: serverItem
subtitle: serverItem.isHomeServer ? i18n("Home Server") : ""
Layout.fillWidth: true
}
QQC2.ToolButton {
visible: serverItem.isAddServerDelegate || serverItem.isDeletable
icon.name: serverItem.isAddServerDelegate ? "list-add" : "dialog-close"
text: i18nc("@action:button", "Add new server")
Accessible.name: text
display: QQC2.AbstractButton.IconOnly
onClicked: {
if (serverField.currentIndex === serverItem.index && serverItem.isDeletable) {
serverField.currentIndex = 0;
server = serverField.currentValue;
serverField.popup.close();
}
if (serverItem.isAddServerDelegate) {
addServerSheet.open();
serverItem.clicked();
} else {
serverListModel.removeServerAtIndex(serverItem.index);
}
}
}
}
}
onActivated: {
if (currentIndex !== count - 1) {
server = currentValue
}
}
Kirigami.OverlaySheet {
id: addServerSheet
parent: applicationWindow().overlay
title: i18nc("@title:window", "Add server")
onOpened: if (!serverUrlField.isValidServer && !addServerSheet.opened) {
serverField.currentIndex = 0
server = serverField.currentValue
} else if (addServerSheet.opened) {
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)
server = serverField.currentValue
serverUrlField.text = ""
addServerSheet.close();
}
}
}
}
}
}
Kirigami.Separator {
z: 999
anchors {
left: parent.left
right: parent.right
top: parent.bottom
}
}
}
ListView {
id: publicRoomsListView
topMargin: Math.round(Kirigami.Units.smallSpacing / 2)
bottomMargin: Math.round(Kirigami.Units.smallSpacing / 2)
model: PublicRoomListModel {
id: publicRoomListModel
connection: root.connection
server: root.server
keyword: root.keyword
showOnlySpaces: root.showOnlySpaces
}
onContentYChanged: {
if(publicRoomListModel.hasMore && contentHeight - contentY < publicRoomsListView.height + 200)
publicRoomListModel.next();
}
delegate: ExplorerDelegate {
onRoomSelected: (roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
root.roomSelected(roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined);
root.closeDialog();
}
}
header: Delegates.RoundedItemDelegate {
Layout.fillWidth: true
onClicked: _private.openManualRoomDialog()
text: i18n("Enter a room address")
icon.name: "compass"
icon.width: Kirigami.Units.gridUnit * 2
icon.height: Kirigami.Units.gridUnit * 2
}
footer: QQC2.ProgressBar {
width: parent.width
visible: publicRoomsListView.count !== 0 && publicRoomsListView.model.loading
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 public rooms found")
}
}
Component {
id: manualRoomDialog
ManualRoomDialog {}
}
QtObject {
id: _private
function openManualRoomDialog() {
let dialog = manualRoomDialog.createObject(applicationWindow().overlay, {connection: root.connection});
dialog.roomSelected.connect((roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
root.roomSelected(roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined);
root.closeDialog();
});
dialog.open();
}
}
}