feat(CreateCommunityPopup): validation and ensuring min. 1 tag added
- enable the Next button, and delay the validation after it's been clicked - visually display required fields also for logo, banner, and tags (min 1 tag is required now) - when pasting over limit, chop the text to the maximum length, instead of just leaving the text field empty - do not let the popup autoclose on clicking outside or pressing Esc - add a StoryBook page - minor cleanups and alignments to the latest Figma designs/flows Fixes #13966 Fixes #16479 Fixes #14902
This commit is contained in:
parent
5518df3af9
commit
26dddcaff9
|
@ -0,0 +1,181 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
import StatusQ 0.1
|
||||||
|
|
||||||
|
import Storybook 1.0
|
||||||
|
import Models 1.0
|
||||||
|
|
||||||
|
import mainui 1.0
|
||||||
|
|
||||||
|
import shared.stores 1.0 as SharedStores
|
||||||
|
|
||||||
|
import AppLayouts.Communities.popups 1.0
|
||||||
|
import AppLayouts.Communities.controls 1.0
|
||||||
|
import AppLayouts.Communities.stores 1.0 as CommunitiesStores
|
||||||
|
|
||||||
|
import AppLayouts.stores 1.0 as AppLayoutStores
|
||||||
|
|
||||||
|
SplitView {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
Logs { id: logs }
|
||||||
|
|
||||||
|
orientation: Qt.Vertical
|
||||||
|
|
||||||
|
property var dialog
|
||||||
|
|
||||||
|
function createAndOpenDialog() {
|
||||||
|
dialog = dlgComponent.createObject(popupBg)
|
||||||
|
dialog.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: createAndOpenDialog()
|
||||||
|
|
||||||
|
Item {
|
||||||
|
SplitView.fillWidth: true
|
||||||
|
SplitView.fillHeight: true
|
||||||
|
|
||||||
|
PopupBackground {
|
||||||
|
id: popupBg
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Button {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Reopen"
|
||||||
|
|
||||||
|
onClicked: createAndOpenDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Popups {
|
||||||
|
popupParent: root
|
||||||
|
sharedRootStore: SharedStores.RootStore {}
|
||||||
|
rootStore: AppLayoutStores.RootStore {}
|
||||||
|
communityTokensStore: SharedStores.CommunityTokensStore {}
|
||||||
|
isDevBuild: ctrlIsDevBuild.checked
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: dlgComponent
|
||||||
|
CreateCommunityPopup {
|
||||||
|
id: dialog
|
||||||
|
anchors.centerIn: parent
|
||||||
|
destroyOnClose: true
|
||||||
|
modal: false
|
||||||
|
isDiscordImport: isDiscordCheckBox.checked
|
||||||
|
isDevBuild: ctrlIsDevBuild.checked
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: localAppSettings
|
||||||
|
readonly property bool testEnvironment: dialog.isDevBuild
|
||||||
|
}
|
||||||
|
|
||||||
|
store: CommunitiesStores.CommunitiesStore {
|
||||||
|
readonly property string communityTags: ModelsData.communityTags
|
||||||
|
|
||||||
|
function createCommunity() {
|
||||||
|
logs.logEvent("createCommunity")
|
||||||
|
}
|
||||||
|
|
||||||
|
property string discordImportChannelName
|
||||||
|
readonly property bool discordImportInProgress: false
|
||||||
|
readonly property bool discordDataExtractionInProgress: false
|
||||||
|
readonly property int discordImportErrorsCount: 0
|
||||||
|
readonly property int discordImportWarningsCount: 0
|
||||||
|
readonly property int discordOldestMessageTimestamp: 0
|
||||||
|
|
||||||
|
property var discordFileList: ListModel {
|
||||||
|
readonly property int selectedCount: count
|
||||||
|
property bool selectedFilesValid
|
||||||
|
}
|
||||||
|
|
||||||
|
property var discordCategoriesModel: ListModel {}
|
||||||
|
|
||||||
|
property var discordChannelsModel: ListModel {
|
||||||
|
property bool hasSelectedItems
|
||||||
|
readonly property int count: 32 // hide the parsing/loading spinner
|
||||||
|
}
|
||||||
|
|
||||||
|
function setFileListItems(filePaths) {
|
||||||
|
for (const filePath of filePaths) {
|
||||||
|
discordFileList.append({"filePath": filePath, errorMessage: ""})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeFileListItem(path) {
|
||||||
|
for (let i = 0; i < discordFileList.count; i++) {
|
||||||
|
const item = discordFileList.get(i)
|
||||||
|
if (item.filePath === path)
|
||||||
|
discordFileList.remove(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearFileList() {
|
||||||
|
discordFileList.clear()
|
||||||
|
discordFileList.selectedFilesValid = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearDiscordCategoriesAndChannels() {
|
||||||
|
discordCategoriesModel.clear()
|
||||||
|
discordChannelsModel.clear()
|
||||||
|
discordChannelsModel.hasSelectedItems = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestExtractChannelsAndCategories() {
|
||||||
|
discordFileList.selectedFilesValid = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleOneDiscordChannel(id) {
|
||||||
|
logs.logEvent("toggleOneDiscordChannel", ["id"], arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetDiscordImport() {
|
||||||
|
logs.logEvent("resetDiscordImport")
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestCancelDiscordChannelImport(id) {
|
||||||
|
logs.logEvent("requestCancelDiscordChannelImport", ["id"], arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestImportDiscordChannel(args, timestamp) {
|
||||||
|
logs.logEvent("requestImportDiscordChannel", ["args", "timestamp"], arguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogsAndControlsPanel {
|
||||||
|
SplitView.minimumHeight: 100
|
||||||
|
SplitView.preferredHeight: 200
|
||||||
|
|
||||||
|
logsView.logText: logs.logText
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Switch {
|
||||||
|
id: isDiscordCheckBox
|
||||||
|
text: "Discord import"
|
||||||
|
onToggled: {
|
||||||
|
if (!!dialog && dialog.opened)
|
||||||
|
dialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Switch {
|
||||||
|
id: ctrlIsDevBuild
|
||||||
|
text: "Dev build"
|
||||||
|
onToggled: {
|
||||||
|
if (!!dialog && dialog.opened)
|
||||||
|
dialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// category: Popups
|
||||||
|
|
||||||
|
// https://www.figma.com/design/qHfFm7C9LwtXpfdbxssCK3/Kuba%E2%8E%9CDesktop---Communities?node-id=52741-266926&node-type=frame&t=PkDxeWSXoiZbIQXv-0
|
||||||
|
// https://www.figma.com/design/qHfFm7C9LwtXpfdbxssCK3/Kuba%E2%8E%9CDesktop---Communities?node-id=2636-359221&node-type=frame&t=PkDxeWSXoiZbIQXv-0
|
||||||
|
// https://www.figma.com/design/qHfFm7C9LwtXpfdbxssCK3/Kuba%E2%8E%9CDesktop---Communities?node-id=52741-267155&node-type=frame&t=PkDxeWSXoiZbIQXv-0
|
|
@ -1,4 +1,4 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
|
|
||||||
import StatusQ 0.1
|
import StatusQ 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
|
@ -76,7 +76,7 @@ Item {
|
||||||
delegate: StatusCommunityTag {
|
delegate: StatusCommunityTag {
|
||||||
emoji: model.emoji
|
emoji: model.emoji
|
||||||
name: model.name
|
name: model.name
|
||||||
removable: root.mode === StatusCommunityTags.ShowSelectedOnly && root.active
|
removable: root.mode === StatusCommunityTags.ShowSelectedOnly && root.active && repeater.count > 1
|
||||||
highlighted: root.mode === StatusCommunityTags.Highlight && model.selected
|
highlighted: root.mode === StatusCommunityTags.Highlight && model.selected
|
||||||
|
|
||||||
onClicked: root.clicked(model)
|
onClicked: root.clicked(model)
|
||||||
|
|
|
@ -419,7 +419,7 @@ Item {
|
||||||
let utf8Length = Utils.encodeUtf8(text).length
|
let utf8Length = Utils.encodeUtf8(text).length
|
||||||
if (utf8Length > root.maximumLength) {
|
if (utf8Length > root.maximumLength) {
|
||||||
var cursor = cursorPosition
|
var cursor = cursorPosition
|
||||||
text = previousText
|
text = text.slice(0, maximumLength)
|
||||||
if (cursor > edit.length) {
|
if (cursor > edit.length) {
|
||||||
cursorPosition = edit.length
|
cursorPosition = edit.length
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import QtQuick 2.13
|
import QtQuick 2.15
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
|
||||||
import "./"
|
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
@ -27,7 +25,6 @@ Column {
|
||||||
id: title
|
id: title
|
||||||
width: parent.width
|
width: parent.width
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.baseColor1
|
color: Theme.palette.baseColor1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,8 +97,8 @@ Item {
|
||||||
*/
|
*/
|
||||||
property alias errorMessageCmp: errorMessage
|
property alias errorMessageCmp: errorMessage
|
||||||
/*!
|
/*!
|
||||||
\qmlproperty string StatusInput::label
|
\qmlproperty int StatusInput::labelPadding
|
||||||
This property sets the label text.
|
This property sets the padding of the label text.
|
||||||
*/
|
*/
|
||||||
property int labelPadding: 8
|
property int labelPadding: 8
|
||||||
/*!
|
/*!
|
||||||
|
@ -118,7 +118,7 @@ Item {
|
||||||
property int charLimit: 0
|
property int charLimit: 0
|
||||||
/*!
|
/*!
|
||||||
\qmlproperty string StatusInput::charLimitLabel
|
\qmlproperty string StatusInput::charLimitLabel
|
||||||
This property overrides the char default chart limit text format.
|
This property overrides the default char limit text.
|
||||||
*/
|
*/
|
||||||
property string charLimitLabel: ""
|
property string charLimitLabel: ""
|
||||||
/*!
|
/*!
|
||||||
|
@ -157,12 +157,12 @@ Item {
|
||||||
*/
|
*/
|
||||||
property real maximumHeight: 44
|
property real maximumHeight: 44
|
||||||
/*!
|
/*!
|
||||||
\qmlproperty list StatusBaseInput::validators
|
\qmlproperty list<StatusValidator> StatusBaseInput::validators
|
||||||
This property sets the list of validators to be considered.
|
This property sets the list of validators to be considered.
|
||||||
*/
|
*/
|
||||||
property list<StatusValidator> validators
|
property list<StatusValidator> validators
|
||||||
/*!
|
/*!
|
||||||
\qmlproperty list StatusBaseInput::validators
|
\qmlproperty list<StatusAsyncValidator> StatusBaseInput::asyncValidators
|
||||||
This property sets the list of async validators to be considered.
|
This property sets the list of async validators to be considered.
|
||||||
*/
|
*/
|
||||||
property list<StatusAsyncValidator> asyncValidators
|
property list<StatusAsyncValidator> asyncValidators
|
||||||
|
@ -250,7 +250,7 @@ Item {
|
||||||
*/
|
*/
|
||||||
property var errors: ({})
|
property var errors: ({})
|
||||||
/*!
|
/*!
|
||||||
\qmlproperty var StatusBaseInput::errors
|
\qmlproperty var StatusBaseInput::asyncErrors
|
||||||
This property holds the validation async errors.
|
This property holds the validation async errors.
|
||||||
*/
|
*/
|
||||||
property var asyncErrors: ({})
|
property var asyncErrors: ({})
|
||||||
|
@ -343,8 +343,9 @@ Item {
|
||||||
root.validatedValue = root.text
|
root.validatedValue = root.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\qmlmethod
|
\qmlmethod updateAsyncValidity(validatorName, value, result)
|
||||||
This function updates the text input async validation.
|
This function updates the text input async validation.
|
||||||
*/
|
*/
|
||||||
function updateAsyncValidity(validatorName, value, result) {
|
function updateAsyncValidity(validatorName, value, result) {
|
||||||
|
@ -435,7 +436,7 @@ Item {
|
||||||
id: charLimitLabelItem
|
id: charLimitLabelItem
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
height: visible ? contentHeight : 0
|
height: visible ? contentHeight : 0
|
||||||
visible: root.charLimit > 0
|
visible: root.charLimit > 0 || !!root.charLimitLabel
|
||||||
text: root.charLimitLabel ? root.charLimitLabel : "%1 / %2".arg(Utils.encodeUtf8(statusBaseInput.text).length).arg(root.charLimit)
|
text: root.charLimitLabel ? root.charLimitLabel : "%1 / %2".arg(Utils.encodeUtf8(statusBaseInput.text).length).arg(root.charLimit)
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
color: statusBaseInput.enabled ? Theme.palette.baseColor1 : Theme.palette.directColor6
|
color: statusBaseInput.enabled ? Theme.palette.baseColor1 : Theme.palette.directColor6
|
||||||
|
|
|
@ -29,6 +29,8 @@ StatusButton {
|
||||||
Down
|
Down
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property bool isError
|
||||||
|
|
||||||
horizontalPadding: 16
|
horizontalPadding: 16
|
||||||
verticalPadding: 3
|
verticalPadding: 3
|
||||||
spacing: 4
|
spacing: 4
|
||||||
|
@ -37,6 +39,8 @@ StatusButton {
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
radius: 8
|
radius: 8
|
||||||
color: root.bgColor
|
color: root.bgColor
|
||||||
|
border.color: Theme.palette.dangerColor1
|
||||||
|
border.width: root.isError ? 1 : 0
|
||||||
}
|
}
|
||||||
opacity: !root.interactive || !root.enabled ? 0.5 : 1
|
opacity: !root.interactive || !root.enabled ? 0.5 : 1
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
|
@ -62,16 +66,11 @@ StatusButton {
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
StatusIcon {
|
StatusIcon {
|
||||||
icon: "tiny/chevron-right"
|
icon: "next"
|
||||||
visible: root.type === StatusPickerButton.PickerType.Next
|
visible: root.type === StatusPickerButton.PickerType.Next
|
||||||
color: !Qt.colorEqual(root.contentColor, Theme.palette.baseColor1) ? root.contentColor : Theme.palette.directColor1
|
color: !Qt.colorEqual(root.contentColor, Theme.palette.baseColor1) ? root.contentColor : Theme.palette.directColor1
|
||||||
width: root.icon.width
|
width: root.icon.width
|
||||||
height: root.icon.height
|
height: root.icon.height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HoverHandler {
|
|
||||||
enabled: root.enabled
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ StatusValidator {
|
||||||
|
|
||||||
errorMessage: {
|
errorMessage: {
|
||||||
minLength === 1 ?
|
minLength === 1 ?
|
||||||
"Please enter a value" :
|
qsTr("Please enter a value") :
|
||||||
`The value must be at least ${minLength} characters.`
|
qsTr("The value must be at least %n character(s).", "", minLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
validate: function (value) {
|
validate: function (value) {
|
||||||
|
@ -19,4 +19,3 @@ StatusValidator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
property string name: ""
|
property string name: ""
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import QtQuick 2.0
|
import QtQuick 2.15
|
||||||
import QtTest 1.0
|
import QtTest 1.15
|
||||||
|
|
||||||
|
import StatusQ 0.1
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
import StatusQ.Controls.Validators 0.1
|
import StatusQ.Controls.Validators 0.1
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ Item {
|
||||||
|
|
||||||
property StatusInput testControl: null
|
property StatusInput testControl: null
|
||||||
|
|
||||||
name: "RegexValidationTest"
|
name: "StatusInput-RegexValidationTest"
|
||||||
|
|
||||||
when: windowShown
|
when: windowShown
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@ Item {
|
||||||
|
|
||||||
property StatusInput testControl: null
|
property StatusInput testControl: null
|
||||||
|
|
||||||
name: "BindedValuesTest"
|
name: "StatusInput-BindedValuesTest"
|
||||||
when: windowShown
|
when: windowShown
|
||||||
|
|
||||||
property QtObject dataObject: QtObject {
|
property QtObject dataObject: QtObject {
|
||||||
|
@ -167,6 +168,35 @@ Item {
|
||||||
|
|
||||||
verify(qtOuput.qtOuput().length === 0, `No output expected. Found:\n"${qtOuput.qtOuput()}"\n`)
|
verify(qtOuput.qtOuput().length === 0, `No output expected. Found:\n"${qtOuput.qtOuput()}"\n`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// regression test for https://github.com/status-im/status-desktop/issues/16479
|
||||||
|
function test_paste_text() {
|
||||||
|
verify(!!testControl)
|
||||||
|
|
||||||
|
const textToPaste = "1234567890abcdef" // 16 chars
|
||||||
|
ClipboardUtils.setText(textToPaste)
|
||||||
|
|
||||||
|
// clear
|
||||||
|
testControl.input.edit.clear()
|
||||||
|
testControl.charLimit = 0
|
||||||
|
|
||||||
|
keySequence(StandardKey.Paste)
|
||||||
|
|
||||||
|
// verify we can paste the full text
|
||||||
|
compare(testControl.input.edit.length, textToPaste.length)
|
||||||
|
compare(testControl.input.edit.text, textToPaste)
|
||||||
|
compare(testControl.input.dirty, true)
|
||||||
|
|
||||||
|
// clear again, and set a lower limit
|
||||||
|
testControl.input.edit.clear()
|
||||||
|
testControl.charLimit = 10
|
||||||
|
|
||||||
|
keySequence(StandardKey.Paste)
|
||||||
|
|
||||||
|
// verify we can paste (some) text and it gets truncated to the charLimit
|
||||||
|
compare(testControl.input.edit.length, testControl.charLimit)
|
||||||
|
compare(testControl.input.edit.text, textToPaste.slice(0, testControl.charLimit))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MonitorQtOutput {
|
MonitorQtOutput {
|
||||||
|
|
|
@ -27,12 +27,16 @@ Item {
|
||||||
|
|
||||||
implicitHeight: layout.childrenRect.height
|
implicitHeight: layout.childrenRect.height
|
||||||
|
|
||||||
|
function validate() {
|
||||||
|
editor.isError = !hasSelectedImage
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: layout
|
id: layout
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
spacing: 19
|
spacing: 16
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: qsTr("Community banner")
|
text: qsTr("Community banner")
|
||||||
|
@ -67,6 +71,17 @@ Item {
|
||||||
additionalTextPixelSize: Theme.tertiaryTextFontSize
|
additionalTextPixelSize: Theme.tertiaryTextFontSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: -layout.spacing/2
|
||||||
|
visible: editor.isError
|
||||||
|
text: qsTr("Upload a community banner")
|
||||||
|
font.pixelSize: Theme.tertiaryTextFontSize
|
||||||
|
color: Theme.palette.dangerColor1
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@ ColumnLayout {
|
||||||
|
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
implicitHeight: childrenRect.height
|
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: root.title
|
text: root.title
|
||||||
|
@ -35,6 +33,9 @@ ColumnLayout {
|
||||||
bgColor: root.color
|
bgColor: root.color
|
||||||
contentColor: Theme.palette.white
|
contentColor: Theme.palette.white
|
||||||
text: root.color.toString()
|
text: root.color.toString()
|
||||||
|
font.weight: Font.Normal
|
||||||
|
icon.width: 24
|
||||||
|
icon.height: 24
|
||||||
onClicked: root.pick()
|
onClicked: root.pick()
|
||||||
|
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ Control {
|
||||||
readonly property alias isDescriptionDirty: descriptionTextInput.input.dirty
|
readonly property alias isDescriptionDirty: descriptionTextInput.input.dirty
|
||||||
readonly property alias isLogoSelected: logoPicker.hasSelectedImage
|
readonly property alias isLogoSelected: logoPicker.hasSelectedImage
|
||||||
readonly property alias isBannerSelected: bannerPicker.hasSelectedImage
|
readonly property alias isBannerSelected: bannerPicker.hasSelectedImage
|
||||||
|
readonly property alias areTagsSelected: tagsPicker.hasSelectedTags
|
||||||
|
|
||||||
property alias name: nameInput.text
|
property alias name: nameInput.text
|
||||||
property alias description: descriptionTextInput.text
|
property alias description: descriptionTextInput.text
|
||||||
|
@ -38,6 +39,21 @@ Control {
|
||||||
|
|
||||||
implicitWidth: 608
|
implicitWidth: 608
|
||||||
|
|
||||||
|
function validate(isDevBuild = false) {
|
||||||
|
if (!nameInput.validate(true))
|
||||||
|
nameInput.input.dirty = true
|
||||||
|
if (!descriptionTextInput.validate(true))
|
||||||
|
descriptionTextInput.input.dirty = true
|
||||||
|
if (!isDevBuild) {
|
||||||
|
logoPicker.validate()
|
||||||
|
bannerPicker.validate()
|
||||||
|
tagsPicker.validate()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nameInput.valid && descriptionTextInput.valid &&
|
||||||
|
(isDevBuild ? true : logoPicker.hasSelectedImage && bannerPicker.hasSelectedImage && tagsPicker.hasSelectedTags)
|
||||||
|
}
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
spacing: 16
|
spacing: 16
|
||||||
|
|
||||||
|
@ -45,24 +61,28 @@ Control {
|
||||||
id: nameInput
|
id: nameInput
|
||||||
input.edit.objectName: "communityNameInput"
|
input.edit.objectName: "communityNameInput"
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Component.onCompleted: nameInput.input.forceActiveFocus(Qt.MouseFocusReason)
|
input.tabNavItem: descriptionTextInput.input.edit
|
||||||
|
Component.onCompleted: nameInput.input.forceActiveFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
DescriptionInput {
|
DescriptionInput {
|
||||||
id: descriptionTextInput
|
id: descriptionTextInput
|
||||||
input.edit.objectName: "communityDescriptionInput"
|
input.edit.objectName: "communityDescriptionInput"
|
||||||
|
input.tabNavItem: nameInput.input.edit
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
LogoPicker {
|
LogoPicker {
|
||||||
id: logoPicker
|
id: logoPicker
|
||||||
objectName: "communityLogoPicker"
|
objectName: "communityLogoPicker"
|
||||||
|
onHasSelectedImageChanged: validate()
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
BannerPicker {
|
BannerPicker {
|
||||||
id: bannerPicker
|
id: bannerPicker
|
||||||
objectName: "communityBannerPicker"
|
objectName: "communityBannerPicker"
|
||||||
|
onHasSelectedImageChanged: validate()
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: -8 //Closer by design
|
Layout.topMargin: -8 //Closer by design
|
||||||
}
|
}
|
||||||
|
@ -109,12 +129,13 @@ Control {
|
||||||
width: 640
|
width: 640
|
||||||
replaceItem: TagsPanel {
|
replaceItem: TagsPanel {
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
tags = tagsPicker.tags;
|
tags = tagsPicker.tags
|
||||||
selectedTags = tagsPicker.selectedTags;
|
selectedTags = tagsPicker.selectedTags
|
||||||
}
|
}
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
tagsPicker.selectedTags = selectedTags;
|
tagsPicker.selectedTags = selectedTags
|
||||||
close();
|
tagsPicker.validate()
|
||||||
|
close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onClosed: destroy()
|
onClosed: destroy()
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
import StatusQ.Controls.Validators 0.1
|
import StatusQ.Controls.Validators 0.1
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,10 @@ Item {
|
||||||
|
|
||||||
implicitHeight: layout.childrenRect.height
|
implicitHeight: layout.childrenRect.height
|
||||||
|
|
||||||
|
function validate() {
|
||||||
|
editor.isError = !hasSelectedImage
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: layout
|
id: layout
|
||||||
|
|
||||||
|
@ -37,7 +41,6 @@ Item {
|
||||||
id: label
|
id: label
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("Community logo")
|
text: qsTr("Community logo")
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.directColor1
|
color: Theme.palette.directColor1
|
||||||
horizontalAlignment: Qt.AlignLeft
|
horizontalAlignment: Qt.AlignLeft
|
||||||
}
|
}
|
||||||
|
@ -59,6 +62,16 @@ Item {
|
||||||
visible: !editor.userSelectedImage && !root.imageData
|
visible: !editor.userSelectedImage && !root.imageData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: editor.isError
|
||||||
|
text: qsTr("Upload a community logo")
|
||||||
|
font.pixelSize: Theme.tertiaryTextFontSize
|
||||||
|
color: Theme.palette.dangerColor1
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
import StatusQ.Controls.Validators 0.1
|
import StatusQ.Controls.Validators 0.1
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ ColumnLayout {
|
||||||
StatusCheckBox {
|
StatusCheckBox {
|
||||||
id: archiveSupportToggle
|
id: archiveSupportToggle
|
||||||
width: (parent.width-12)
|
width: (parent.width-12)
|
||||||
checked: false
|
|
||||||
leftSide: false
|
leftSide: false
|
||||||
padding: 0
|
padding: 0
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
@ -39,11 +38,7 @@ ColumnLayout {
|
||||||
|
|
||||||
StatusToolTip {
|
StatusToolTip {
|
||||||
text: qsTr('For this Community Setting to work, you also need to activate "Archive Protocol Enabled" in Advanced Settings')
|
text: qsTr('For this Community Setting to work, you also need to activate "Archive Protocol Enabled" in Advanced Settings')
|
||||||
visible: hoverHandler.hovered
|
visible: parent.hovered
|
||||||
}
|
|
||||||
HoverHandler {
|
|
||||||
id: hoverHandler
|
|
||||||
enabled: true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +60,7 @@ ColumnLayout {
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Layout.preferredWidth: parent.width
|
Layout.preferredWidth: parent.width
|
||||||
Layout.topMargin: 22
|
Layout.topMargin: 22
|
||||||
spacing: 0
|
spacing: 4
|
||||||
StatusCheckBox {
|
StatusCheckBox {
|
||||||
id: requestToJoinToggle
|
id: requestToJoinToggle
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -78,9 +73,8 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
id: warningText
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.rightMargin: 12
|
Layout.rightMargin: 64
|
||||||
visible: requestToJoinToggle.checked
|
visible: requestToJoinToggle.checked
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
text: qsTr("Warning: Only token gated communities (or token gated channels inside non-token gated community) are encrypted")
|
text: qsTr("Warning: Only token gated communities (or token gated channels inside non-token gated community) are encrypted")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
import QtQuick.Layouts 1.14
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
|
@ -15,14 +15,19 @@ ColumnLayout {
|
||||||
property string tags
|
property string tags
|
||||||
property string selectedTags
|
property string selectedTags
|
||||||
|
|
||||||
|
readonly property bool hasSelectedTags: localAppSettings.testEnvironment || selectedTags !== ""
|
||||||
|
|
||||||
signal pick()
|
signal pick()
|
||||||
|
|
||||||
implicitHeight: childrenRect.height
|
spacing: 8
|
||||||
spacing: 14
|
|
||||||
|
|
||||||
onSelectedTagsChanged: d.handleSelectedTags()
|
onSelectedTagsChanged: d.handleSelectedTags()
|
||||||
Component.onCompleted: d.handleSelectedTags()
|
Component.onCompleted: d.handleSelectedTags()
|
||||||
|
|
||||||
|
function validate() {
|
||||||
|
pickerButton.isError = !hasSelectedTags
|
||||||
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
|
|
||||||
|
@ -33,7 +38,7 @@ ColumnLayout {
|
||||||
|
|
||||||
d.tagsModel.clear();
|
d.tagsModel.clear();
|
||||||
for (const key of Object.keys(obj)) {
|
for (const key of Object.keys(obj)) {
|
||||||
if (array.indexOf(key) != -1) {
|
if (array.indexOf(key) !== -1) {
|
||||||
d.tagsModel.append({ name: key, emoji: obj[key], selected: false });
|
d.tagsModel.append({ name: key, emoji: obj[key], selected: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,15 +47,19 @@ ColumnLayout {
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: qsTr("Tags")
|
text: qsTr("Tags")
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.directColor1
|
color: Theme.palette.directColor1
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusPickerButton {
|
StatusPickerButton {
|
||||||
|
id: pickerButton
|
||||||
bgColor: d.tagsModel.count === 0 ? Theme.palette.baseColor2 : "transparent"
|
bgColor: d.tagsModel.count === 0 ? Theme.palette.baseColor2 : "transparent"
|
||||||
text: d.tagsModel.count === 0 ? qsTr("Choose tags describing the community") : ""
|
text: d.tagsModel.count === 0 ? qsTr("Choose tags describing the community") : ""
|
||||||
onClicked: root.pick()
|
onClicked: root.pick()
|
||||||
|
font.weight: Font.Normal
|
||||||
|
icon.width: 24
|
||||||
|
icon.height: 24
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 44
|
||||||
|
|
||||||
StatusCommunityTags {
|
StatusCommunityTags {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
@ -60,4 +69,14 @@ ColumnLayout {
|
||||||
contentWidth: width
|
contentWidth: width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: pickerButton.isError
|
||||||
|
text: qsTr("Add at least 1 tag")
|
||||||
|
font.pixelSize: Theme.tertiaryTextFontSize
|
||||||
|
color: Theme.palette.dangerColor1
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
import QtQuick 2.13
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.13
|
import QtQuick.Controls 2.15
|
||||||
import QtGraphicalEffects 1.13
|
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Components 0.1
|
import StatusQ.Components 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Controls 0.1 as StatusQControls
|
import StatusQ.Controls 0.1 as StatusQControls
|
||||||
|
|
||||||
import shared.panels 1.0
|
|
||||||
import shared.status 1.0
|
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -61,7 +57,6 @@ Rectangle {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 48
|
anchors.topMargin: 48
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.directColor1
|
color: Theme.palette.directColor1
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.12
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
@ -69,7 +69,7 @@ StatusScrollView {
|
||||||
// TODO: editingFinished() signal instead of this crutch
|
// TODO: editingFinished() signal instead of this crutch
|
||||||
property bool locked: false
|
property bool locked: false
|
||||||
|
|
||||||
implicitWidth: 256
|
Layout.preferredWidth: 256
|
||||||
validators: [
|
validators: [
|
||||||
StatusRegularExpressionValidator {
|
StatusRegularExpressionValidator {
|
||||||
regularExpression: /^#(?:[0-9a-fA-F]{3}){1,2}$/
|
regularExpression: /^#(?:[0-9a-fA-F]{3}){1,2}$/
|
||||||
|
@ -91,22 +91,18 @@ StatusScrollView {
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: qsTr("Preview")
|
text: qsTr("Preview")
|
||||||
font.pixelSize: 15
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
implicitHeight: 48
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 44
|
||||||
radius: 10
|
radius: 10
|
||||||
color: root.color
|
color: root.color
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
id: preview
|
anchors.centerIn: parent
|
||||||
x: 16
|
|
||||||
y: 16
|
|
||||||
text: qsTr("White text should be legible on top of this colour")
|
text: qsTr("White text should be legible on top of this colour")
|
||||||
color: Theme.palette.white
|
color: Theme.palette.white
|
||||||
font.pixelSize: 15
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +110,6 @@ StatusScrollView {
|
||||||
id: colorSelectionGrid
|
id: colorSelectionGrid
|
||||||
titleText: qsTr("Standard colours")
|
titleText: qsTr("Standard colours")
|
||||||
title.color: Theme.palette.directColor1
|
title.color: Theme.palette.directColor1
|
||||||
title.font.pixelSize: 15
|
|
||||||
columns: 8
|
columns: 8
|
||||||
model: Theme.palette.communityColorsArray
|
model: Theme.palette.communityColorsArray
|
||||||
selectedColorIndex: -1
|
selectedColorIndex: -1
|
||||||
|
|
|
@ -173,7 +173,9 @@ StackLayout {
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: root
|
target: root
|
||||||
onCommunityIdChanged: reset()
|
function onCommunityIdChanged() {
|
||||||
|
reset()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.14
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
@ -23,6 +23,7 @@ StatusScrollView {
|
||||||
property var rightButtons: StatusButton {
|
property var rightButtons: StatusButton {
|
||||||
objectName: "confirmCommunityTagsButton"
|
objectName: "confirmCommunityTagsButton"
|
||||||
text: qsTr("Confirm Community Tags")
|
text: qsTr("Confirm Community Tags")
|
||||||
|
enabled: d.countSelectedTags > 0
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var selectedTags = [];
|
var selectedTags = [];
|
||||||
for (let i = 0; i < d.tagsModel.count; ++i) {
|
for (let i = 0; i < d.tagsModel.count; ++i) {
|
||||||
|
@ -39,12 +40,12 @@ StatusScrollView {
|
||||||
function updateSelectedTags() {
|
function updateSelectedTags() {
|
||||||
var array = selectedTags.length ? JSON.parse(selectedTags) : [];
|
var array = selectedTags.length ? JSON.parse(selectedTags) : [];
|
||||||
|
|
||||||
d.cntSelectedTags = 0;
|
d.countSelectedTags = 0;
|
||||||
for (let i = 0; i < d.tagsModel.count; ++i) {
|
for (let i = 0; i < d.tagsModel.count; ++i) {
|
||||||
let item = d.tagsModel.get(i);
|
let item = d.tagsModel.get(i);
|
||||||
if (array.indexOf(item.name) != -1) {
|
if (array.indexOf(item.name) !== -1) {
|
||||||
item.selected = true;
|
item.selected = true;
|
||||||
d.cntSelectedTags++;
|
d.countSelectedTags++;
|
||||||
} else {
|
} else {
|
||||||
item.selected = false;
|
item.selected = false;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +56,7 @@ StatusScrollView {
|
||||||
onTagsChanged: {
|
onTagsChanged: {
|
||||||
var obj = JSON.parse(tags);
|
var obj = JSON.parse(tags);
|
||||||
|
|
||||||
d.cntSelectedTags = 0;
|
d.countSelectedTags = 0;
|
||||||
d.tagsModel.clear();
|
d.tagsModel.clear();
|
||||||
for (const key of Object.keys(obj)) {
|
for (const key of Object.keys(obj)) {
|
||||||
d.tagsModel.append({ name: key, emoji: obj[key], selected: false });
|
d.tagsModel.append({ name: key, emoji: obj[key], selected: false });
|
||||||
|
@ -70,7 +71,7 @@ StatusScrollView {
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
|
|
||||||
property int cntSelectedTags: 0
|
property int countSelectedTags: 0
|
||||||
property ListModel tagsModel: ListModel {}
|
property ListModel tagsModel: ListModel {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +84,6 @@ StatusScrollView {
|
||||||
id: tagsFilter
|
id: tagsFilter
|
||||||
label: qsTr("Select tags that will fit your Community")
|
label: qsTr("Select tags that will fit your Community")
|
||||||
labelPadding: Style.current.bigPadding
|
labelPadding: Style.current.bigPadding
|
||||||
font.pixelSize: 15
|
|
||||||
input.asset.name: "search"
|
input.asset.name: "search"
|
||||||
placeholderText: qsTr("Search tags")
|
placeholderText: qsTr("Search tags")
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -96,9 +96,9 @@ StatusScrollView {
|
||||||
StatusCommunityTags {
|
StatusCommunityTags {
|
||||||
filterString: tagsFilter.text
|
filterString: tagsFilter.text
|
||||||
model: d.tagsModel
|
model: d.tagsModel
|
||||||
enabled: d.cntSelectedTags < maxSelectedTags
|
enabled: d.countSelectedTags < maxSelectedTags
|
||||||
onClicked: {
|
onClicked: {
|
||||||
d.cntSelectedTags++;
|
d.countSelectedTags++;
|
||||||
item.selected = true;
|
item.selected = true;
|
||||||
}
|
}
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -112,12 +112,11 @@ StatusScrollView {
|
||||||
RowLayout {
|
RowLayout {
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: qsTr("Selected tags")
|
text: qsTr("Selected tags")
|
||||||
font.pixelSize: 15
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: qsTr("%1 / %2").arg(d.cntSelectedTags).arg(maxSelectedTags)
|
text: qsTr("%1 / %2").arg(d.countSelectedTags).arg(maxSelectedTags)
|
||||||
color: Theme.palette.baseColor1
|
color: Theme.palette.baseColor1
|
||||||
font.pixelSize: 13
|
font.pixelSize: 13
|
||||||
}
|
}
|
||||||
|
@ -127,10 +126,21 @@ StatusScrollView {
|
||||||
model: d.tagsModel
|
model: d.tagsModel
|
||||||
mode: StatusCommunityTags.ShowSelectedOnly
|
mode: StatusCommunityTags.ShowSelectedOnly
|
||||||
onClicked: {
|
onClicked: {
|
||||||
d.cntSelectedTags--;
|
d.countSelectedTags--;
|
||||||
item.selected = false;
|
item.selected = false;
|
||||||
}
|
}
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.bottomMargin: Style.current.padding
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.bottomMargin: Style.current.padding
|
||||||
|
text: qsTr("No tags selected yet")
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
visible: d.countSelectedTags === 0
|
||||||
|
font.pixelSize: 13
|
||||||
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.14
|
import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.14
|
import QtQuick.Layouts 1.15
|
||||||
import QtQuick.Dialogs 1.3
|
import QtQuick.Dialogs 1.3
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
@ -30,6 +30,8 @@ StatusStackModal {
|
||||||
qsTr("Create New Community")
|
qsTr("Create New Community")
|
||||||
width: 640
|
width: 640
|
||||||
|
|
||||||
|
closePolicy: Popup.NoAutoClose // explicit [x] click needed, or via the `close()` method
|
||||||
|
|
||||||
nextButton: StatusButton {
|
nextButton: StatusButton {
|
||||||
objectName: "createCommunityNextBtn"
|
objectName: "createCommunityNextBtn"
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
|
@ -55,8 +57,6 @@ StatusStackModal {
|
||||||
if (typeof (nextAction) == "function") {
|
if (typeof (nextAction) == "function") {
|
||||||
return nextAction()
|
return nextAction()
|
||||||
}
|
}
|
||||||
if (!root.isDiscordImport)
|
|
||||||
d.createCommunity()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,7 +363,12 @@ StatusStackModal {
|
||||||
StatusScrollView {
|
StatusScrollView {
|
||||||
id: generalView
|
id: generalView
|
||||||
contentWidth: availableWidth
|
contentWidth: availableWidth
|
||||||
readonly property bool canGoNext: generalViewLayout.isNameValid && generalViewLayout.isDescriptionValid && (root.isDevBuild || (generalViewLayout.isLogoSelected && generalViewLayout.isBannerSelected))
|
|
||||||
|
readonly property var nextAction: () => {
|
||||||
|
if (generalViewLayout.validate(root.isDevBuild)) {
|
||||||
|
root.currentIndex++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
padding: 0
|
padding: 0
|
||||||
clip: false
|
clip: false
|
||||||
|
@ -389,8 +394,20 @@ StatusStackModal {
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: introOutroMessageView
|
id: introOutroMessageView
|
||||||
spacing: 11
|
spacing: 16
|
||||||
readonly property bool canGoNext: introMessageInput.valid && outroMessageInput.valid
|
|
||||||
|
readonly property var nextAction: () => {
|
||||||
|
if (!introMessageInput.validate(true))
|
||||||
|
introMessageInput.input.dirty = true
|
||||||
|
if (!outroMessageInput.validate(true))
|
||||||
|
outroMessageInput.input.dirty = true
|
||||||
|
if (introMessageInput.valid && outroMessageInput.valid) {
|
||||||
|
if (root.isDiscordImport)
|
||||||
|
root.currentIndex++
|
||||||
|
else
|
||||||
|
d.createCommunity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IntroMessageInput {
|
IntroMessageInput {
|
||||||
id: introMessageInput
|
id: introMessageInput
|
||||||
|
|
|
@ -35,6 +35,7 @@ Item {
|
||||||
|
|
||||||
property bool userSelectedImage: false
|
property bool userSelectedImage: false
|
||||||
readonly property bool nothingToShow: state === d.noImageState
|
readonly property bool nothingToShow: state === d.noImageState
|
||||||
|
property bool isError
|
||||||
|
|
||||||
readonly property alias cropWorkflow : imageCropWorkflow
|
readonly property alias cropWorkflow : imageCropWorkflow
|
||||||
|
|
||||||
|
@ -119,6 +120,9 @@ Item {
|
||||||
|
|
||||||
icon.name: "edit_pencil"
|
icon.name: "edit_pencil"
|
||||||
|
|
||||||
|
width: 40
|
||||||
|
height: 40
|
||||||
|
|
||||||
readonly property real rotationRadius: root.roundedImage ? parent.width/2 : imageCropEditor.radius
|
readonly property real rotationRadius: root.roundedImage ? parent.width/2 : imageCropEditor.radius
|
||||||
transform: [
|
transform: [
|
||||||
Translate {
|
Translate {
|
||||||
|
@ -154,10 +158,16 @@ Item {
|
||||||
radius: roundedImage ? Math.max(width, height)/2 : croppedPreview.radius
|
radius: roundedImage ? Math.max(width, height)/2 : croppedPreview.radius
|
||||||
color: Style.current.inputBackground
|
color: Style.current.inputBackground
|
||||||
|
|
||||||
|
border.color: Theme.palette.dangerColor1
|
||||||
|
border.width: root.isError ? 1 : 0
|
||||||
|
|
||||||
StatusRoundButton {
|
StatusRoundButton {
|
||||||
id: addButton
|
id: addButton
|
||||||
|
|
||||||
icon.name: "add"
|
icon.name: "add"
|
||||||
|
width: 40
|
||||||
|
height: 40
|
||||||
|
|
||||||
readonly property real rotationRadius: root.roundedImage ? parent.width/2 : imageCropEditor.radius
|
readonly property real rotationRadius: root.roundedImage ? parent.width/2 : imageCropEditor.radius
|
||||||
|
|
||||||
transform: [
|
transform: [
|
||||||
|
|
|
@ -10,7 +10,7 @@ import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
/brief Image icon and ulopad text hints for banner and logo
|
/brief Image icon and upload text hints for banner and logo
|
||||||
*/
|
*/
|
||||||
Control {
|
Control {
|
||||||
id: root
|
id: root
|
||||||
|
|
Loading…
Reference in New Issue