Manual Explore Rooms
This is an update to searching the public room list. Currently if you can't find the room you're looking for you can type a full alias of room ID into the search bar and a view/join button appears. This is hard to discover and technically broken since it was turned into a generic component for finding rooms (it kinda works but doesn't fit now as it's focussed on the joining rooms not adding new ones to spaces). It is also not very discoverable if you don't know it's there. This patch patch updates the workflow to be truly generic and hopefully more discoverable. Instead of using the search bar if no results are found a button asking if someone wants to manually enter a room ID or alias appears. This launches a dialog where the user can type in an alias or ID and it has some basic checking to make sure the string looks as expected. The new functionality also generically works for joining rooms and adding children to spaces.
This commit is contained in:
@@ -152,6 +152,7 @@ qt_add_qml_module(neochat URI org.kde.neochat NO_PLUGIN
|
||||
qml/RoomPage.qml
|
||||
qml/RoomWindow.qml
|
||||
qml/JoinRoomPage.qml
|
||||
qml/ManualRoomDialog.qml
|
||||
qml/ExplorerDelegate.qml
|
||||
qml/InviteUserPage.qml
|
||||
qml/StartChatPage.qml
|
||||
|
||||
@@ -26,7 +26,7 @@ RowLayout {
|
||||
if (isJoined) {
|
||||
RoomManager.enterRoom(root.connection.room(roomId))
|
||||
} else {
|
||||
Controller.joinRoom(roomId)
|
||||
Controller.joinRoom(roomId.length > 0 ? roomId : alias)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -52,32 +52,9 @@ Kirigami.ScrollablePage {
|
||||
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
|
||||
|
||||
@@ -252,19 +229,26 @@ Kirigami.ScrollablePage {
|
||||
}
|
||||
}
|
||||
|
||||
footer: RowLayout {
|
||||
width: parent.width
|
||||
header: Delegates.RoundedItemDelegate {
|
||||
Layout.fillWidth: true
|
||||
onClicked: _private.openManualRoomDialog()
|
||||
|
||||
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
|
||||
}
|
||||
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 {
|
||||
@@ -275,7 +259,24 @@ Kirigami.ScrollablePage {
|
||||
Kirigami.PlaceholderMessage {
|
||||
anchors.centerIn: parent
|
||||
visible: !publicRoomsListView.model.loading && publicRoomsListView.count === 0
|
||||
text: i18nc("@info:label", "No rooms found")
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
119
src/qml/ManualRoomDialog.qml
Normal file
119
src/qml/ManualRoomDialog.qml
Normal file
@@ -0,0 +1,119 @@
|
||||
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.components as KirigamiComponents
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
Kirigami.Dialog {
|
||||
id: root
|
||||
|
||||
/**
|
||||
* @brief The connection for the current user.
|
||||
*/
|
||||
required property NeoChatConnection connection
|
||||
|
||||
/**
|
||||
* @brief Signal emitted when a valid room id or alias is entered.
|
||||
*/
|
||||
signal roomSelected(string roomId,
|
||||
string displayName,
|
||||
url avatarUrl,
|
||||
string alias,
|
||||
string topic,
|
||||
int memberCount,
|
||||
bool isJoined)
|
||||
|
||||
title: i18nc("@title", "Room ID or Alias")
|
||||
|
||||
width: Math.min(applicationWindow().width, Kirigami.Units.gridUnit * 24)
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
standardButtons: Kirigami.Dialog.Cancel
|
||||
customFooterActions: [
|
||||
Kirigami.Action {
|
||||
enabled: roomIdAliasText.isValidText
|
||||
text: i18n("OK")
|
||||
icon.name: "dialog-ok"
|
||||
onTriggered: {
|
||||
// We don't necessarily have all the info so fill out the best we can.
|
||||
let roomId = roomIdAliasText.isAlias() ? "" : roomIdAliasText.text;
|
||||
let displayName = "";
|
||||
let avatarUrl = "";
|
||||
let alias = roomIdAliasText.isAlias() ? roomIdAliasText.text : "";
|
||||
let topic = "";
|
||||
let memberCount = -1;
|
||||
let isJoined = false;
|
||||
if (roomIdAliasText.room) {
|
||||
roomId = roomIdAliasText.room.id;
|
||||
displayName = roomIdAliasText.room.displayName;
|
||||
avatarUrl = roomIdAliasText.room.avatarUrl.toString().length > 0 ? connection.makeMediaUrl(roomIdAliasText.room.avatarUrl) : ""
|
||||
alias = roomIdAliasText.room.canonicalAlias;
|
||||
topic = roomIdAliasText.room.topic;
|
||||
memberCount = roomIdAliasText.room.joinedCount;
|
||||
isJoined = true;
|
||||
}
|
||||
root.roomSelected(roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined);
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: roomIdAliasText
|
||||
property bool isValidText: text.match(/(#|!)(.+):(.+)/g)
|
||||
property bool correctStart: text.startsWith("#") || text.startsWith("!")
|
||||
property NeoChatRoom room: {
|
||||
if (!acceptableInput) {
|
||||
return null;
|
||||
}
|
||||
if (isAlias()) {
|
||||
return root.connection.roomByAlias(text);
|
||||
} else {
|
||||
return root.connection.room(text);
|
||||
}
|
||||
}
|
||||
|
||||
label: i18n("Room ID or Alias:")
|
||||
statusMessage: {
|
||||
if (text.length > 0 && !correctStart) {
|
||||
return i18n("Must start with # for an alias or ! for an ID");
|
||||
}
|
||||
if (timer.running) {
|
||||
return "";
|
||||
}
|
||||
if (text.length > 0 && !isValidText) {
|
||||
return i18n("The input is not a valid room ID or alias");
|
||||
}
|
||||
return correctStart ? "" : i18n("Must start with # for an alias or ! for an ID");
|
||||
}
|
||||
status: text.length > 0 ? Kirigami.MessageType.Error : Kirigami.MessageType.Information
|
||||
|
||||
onTextEdited: timer.restart()
|
||||
|
||||
function isAlias() {
|
||||
return roomIdAliasText.text.startsWith("#");
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
roomIdAliasText.forceActiveFocus()
|
||||
timer.restart()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user