import QtQuick 2.12 import QtQuick.Controls 2.3 import QtGraphicalEffects 1.13 import QtQuick.Dialogs 1.3 import utils 1.0 import shared.panels 1.0 import shared.popups 1.0 import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 import StatusQ.Components 0.1 import StatusQ.Controls 0.1 import StatusQ.Controls.Validators 0.1 import StatusQ.Popups 0.1 StatusModal { id: popup height: 509 property var store property bool isEdit: false property QtObject community: popup.store.chatsModelInst.communities.activeCommunity readonly property int maxCommunityNameLength: 30 readonly property int maxCommunityDescLength: 140 readonly property var communityColorValidator: Utils.Validate.NoEmpty | Utils.Validate.TextHexColor onOpened: { if (isEdit) { contentItem.communityName.input.text = community.name; contentItem.communityDescription.input.text = community.description; contentItem.communityColor.color = community.communityColor; contentItem.communityColor.colorSelected = true if (community.largeImage) { contentItem.communityImage.selectedImage = community.largeImage } membershipRequirementSettingPopup.checkedMembership = community.access } contentItem.communityName.input.forceActiveFocus(Qt.MouseFocusReason) } onClosed: destroy() function isFormValid() { return contentItem.communityName.valid && contentItem.communityDescription.valid && Utils.validateAndReturnError(contentItem.communityColor.color.toString().toUpperCase(), communityColorValidator) === "" } header.title: isEdit ? //% "Edit community" qsTrId("edit-community") : //% "New community" qsTrId("new-community") contentItem: ScrollView { id: scrollView property ScrollBar vScrollBar: ScrollBar.vertical property alias communityName: nameInput property alias communityDescription: descriptionTextArea property alias communityColor: colorDialog property alias communityImage: addImageButton property alias imageCropperModal: imageCropperModal contentHeight: content.height bottomPadding: 8 width: popup.width ScrollBar.horizontal.policy: ScrollBar.AlwaysOff clip: true function scrollBackUp() { vScrollBar.setPosition(0) } Column { id: content width: popup.width spacing: 8 Item { height: 8 width: parent.width } StatusInput { id: nameInput label: qsTr("Name your community") charLimit: maxCommunityNameLength input.placeholderText: qsTr("A catchy name") validators: [StatusMinLengthValidator { minLength: 1 errorMessage: Utils.getErrorMessage(nameInput.errors, "community name") }] } StatusInput { id: descriptionTextArea label: qsTr("Description") charLimit: maxCommunityDescLength input.placeholderText: qsTr("What your community is about") input.multiline: true input.implicitHeight: 88 validators: [StatusMinLengthValidator { minLength: 1 errorMessage: Utils.getErrorMessage(descriptionTextArea.errors, "community description") }] } StatusBaseText { id: thumbnailText //% "Thumbnail image" text: qsTrId("thumbnail-image") font.pixelSize: 15 color: Theme.palette.directColor1 anchors.left: parent.left anchors.leftMargin: 16 anchors.topMargin: 8 } Item { width: parent.width height: addImageButton.height + 32 Rectangle { id: addImageButton color: imagePreview.visible ? "transparent" : Style.current.inputBackground width: 128 height: width radius: width / 2 anchors.centerIn: parent property string selectedImage: "" FileDialog { id: imageDialog //% "Please choose an image" title: qsTrId("please-choose-an-image") folder: shortcuts.pictures nameFilters: [ //% "Image files (*.jpg *.jpeg *.png)" qsTrId("image-files----jpg---jpeg---png-") ] onAccepted: { addImageButton.selectedImage = imageDialog.fileUrls[0] imageCropperModal.open() } } Rectangle { id: imagePreviewCropper clip: true width: parent.width height: parent.height radius: parent.width / 2 visible: !!addImageButton.selectedImage Image { id: imagePreview visible: !!addImageButton.selectedImage source: addImageButton.selectedImage fillMode: Image.PreserveAspectFit width: parent.width height: parent.height } layer.enabled: true layer.effect: OpacityMask { maskSource: Rectangle { anchors.centerIn: parent width: imageCropperModal.width height: imageCropperModal.height radius: width / 2 } } } Item { id: addImageCenter visible: !imagePreview.visible width: uploadText.width height: childrenRect.height anchors.centerIn: parent SVGImage { id: imageImg source: Style.svg("images_icon") width: 20 height: 18 anchors.horizontalCenter: parent.horizontalCenter } StatusBaseText { id: uploadText //% "Upload" text: qsTrId("upload") anchors.top: imageImg.bottom anchors.topMargin: 5 font.pixelSize: 15 color: Theme.palette.baseColor1 } } StatusRoundButton { type: StatusRoundButton.Type.Secondary icon.name: "add" anchors.top: parent.top anchors.right: parent.right anchors.rightMargin: Style.current.halfPadding highlighted: sensor.containsMouse } MouseArea { id: sensor hoverEnabled: true anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: imageDialog.open() } ImageCropperModal { id: imageCropperModal selectedImage: addImageButton.selectedImage ratio: "1:1" } } } StatusBaseText { //% "Community colour" text: qsTrId("community-color") font.pixelSize: 15 color: Theme.palette.directColor1 anchors.left: parent.left anchors.leftMargin: 16 } Item { anchors.horizontalCenter: parent.horizontalCenter height: colorSelectorButton.height + 16 width: parent.width - 32 StatusPickerButton { id: colorSelectorButton anchors.top: parent.top anchors.topMargin: 10 property string validationError: "" bgColor: colorDialog.colorSelected ? colorDialog.color : Theme.palette.baseColor2 contentColor: colorDialog.colorSelected ? Theme.palette.indirectColor1 : Theme.palette.baseColor1 text: colorDialog.colorSelected ? colorDialog.color.toString().toUpperCase() : //% "Pick a color" qsTrId("pick-a-color") onClicked: colorDialog.open(); onTextChanged: { if (colorDialog.colorSelected) { validationError = Utils.validateAndReturnError(text, communityColorValidator) } } ColorDialog { id: colorDialog property bool colorSelected: false color: Theme.palette.primaryColor1 onAccepted: colorSelected = true } } StatusBaseText { text: colorSelectorButton.validationError visible: !!text color: Theme.palette.dangerColor1 anchors.top: colorSelectorButton.bottom anchors.topMargin: 4 anchors.right: colorSelectorButton.right } } StatusModalDivider { topPadding: 8 bottomPadding: 8 visible: !isEdit } StatusListItem { anchors.horizontalCenter: parent.horizontalCenter visible: !isEdit //% "Membership requirement" title: qsTrId("membership-title") label: { switch (membershipRequirementSettingPopup.checkedMembership) { //% "Require invite from another member" case Constants.communityChatInvitationOnlyAccess: return qsTrId("membership-invite") //% "Require approval" case Constants.communityChatOnRequestAccess: return qsTrId("membership-approval") //% "No requirement" default: return qsTrId("membership-free") } } sensor.onClicked: membershipRequirementSettingPopup.open() components: [ StatusIcon { icon: "chevron-down" rotation: 270 color: Theme.palette.baseColor1 } ] } StatusBaseText { visible: !isEdit height: visible ? implicitHeight : 0 wrapMode: Text.WordWrap font.pixelSize: 13 color: Theme.palette.baseColor1 width: parent.width * 0.78 //% "You can require new members to meet certain criteria before they can join. This can be changed at any time" text: qsTrId("membership-none-placeholder") anchors.left: parent.left anchors.leftMargin: 16 } // Feature commented temporarily /* StatusSettingsLineButton { id: ensOnlySwitch anchors.top: privateExplanation.bottom anchors.topMargin: Style.current.padding isEnabled: profileModel.profile.ensVerified //% "Require ENS username" text: qsTrId("membership-ens") isSwitch: true onClicked: switchChecked = checked StatusToolTip { visible: !ensOnlySwitch.isEnabled && ensMouseArea.isHovered //% "You can only enable this setting if you have an ENS name" text: qsTrId("you-can-only-enable-this-setting-if-you-have-an-ens-name") } MouseArea { property bool isHovered: false id: ensMouseArea enabled: !ensOnlySwitch.isEnabled visible: enabled anchors.fill: parent hoverEnabled: true onEntered: isHovered = true onExited: isHovered = false } } StyledText { visible: !isEdit height: visible ? implicitHeight : 0 id: ensExplanation anchors.top: ensOnlySwitch.bottom wrapMode: Text.WordWrap anchors.topMargin: isEdit ? 0 : Style.current.halfPadding width: parent.width //% "Your community requires an ENS username to be able to join" text: qsTrId("membership-ens-description") } */ } } leftButtons: [ StatusRoundButton { id: btnBack visible: isEdit icon.name: "arrow-right" icon.width: 20 icon.height: 16 rotation: 180 onClicked: popup.destroy() } ] rightButtons: [ StatusButton { id: btnCreateEdit enabled: isFormValid() text: isEdit ? //% "Save" qsTrId("Save") : //% "Create" qsTrId("create") onClicked: { if (!isFormValid()) { popup.contentItem.scrollBackUp() return } let error = false; if(isEdit) { error = popup.store.editCommunity( community.id, Utils.filterXSS(popup.contentItem.communityName.input.text), Utils.filterXSS(popup.contentItem.communityDescription.input.text), membershipRequirementSettingPopup.checkedMembership, false, popup.contentItem.communityColor.color.toString().toUpperCase(), // to retain the existing image, pass "" for the image path popup.contentItem.communityImage.selectedImage === community.largeImage ? "" : popup.contentItem.communityImage.selectedImage, popup.contentItem.imageCropperModal.aX, popup.contentItem.imageCropperModal.aY, popup.contentItem.imageCropperModal.bX, popup.contentItem.imageCropperModal.bY ) } else { error = popup.store.createCommunity( Utils.filterXSS(popup.contentItem.communityName.input.text), Utils.filterXSS(popup.contentItem.communityDescription.input.text), membershipRequirementSettingPopup.checkedMembership, false, // ensOnlySwitch.switchChecked, // TODO: popup.contentItem.communityColor.color.toString().toUpperCase(), popup.contentItem.communityImage.selectedImage, popup.contentItem.imageCropperModal.aX, popup.contentItem.imageCropperModal.aY, popup.contentItem.imageCropperModal.bX, popup.contentItem.imageCropperModal.bY ) } if (error) { creatingError.text = error.error return creatingError.open() } popup.close() } } ] MessageDialog { id: creatingError //% "Error creating the community" title: qsTrId("error-creating-the-community") icon: StandardIcon.Critical standardButtons: StandardButton.Ok } MembershipRequirementPopup { anchors.centerIn: parent id: membershipRequirementSettingPopup } }