da4a5ab5cd
- Refactor everything about HBox, and adapt all the pages and popups that used it - Replace HTabContainer by HTabbedBox - Make boxes swippable - Make esc presses in boxes click the cancel button - Make all boxes and popups scrollable when needed - Replace generic apply button icons in popups - Fix tab focus for error and invite popups - Rework (still WIP) the account settings page: - Use the standard tabbed design of other pages - Ditch the horizontal profile layout, hacky and impossible to extend - Add real-time coloring for the display name field - Implement a device list in account settings (Sessions, still WIP)
148 lines
4.1 KiB
QML
148 lines
4.1 KiB
QML
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
import QtQuick 2.12
|
|
import QtQuick.Controls 2.12
|
|
import QtQuick.Layouts 1.12
|
|
import "../Base"
|
|
import "../Base/ButtonLayout"
|
|
|
|
HColumnPopup {
|
|
id: popup
|
|
|
|
|
|
property string userId
|
|
property string roomId
|
|
property string roomName
|
|
property bool invitingAllowed: true
|
|
|
|
property var inviteFuture: null
|
|
property var successfulInvites: []
|
|
property var failedInvites: []
|
|
|
|
|
|
function invite() {
|
|
inviteButton.loading = true
|
|
|
|
const inviteesLeft = inviteArea.text.trim().split(/\s+/).filter(
|
|
user => ! successfulInvites.includes(user)
|
|
)
|
|
|
|
inviteFuture = py.callClientCoro(
|
|
userId,
|
|
"room_mass_invite",
|
|
[roomId, ...inviteesLeft],
|
|
|
|
([successes, errors]) => {
|
|
if (errors.length < 1) {
|
|
popup.close()
|
|
return
|
|
}
|
|
|
|
successfulInvites = successes
|
|
failedInvites = errors
|
|
inviteButton.loading = false
|
|
}
|
|
)
|
|
}
|
|
|
|
|
|
page.footer: ButtonLayout {
|
|
ApplyButton {
|
|
id: inviteButton
|
|
text: qsTr("Invite")
|
|
icon.name: "room-send-invite"
|
|
enabled: invitingAllowed && Boolean(inviteArea.text.trim())
|
|
onClicked: invite()
|
|
}
|
|
|
|
CancelButton {
|
|
id: cancelButton
|
|
onClicked: popup.close()
|
|
}
|
|
}
|
|
|
|
onOpened: inviteArea.forceActiveFocus()
|
|
onClosed: if (inviteFuture) inviteFuture.cancel()
|
|
|
|
onInvitingAllowedChanged:
|
|
if (! invitingAllowed && inviteFuture) inviteFuture.cancel()
|
|
|
|
|
|
SummaryLabel {
|
|
text: qsTr("Invite members to <i>%1</i>").arg(roomName)
|
|
textFormat: Text.StyledText
|
|
}
|
|
|
|
HScrollView {
|
|
clip: true
|
|
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
|
|
HTextArea {
|
|
id: inviteArea
|
|
focusItemOnTab: inviteButton.enabled ? inviteButton : cancelButton
|
|
placeholderText:
|
|
qsTr("User IDs (e.g. @bob:matrix.org @alice:localhost)")
|
|
}
|
|
}
|
|
|
|
HLabel {
|
|
id: errorMessage
|
|
visible: Layout.maximumHeight > 0
|
|
wrapMode: Text.Wrap
|
|
color: theme.colors.errorText
|
|
text:
|
|
invitingAllowed ?
|
|
allErrors :
|
|
qsTr("You do not have permission to invite members to this room")
|
|
|
|
Layout.maximumHeight: text ? implicitHeight : 0
|
|
Layout.fillWidth: true
|
|
|
|
readonly property string allErrors: {
|
|
// TODO: handle these: real user not found
|
|
const lines = []
|
|
|
|
for (const [user, error] of failedInvites) {
|
|
const type = py.getattr(
|
|
py.getattr(error, "__class__"), "__name__",
|
|
)
|
|
|
|
lines.push(
|
|
type === "InvalidUserId" ?
|
|
qsTr("%1 is not a valid user ID, expected format is " +
|
|
"@username:homeserver").arg(user) :
|
|
|
|
type === "UserFromOtherServerDisallowed" ?
|
|
qsTr("This room rejects users from other matrix " +
|
|
"servers, can't invite %1").arg(user) :
|
|
|
|
type === "MatrixNotFound" ?
|
|
qsTr("%1 not found, please verify the entered ID")
|
|
.arg(user) :
|
|
|
|
type === "MatrixBadGateway" ?
|
|
qsTr("Could not contact %1's server, " +
|
|
"please verify the entered ID").arg(user) :
|
|
|
|
type === "MatrixUnsupportedRoomVersion" ?
|
|
qsTr("%1's server does not support this room's version")
|
|
.arg(user) :
|
|
|
|
type === "MatrixForbidden" ?
|
|
qsTr("%1 is banned from this room")
|
|
.arg(user) :
|
|
|
|
qsTr("Unknown error while inviting %1: %2 - %3")
|
|
.arg(user).arg(type).arg(py.getattr(error, "args"))
|
|
)
|
|
}
|
|
|
|
return lines.join("\n\n")
|
|
}
|
|
|
|
Behavior on Layout.maximumHeight { HNumberAnimation {} }
|
|
}
|
|
}
|