Pascal Precht 9f6a4f7834 fix(CreateCategoryPopup): ensure delete button and name input stay in viewport
There are a few issues with the popup's content when there are many channels in a community:

1. Channel items belonging to other categories would still take space in the list
1. Due to the longer list of channels, the delete button wouldn't be fully visible (scrolling down
   helps here)
2. Scrolling down is hard because the `ListView` in use is `interactive`
3. Even when `interactive` is set to false, one would scroll the name input out of the viewport.

To solve these, this commit rearchitects the popup's content such that:

1. The name input is always static and in place
2. The scrollview starts with the channel list and ends with the channel list
3. The delete button is positioned below the scrollview
4. The scrollview has a max height of 300 so that the popup doesn't grow too big
5. Invisible channel items won't have a height anymore

The result is that the middle section of the popup becomes scrollable in case there's many
channel items, while both, the name input and the delete button stay in the viewport.

Fixes #3013
2021-07-22 13:52:33 -04:00

266 lines
9.1 KiB
QML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import QtQuick 2.12
import QtQuick.Controls 2.3
import QtGraphicalEffects 1.13
import QtQuick.Dialogs 1.3
import "../../../../imports"
import "../../../../shared"
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
StatusModal {
property string communityId
property string categoryId
property string categoryName: ""
property var channels: []
property bool isEdit: false
readonly property int maxCategoryNameLength: 30
readonly property var categoryNameValidator: Utils.Validate.NoEmpty
| Utils.Validate.TextLength
id: popup
onOpened: {
if(isEdit){
popup.contentComponent.categoryName.text = categoryName
channels = JSON.parse(chatsModel.communities.activeCommunity.getChatIdsByCategory(categoryId))
}
popup.contentComponent.categoryName.forceActiveFocus(Qt.MouseFocusReason)
}
onClosed: destroy()
function isFormValid() {
return Utils.validateAndReturnError(popup.contentComponent.categoryName.text,
categoryNameValidator,
//% "category name"
qsTrId("category-name"),
maxCategoryNameLength) === ""
}
header.title: isEdit ?
//% "Edit category"
qsTrId("edit-category") :
//% "New category"
qsTrId("new-category")
content: Column {
width: popup.width
property alias categoryName: nameInput
Item {
width: parent.width
height: 76
Input {
id: nameInput
width: parent.width -32
anchors.centerIn: parent
anchors.left: undefined
anchors.right: undefined
//% "Category title"
placeholderText: qsTrId("category-title")
maxLength: maxCategoryNameLength
onTextEdited: {
validationError = Utils.validateAndReturnError(text,
categoryNameValidator,
//% "category name"
qsTrId("category-name"),
maxCategoryNameLength)
}
}
}
StatusModalDivider {
topPadding: 8
bottomPadding: 8
}
ScrollView {
id: scrollView
width: popup.width
height: Math.min(content.height, 300)
anchors.horizontalCenter: parent.horizontalCenter
property ScrollBar vScrollBar: ScrollBar.vertical
contentHeight: content.height
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
clip: true
function scrollBackUp() {
vScrollBar.setPosition(0)
}
Item {
id: content
width: parent.width
height: channelsLabel.height + communityChannelList.height
Item {
id: channelsLabel
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width - 32
height: 34
StatusBaseText {
//% "Channels"
text: qsTrId("channels")
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
font.pixelSize: 15
color: Theme.palette.baseColor1
}
}
ListView {
id: communityChannelList
anchors.top: channelsLabel.bottom
height: childrenRect.height
width: parent.width
model: chatsModel.communities.activeCommunity.chats
interactive: false
clip: true
delegate: StatusListItem {
anchors.horizontalCenter: parent.horizontalCenter
visible: popup.isEdit ?
model.categoryId === popup.categoryId || model.categoryId === "" :
model.categoryId === ""
height: visible ? implicitHeight : 0
title: "#" + model.name
icon.isLetterIdenticon: true
icon.background.color: model.color
sensor.onClicked: channelItemCheckbox.checked = !channelItemCheckbox.checked
components: [
StatusCheckBox {
id: channelItemCheckbox
checked: popup.isEdit ? popup.channels.indexOf(model.id) > - 1 : false
onCheckedChanged: {
var idx = popup.channels.indexOf(model.id)
if(checked){
if(idx === -1){
popup.channels.push(model.id)
}
} else {
if(idx > -1){
popup.channels.splice(idx, 1);
}
}
}
}
]
}
}
}
}
StatusModalDivider {
visible: deleteCategoryButton.visible
topPadding: 8
bottomPadding: 8
}
StatusListItem {
id: deleteCategoryButton
anchors.horizontalCenter: parent.horizontalCenter
visible: isEdit
//% "Delete category"
title: qsTrId("delete-category")
icon.name: "delete"
type: StatusListItem.Type.Danger
sensor.onClicked: {
openPopup(deleteCategoryConfirmationDialogComponent, {
//% "Delete %1 category"
title: qsTrId("delete--1-category").arg(popup.contentComponent.categoryName.text),
//% "Are you sure you want to delete %1 category? Channels inside the category wont be deleted."
confirmationText: qsTrId("are-you-sure-you-want-to-delete--1-category--channels-inside-the-category-won-t-be-deleted-").arg(popup.contentComponent.categoryName.text)
})
}
}
Item {
height: 8
width: parent.width
}
Component {
id: deleteCategoryConfirmationDialogComponent
ConfirmationDialog {
btnType: "warn"
height: 216
showCancelButton: true
onClosed: {
destroy()
}
onCancelButtonClicked: {
close();
}
onConfirmButtonClicked: function(){
const error = chatsModel.communities.deleteCommunityCategory(chatsModel.communities.activeCommunity.id, popup.categoryId)
if (error) {
creatingError.text = error
return creatingError.open()
}
close();
popup.close()
}
}
}
}
rightButtons: [
StatusButton {
enabled: isFormValid()
text: isEdit ?
//% "Save"
qsTrId("save") :
//% "Create"
qsTrId("create")
onClicked: {
if (!isFormValid()) {
scrollView.scrollBackUp()
return
}
let error = ""
if (isEdit) {
error = chatsModel.communities.editCommunityCategory(communityId, categoryId, Utils.filterXSS(popup.contentComponent.categoryName.text), JSON.stringify(channels))
} else {
error = chatsModel.communities.createCommunityCategory(communityId, Utils.filterXSS(popup.contentComponent.categoryName.text), JSON.stringify(channels))
}
if (error) {
categoryError.text = error
return categoryError.open()
}
popup.close()
}
}
]
MessageDialog {
id: categoryError
title: isEdit ?
//% "Error editing the category"
qsTrId("error-editing-the-category") :
//% "Error creating the category"
qsTrId("error-creating-the-category")
icon: StandardIcon.Critical
standardButtons: StandardButton.Ok
}
}