desktop(community-settings): add overview and members settings
this is first iteration for: #4938
This commit is contained in:
parent
4b22a709ba
commit
2850ee75ee
|
@ -1,202 +1,50 @@
|
||||||
import QtQuick 2.13
|
import QtQuick 2.14
|
||||||
import QtQuick.Controls 2.13
|
import QtQuick.Controls 2.14
|
||||||
import Qt.labs.settings 1.0
|
import QtQuick.Layouts 1.14
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
import shared 1.0
|
|
||||||
import shared.panels 1.0
|
|
||||||
import shared.popups 1.0
|
|
||||||
import shared.status 1.0
|
|
||||||
import shared.views.chat 1.0
|
|
||||||
|
|
||||||
import StatusQ.Layout 0.1
|
|
||||||
import StatusQ.Popups 0.1
|
|
||||||
|
|
||||||
import "views"
|
import "views"
|
||||||
import "panels"
|
|
||||||
import "panels/communities"
|
|
||||||
import "popups"
|
|
||||||
import "helpers"
|
|
||||||
import "controls"
|
|
||||||
import "stores"
|
import "stores"
|
||||||
|
|
||||||
StatusAppThreePanelLayout {
|
StackLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var contactsStore
|
property var contactsStore
|
||||||
property bool hasAddedContacts: root.contactsStore.myContactsModel.count > 0
|
|
||||||
|
|
||||||
// Not Refactored
|
|
||||||
property var messageStore
|
|
||||||
|
|
||||||
property RootStore rootStore: RootStore {
|
property RootStore rootStore: RootStore {
|
||||||
contactsStore: root.contactsStore
|
contactsStore: root.contactsStore
|
||||||
}
|
}
|
||||||
|
|
||||||
property Component pinnedMessagesListPopupComponent
|
property alias chatView: chatView
|
||||||
property var emojiPopup
|
|
||||||
property bool stickersLoaded: false
|
|
||||||
signal profileButtonClicked()
|
|
||||||
signal openAppSearch()
|
|
||||||
|
|
||||||
Connections {
|
clip: true
|
||||||
target: root.rootStore.stickersStore.stickersModule
|
|
||||||
onStickerPacksLoaded: {
|
|
||||||
root.stickersLoaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
ChatView {
|
||||||
target: root.rootStore.chatCommunitySectionModule
|
id: chatView
|
||||||
onActiveItemChanged: {
|
|
||||||
root.rootStore.openCreateChat = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// property var onActivated: function () {
|
|
||||||
// root.rootStore.chatsModelInst.channelView.restorePreviousActiveChannel();
|
|
||||||
// chatColumn.onActivated();
|
|
||||||
// }
|
|
||||||
|
|
||||||
leftPanel: Loader {
|
|
||||||
id: contactColumnLoader
|
|
||||||
sourceComponent: root.rootStore.chatCommunitySectionModule.isCommunity()?
|
|
||||||
communtiyColumnComponent :
|
|
||||||
contactsColumnComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
centerPanel: ChatColumnView {
|
|
||||||
id: chatColumn
|
|
||||||
parentModule: root.rootStore.chatCommunitySectionModule
|
|
||||||
rootStore: root.rootStore
|
|
||||||
contactsStore: root.contactsStore
|
contactsStore: root.contactsStore
|
||||||
chatSectionModule: root.rootStore.chatCommunitySectionModule
|
|
||||||
pinnedMessagesPopupComponent: root.pinnedMessagesListPopupComponent
|
|
||||||
stickersLoaded: root.stickersLoaded
|
|
||||||
emojiPopup: root.emojiPopup
|
|
||||||
//chatGroupsListViewCount: contactColumnLoader.item.chatGroupsListViewCount
|
|
||||||
onOpenStickerPackPopup: {
|
|
||||||
Global.openPopup(statusStickerPackClickPopup, {packId: stickerPackId} )
|
|
||||||
}
|
|
||||||
onOpenAppSearch: {
|
|
||||||
root.openAppSearch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showRightPanel: {
|
|
||||||
if (root.rootStore.openCreateChat ||
|
|
||||||
!localAccountSensitiveSettings.showOnlineUsers ||
|
|
||||||
!localAccountSensitiveSettings.expandUsersList) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
let chatContentModule = root.rootStore.currentChatContentModule()
|
|
||||||
if (!chatContentModule
|
|
||||||
|| chatContentModule.chatDetails.type === Constants.chatType.publicChat)
|
|
||||||
{
|
|
||||||
// New communities have no chats, so no chatContentModule or it is a public chat
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Check if user list is available as an option for particular chat content module
|
|
||||||
return chatContentModule.chatDetails.isUsersListAvailable
|
|
||||||
}
|
|
||||||
|
|
||||||
rightPanel: userListComponent
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: userListComponent
|
|
||||||
UserListPanel {
|
|
||||||
rootStore: root.rootStore
|
rootStore: root.rootStore
|
||||||
label: localAccountSensitiveSettings.communitiesEnabled &&
|
|
||||||
root.rootStore.chatCommunitySectionModule.isCommunity() ?
|
onCommunityInfoButtonClicked: root.currentIndex = 1
|
||||||
//% "Members"
|
onCommunityManageButtonClicked: root.currentIndex = 1
|
||||||
qsTrId("members-label") :
|
|
||||||
qsTr("Last seen")
|
|
||||||
messageContextMenu: quickActionMessageOptionsMenu
|
|
||||||
usersModule: {
|
|
||||||
let chatContentModule = root.rootStore.currentChatContentModule()
|
|
||||||
if (!chatContentModule || !chatContentModule.usersModule) {
|
|
||||||
// New communities have no chats, so no chatContentModule
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
return chatContentModule.usersModule
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Loader {
|
||||||
id: contactsColumnComponent
|
active: root.rootStore.chatCommunitySectionModule.isCommunity()
|
||||||
ContactsColumnView {
|
|
||||||
chatSectionModule: root.rootStore.chatCommunitySectionModule
|
|
||||||
store: root.rootStore
|
|
||||||
contactsStore: root.contactsStore
|
|
||||||
emojiPopup: root.emojiPopup
|
|
||||||
onOpenProfileClicked: {
|
|
||||||
root.profileButtonClicked();
|
|
||||||
}
|
|
||||||
|
|
||||||
onOpenAppSearch: {
|
sourceComponent: CommunitySettingsView {
|
||||||
root.openAppSearch()
|
rootStore: root.rootStore
|
||||||
}
|
chatCommunitySectionModule: root.rootStore.chatCommunitySectionModule
|
||||||
}
|
community: root.rootStore.mainModuleInst ? root.rootStore.mainModuleInst.activeSection
|
||||||
}
|
|| {} : {}
|
||||||
|
|
||||||
Component {
|
onBackToCommunityClicked: root.currentIndex = 0
|
||||||
id: communtiyColumnComponent
|
|
||||||
CommunityColumnView {
|
|
||||||
communitySectionModule: root.rootStore.chatCommunitySectionModule
|
|
||||||
store: root.rootStore
|
|
||||||
emojiPopup: root.emojiPopup
|
|
||||||
hasAddedContacts: root.hasAddedContacts
|
|
||||||
pinnedMessagesPopupComponent: root.pinnedMessagesListPopupComponent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
// TODO: remove me when migration to new settings is done
|
||||||
id: groupInfoPopupComponent
|
onOpenLegacyPopupClicked: Global.openPopup(communityProfilePopup, {
|
||||||
GroupInfoPopup {
|
"store": root.rootStore,
|
||||||
chatSectionModule: root.rootStore.chatCommunitySectionModule
|
"community": community,
|
||||||
store: root.rootStore
|
"communitySectionModule": chatCommunitySectionModule
|
||||||
pinnedMessagesPopupComponent: root.pinnedMessagesListPopupComponent
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: statusStickerPackClickPopup
|
|
||||||
StatusStickerPackClickPopup{
|
|
||||||
store: root.rootStore
|
|
||||||
onClosed: {
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfirmationDialog {
|
|
||||||
id: removeContactConfirmationDialog
|
|
||||||
// % "Remove contact"
|
|
||||||
header.title: qsTrId("remove-contact")
|
|
||||||
//% "Are you sure you want to remove this contact?"
|
|
||||||
confirmationText: qsTrId("are-you-sure-you-want-to-remove-this-contact-")
|
|
||||||
onConfirmButtonClicked: {
|
|
||||||
let pk = chatColumn.contactToRemove
|
|
||||||
if (Utils.getContactDetailsAsJson(pk).isContact) {
|
|
||||||
root.contactsStore.removeContact(pk)
|
|
||||||
}
|
|
||||||
removeContactConfirmationDialog.parentPopup.close();
|
|
||||||
removeContactConfirmationDialog.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageContextMenuView {
|
|
||||||
id: quickActionMessageOptionsMenu
|
|
||||||
store: root.rootStore
|
|
||||||
|
|
||||||
onOpenProfileClicked: {
|
|
||||||
Global.openProfilePopup(publicKey)
|
|
||||||
}
|
|
||||||
onCreateOneToOneChat: {
|
|
||||||
Global.changeAppSectionBySectionType(Constants.appSection.chat)
|
|
||||||
root.rootStore.chatCommunitySectionModule.createOneToOneChat(communityId, chatId, ensName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
|
||||||
|
import QtGraphicalEffects 1.13
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
// required
|
||||||
|
property string title
|
||||||
|
property Component content
|
||||||
|
|
||||||
|
// optional
|
||||||
|
property string previousPage
|
||||||
|
property bool dirty: false
|
||||||
|
|
||||||
|
readonly property Item contentItem: contentLoader.item
|
||||||
|
|
||||||
|
signal previousPageClicked
|
||||||
|
signal saveChangesClicked
|
||||||
|
signal resetChangesClicked
|
||||||
|
|
||||||
|
function reloadContent() {
|
||||||
|
contentLoader.active = false
|
||||||
|
contentLoader.active = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function notifyDirty() {
|
||||||
|
toastAnimation.running = true
|
||||||
|
saveChangesButton.forceActiveFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitWidth: layout.implicitWidth
|
||||||
|
implicitHeight: layout.implicitHeight
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
Item {
|
||||||
|
implicitHeight: 32
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
visible: root.previousPage
|
||||||
|
text: "<- " + root.previousPage
|
||||||
|
color: Theme.palette.primaryColor1
|
||||||
|
font.pixelSize: 15
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.previousPageClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.leftMargin: 32
|
||||||
|
|
||||||
|
text: root.title
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
font.pixelSize: 26
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: contentLoader
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
sourceComponent: root.content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: toastMessage
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
bottomMargin: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
height: toastContent.height + 16
|
||||||
|
width: toastContent.width + 16
|
||||||
|
|
||||||
|
opacity: root.dirty ? 1 : 0
|
||||||
|
color: Theme.palette.statusToastMessage.backgroundColor
|
||||||
|
radius: 8
|
||||||
|
border.color: Theme.palette.dangerColor2
|
||||||
|
border.width: 2
|
||||||
|
layer.enabled: true
|
||||||
|
layer.effect: DropShadow {
|
||||||
|
verticalOffset: 3
|
||||||
|
radius: 8
|
||||||
|
samples: 15
|
||||||
|
fast: true
|
||||||
|
cached: true
|
||||||
|
color: Theme.palette.dangerColor2
|
||||||
|
spread: 0.1
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberAnimation on border.width {
|
||||||
|
id: toastAnimation
|
||||||
|
from: 0
|
||||||
|
to: 4
|
||||||
|
loops: 2
|
||||||
|
duration: 600
|
||||||
|
|
||||||
|
onFinished: toastMessage.border.width = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: toastContent
|
||||||
|
|
||||||
|
x: 8
|
||||||
|
y: 8
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
text: qsTr("Changes detected!")
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
text: qsTr("Cancel")
|
||||||
|
type: StatusBaseButton.Type.Danger
|
||||||
|
onClicked: root.resetChangesClicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
id: saveChangesButton
|
||||||
|
|
||||||
|
text: qsTr("Save changes")
|
||||||
|
onClicked: root.saveChangesClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,251 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
|
import QtGraphicalEffects 1.13
|
||||||
|
|
||||||
|
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.Layout 0.1
|
||||||
|
import StatusQ.Components 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Controls.Validators 0.1
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property alias name: nameInput.text
|
||||||
|
property alias description: descriptionTextInput.text
|
||||||
|
property alias color: colorDialog.color
|
||||||
|
property alias image: addImageButton.selectedImage
|
||||||
|
readonly property alias imageAx: imageCropperModal.aX
|
||||||
|
readonly property alias imageAy: imageCropperModal.aY
|
||||||
|
readonly property alias imageBx: imageCropperModal.bX
|
||||||
|
readonly property alias imageBy: imageCropperModal.bY
|
||||||
|
|
||||||
|
contentWidth: layout.width
|
||||||
|
contentHeight: layout.height
|
||||||
|
clip: true
|
||||||
|
interactive: contentHeight > height
|
||||||
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
width: root.width
|
||||||
|
spacing: 12
|
||||||
|
|
||||||
|
StatusInput {
|
||||||
|
id: nameInput
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
label: qsTr("Community name")
|
||||||
|
charLimit: 30
|
||||||
|
input.placeholderText: qsTr("A catchy name")
|
||||||
|
validators: [
|
||||||
|
StatusMinLengthValidator {
|
||||||
|
minLength: 1
|
||||||
|
errorMessage: Utils.getErrorMessage(nameInput.errors,
|
||||||
|
qsTr("community name"))
|
||||||
|
}
|
||||||
|
]
|
||||||
|
validationMode: StatusInput.ValidationMode.Always
|
||||||
|
|
||||||
|
Component.onCompleted: nameInput.input.forceActiveFocus(Qt.MouseFocusReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusInput {
|
||||||
|
id: descriptionTextInput
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
label: qsTr("Description")
|
||||||
|
charLimit: 140
|
||||||
|
|
||||||
|
input.placeholderText: qsTr("What your community is about")
|
||||||
|
input.multiline: true
|
||||||
|
input.implicitHeight: 88
|
||||||
|
|
||||||
|
validators: [
|
||||||
|
StatusMinLengthValidator {
|
||||||
|
minLength: 1
|
||||||
|
errorMessage: Utils.getErrorMessage(
|
||||||
|
descriptionTextInput.errors,
|
||||||
|
qsTr("community description"))
|
||||||
|
}
|
||||||
|
]
|
||||||
|
validationMode: StatusInput.ValidationMode.Always
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
//% "Thumbnail image"
|
||||||
|
text: qsTrId("thumbnail-image")
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
implicitHeight: addImageButton.height + 32
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: addImageButton
|
||||||
|
|
||||||
|
property string selectedImage: ""
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: imagePreview.visible ? "transparent" : Style.current.inputBackground
|
||||||
|
width: 128
|
||||||
|
height: width
|
||||||
|
radius: width / 2
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
text: qsTrId("Community colour")
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusPickerButton {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
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() : qsTr("Pick a color")
|
||||||
|
|
||||||
|
onClicked: colorDialog.open()
|
||||||
|
onTextChanged: {
|
||||||
|
if (colorDialog.colorSelected) {
|
||||||
|
validationError = Utils.validateAndReturnError(
|
||||||
|
text,
|
||||||
|
Utils.Validate.NoEmpty | Utils.Validate.TextHexColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorDialog {
|
||||||
|
id: colorDialog
|
||||||
|
property bool colorSelected: true
|
||||||
|
color: Theme.palette.primaryColor1
|
||||||
|
onAccepted: colorSelected = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Components 0.1
|
||||||
|
import StatusQ.Popups 0.1
|
||||||
|
|
||||||
|
import utils 1.0
|
||||||
|
import shared.controls.chat 1.0
|
||||||
|
|
||||||
|
import "../../layouts"
|
||||||
|
|
||||||
|
SettingsPageLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var membersModel
|
||||||
|
|
||||||
|
property bool editable: true
|
||||||
|
property int pendingRequests
|
||||||
|
|
||||||
|
signal membershipRequestsClicked()
|
||||||
|
signal userProfileClicked(string id)
|
||||||
|
signal kickUserClicked(string id)
|
||||||
|
signal banUserClicked(string id)
|
||||||
|
|
||||||
|
title: qsTr("Members")
|
||||||
|
|
||||||
|
content: ColumnLayout {
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
StatusInput {
|
||||||
|
id: memberSearch
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
input.placeholderText: qsTr("Member name")
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusContactRequestsIndicatorListItem {
|
||||||
|
id: memberRequestsButton
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
visible: root.editable && root.pendingRequests > 0
|
||||||
|
//% "Membership requests"
|
||||||
|
title: qsTrId("membership-requests")
|
||||||
|
requestsCount: root.pendingRequests
|
||||||
|
sensor.onClicked: root.membershipRequestsClicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
implicitHeight: 1
|
||||||
|
visible: memberRequestsButton.visible
|
||||||
|
color: Theme.palette.statusPopupMenu.separatorColor
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
visible: memberList.count === 0
|
||||||
|
//% "Community members will appear here"
|
||||||
|
text: qsTrId("community-members-will-appear-here")
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
visible: !!memberSearch.input.text && memberList.height == 0
|
||||||
|
//% "No contacts found"
|
||||||
|
text: qsTrId("no-contacts-found")
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: memberList
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
model: root.membersModel
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
// TODO: use StatusMemberListItem (it does not behave correctly right now)
|
||||||
|
delegate: StatusListItem {
|
||||||
|
id: memberItem
|
||||||
|
|
||||||
|
readonly property bool itsMe: model.id.toLowerCase() === userProfile.pubKey.toLowerCase()
|
||||||
|
readonly property bool isOnline: model.onlineStatus === Constants.userStatus.online
|
||||||
|
|
||||||
|
width: memberList.width
|
||||||
|
|
||||||
|
// FIXME: use QSortFilterProxyModel instead
|
||||||
|
visible: memberSearch.input.text === "" || title.toLowerCase().includes(memberSearch.input.text.toLowerCase())
|
||||||
|
height: visible ? implicitHeight : 0
|
||||||
|
|
||||||
|
title: {
|
||||||
|
if (memberItem.itsMe) {
|
||||||
|
//% "You"
|
||||||
|
return qsTrId("You")
|
||||||
|
}
|
||||||
|
return !model.name.endsWith(".eth") ? model.name : Utils.removeStatusEns(model.name)
|
||||||
|
}
|
||||||
|
subTitle: model.id.substring(0, 5) + "..." + model.id.substring(model.id.length - 3)
|
||||||
|
|
||||||
|
statusListItemIcon {
|
||||||
|
name: model.name
|
||||||
|
badge {
|
||||||
|
visible: true
|
||||||
|
color: memberItem.isOnline ? Theme.palette.successColor1 : Theme.palette.baseColor1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 40
|
||||||
|
height: 40
|
||||||
|
source: model.icon
|
||||||
|
isIdenticon: false
|
||||||
|
}
|
||||||
|
|
||||||
|
icon {
|
||||||
|
width: 40
|
||||||
|
height: 40
|
||||||
|
color: Style.current.background
|
||||||
|
textColor: Style.current.secondaryText
|
||||||
|
letterSize: Math.max(4, root.imageWidth / 2.4)
|
||||||
|
charactersLen: 2
|
||||||
|
isLetterIdenticon: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ringSettings {
|
||||||
|
ringSpecModel: model.isAdded ? "" : Utils.getColorHashAsJson(model.id)
|
||||||
|
ringPxSize: Math.max(icon.width / 24.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: root.userProfileClicked(model.id)
|
||||||
|
|
||||||
|
components: [
|
||||||
|
StatusButton {
|
||||||
|
visible: root.editable && !memberItem.itsMe
|
||||||
|
text: qsTr("Ban")
|
||||||
|
type: StatusBaseButton.Type.Danger
|
||||||
|
size: StatusBaseButton.Size.Tiny
|
||||||
|
|
||||||
|
onClicked: root.banUserClicked(model.id)
|
||||||
|
},
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
visible: root.editable && !memberItem.itsMe
|
||||||
|
text: qsTr("Kick")
|
||||||
|
type: StatusBaseButton.Type.Danger
|
||||||
|
size: StatusBaseButton.Size.Tiny
|
||||||
|
|
||||||
|
onClicked: root.kickUserClicked(model.id)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Components 0.1
|
||||||
|
|
||||||
|
import "../../layouts"
|
||||||
|
|
||||||
|
StackLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string name
|
||||||
|
property string description
|
||||||
|
property string image
|
||||||
|
property color color
|
||||||
|
property bool editable: false
|
||||||
|
property bool owned: false
|
||||||
|
|
||||||
|
signal edited(Item item) // item containing edited fields (name, description, image, color)
|
||||||
|
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
SettingsPageLayout {
|
||||||
|
title: qsTr("Overview")
|
||||||
|
|
||||||
|
content: ColumnLayout {
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
StatusSmartIdenticon {
|
||||||
|
name: root.name
|
||||||
|
|
||||||
|
icon {
|
||||||
|
width: 80
|
||||||
|
height: 80
|
||||||
|
isLetterIdenticon: !root.image
|
||||||
|
color: root.color
|
||||||
|
letterSize: width / 2.4
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 80
|
||||||
|
height: 80
|
||||||
|
source: root.image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
id: nameText
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pixelSize: 24
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: root.name
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
id: descriptionText
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: root.description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
visible: root.editable
|
||||||
|
text: qsTr("Edit Community")
|
||||||
|
onClicked: root.currentIndex = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
implicitHeight: 1
|
||||||
|
visible: root.editable
|
||||||
|
color: Theme.palette.statusPopupMenu.separatorColor
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
visible: root.owned
|
||||||
|
|
||||||
|
StatusIcon {
|
||||||
|
icon: "info"
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("This node is the Community Owner Node. For your Community to function correctly try to keep this computer with Status running and onlinie as much as possible.")
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPageLayout {
|
||||||
|
id: editCommunityPage
|
||||||
|
|
||||||
|
previousPage: qsTr("Overview")
|
||||||
|
title: qsTr("Edit Community")
|
||||||
|
|
||||||
|
content: CommunityEditSettingsPanel {
|
||||||
|
name: root.name
|
||||||
|
description: root.description
|
||||||
|
color: root.color
|
||||||
|
image: root.image
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
editCommunityPage.dirty =
|
||||||
|
Qt.binding(() => {
|
||||||
|
return root.name != name ||
|
||||||
|
root.description != description ||
|
||||||
|
root.image != image ||
|
||||||
|
root.color != color
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onPreviousPageClicked: {
|
||||||
|
if (dirty) {
|
||||||
|
notifyDirty()
|
||||||
|
} else {
|
||||||
|
root.currentIndex = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSaveChangesClicked: {
|
||||||
|
root.currentIndex = 0
|
||||||
|
root.edited(contentItem)
|
||||||
|
reloadContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
onResetChangesClicked: reloadContent()
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,8 @@ Rectangle {
|
||||||
property var communitySectionModule
|
property var communitySectionModule
|
||||||
property bool hasAddedContacts
|
property bool hasAddedContacts
|
||||||
|
|
||||||
|
signal manageCommunityClicked()
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
|
@ -104,10 +106,7 @@ Rectangle {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: Style.current.padding
|
anchors.bottomMargin: Style.current.padding
|
||||||
onClicked: Global.openPopup(communityProfilePopup, {
|
|
||||||
store: rootStore,
|
onClicked: root.manageCommunityClicked()
|
||||||
community: root.activeCommunity,
|
|
||||||
communitySectionModule: root.communitySectionModule
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
import QtQuick 2.13
|
||||||
|
import QtQuick.Controls 2.13
|
||||||
|
import Qt.labs.settings 1.0
|
||||||
|
|
||||||
|
import utils 1.0
|
||||||
|
import shared 1.0
|
||||||
|
import shared.panels 1.0
|
||||||
|
import shared.popups 1.0
|
||||||
|
import shared.status 1.0
|
||||||
|
import shared.views.chat 1.0
|
||||||
|
|
||||||
|
import StatusQ.Layout 0.1
|
||||||
|
import StatusQ.Popups 0.1
|
||||||
|
|
||||||
|
import "."
|
||||||
|
import "../panels"
|
||||||
|
import "../panels/communities"
|
||||||
|
import "../popups"
|
||||||
|
import "../helpers"
|
||||||
|
import "../controls"
|
||||||
|
import "../stores"
|
||||||
|
|
||||||
|
StatusAppThreePanelLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var contactsStore
|
||||||
|
property bool hasAddedContacts: root.contactsStore.myContactsModel.count > 0
|
||||||
|
|
||||||
|
// Not Refactored
|
||||||
|
property var messageStore
|
||||||
|
|
||||||
|
property RootStore rootStore
|
||||||
|
|
||||||
|
property Component pinnedMessagesListPopupComponent
|
||||||
|
property var emojiPopup
|
||||||
|
property bool stickersLoaded: false
|
||||||
|
|
||||||
|
signal communityInfoButtonClicked()
|
||||||
|
signal communityManageButtonClicked()
|
||||||
|
signal profileButtonClicked()
|
||||||
|
signal openAppSearch()
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.rootStore.stickersStore.stickersModule
|
||||||
|
onStickerPacksLoaded: {
|
||||||
|
root.stickersLoaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.rootStore.chatCommunitySectionModule
|
||||||
|
onActiveItemChanged: {
|
||||||
|
root.rootStore.openCreateChat = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leftPanel: Loader {
|
||||||
|
id: contactColumnLoader
|
||||||
|
sourceComponent: root.rootStore.chatCommunitySectionModule.isCommunity()?
|
||||||
|
communtiyColumnComponent :
|
||||||
|
contactsColumnComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
centerPanel: ChatColumnView {
|
||||||
|
id: chatColumn
|
||||||
|
parentModule: root.rootStore.chatCommunitySectionModule
|
||||||
|
rootStore: root.rootStore
|
||||||
|
contactsStore: root.contactsStore
|
||||||
|
chatSectionModule: root.rootStore.chatCommunitySectionModule
|
||||||
|
pinnedMessagesPopupComponent: root.pinnedMessagesListPopupComponent
|
||||||
|
stickersLoaded: root.stickersLoaded
|
||||||
|
emojiPopup: root.emojiPopup
|
||||||
|
onOpenStickerPackPopup: {
|
||||||
|
Global.openPopup(statusStickerPackClickPopup, {packId: stickerPackId} )
|
||||||
|
}
|
||||||
|
onOpenAppSearch: {
|
||||||
|
root.openAppSearch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showRightPanel: {
|
||||||
|
if (root.rootStore.openCreateChat ||
|
||||||
|
!localAccountSensitiveSettings.showOnlineUsers ||
|
||||||
|
!localAccountSensitiveSettings.expandUsersList) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let chatContentModule = root.rootStore.currentChatContentModule()
|
||||||
|
if (!chatContentModule
|
||||||
|
|| chatContentModule.chatDetails.type === Constants.chatType.publicChat)
|
||||||
|
{
|
||||||
|
// New communities have no chats, so no chatContentModule or it is a public chat
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Check if user list is available as an option for particular chat content module
|
||||||
|
return chatContentModule.chatDetails.isUsersListAvailable
|
||||||
|
}
|
||||||
|
|
||||||
|
rightPanel: userListComponent
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: userListComponent
|
||||||
|
UserListPanel {
|
||||||
|
rootStore: root.rootStore
|
||||||
|
label: localAccountSensitiveSettings.communitiesEnabled &&
|
||||||
|
root.rootStore.chatCommunitySectionModule.isCommunity() ?
|
||||||
|
//% "Members"
|
||||||
|
qsTrId("members-label") :
|
||||||
|
qsTr("Last seen")
|
||||||
|
messageContextMenu: quickActionMessageOptionsMenu
|
||||||
|
usersModule: {
|
||||||
|
let chatContentModule = root.rootStore.currentChatContentModule()
|
||||||
|
if (!chatContentModule || !chatContentModule.usersModule) {
|
||||||
|
// New communities have no chats, so no chatContentModule
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
return chatContentModule.usersModule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: contactsColumnComponent
|
||||||
|
ContactsColumnView {
|
||||||
|
chatSectionModule: root.rootStore.chatCommunitySectionModule
|
||||||
|
store: root.rootStore
|
||||||
|
contactsStore: root.contactsStore
|
||||||
|
emojiPopup: root.emojiPopup
|
||||||
|
onOpenProfileClicked: {
|
||||||
|
root.profileButtonClicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpenAppSearch: {
|
||||||
|
root.openAppSearch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: communtiyColumnComponent
|
||||||
|
CommunityColumnView {
|
||||||
|
communitySectionModule: root.rootStore.chatCommunitySectionModule
|
||||||
|
store: root.rootStore
|
||||||
|
emojiPopup: root.emojiPopup
|
||||||
|
hasAddedContacts: root.hasAddedContacts
|
||||||
|
pinnedMessagesPopupComponent: root.pinnedMessagesListPopupComponent
|
||||||
|
onInfoButtonClicked: root.communityInfoButtonClicked()
|
||||||
|
onManageButtonClicked: root.communityManageButtonClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: groupInfoPopupComponent
|
||||||
|
GroupInfoPopup {
|
||||||
|
chatSectionModule: root.rootStore.chatCommunitySectionModule
|
||||||
|
store: root.rootStore
|
||||||
|
pinnedMessagesPopupComponent: root.pinnedMessagesListPopupComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: statusStickerPackClickPopup
|
||||||
|
StatusStickerPackClickPopup{
|
||||||
|
store: root.rootStore
|
||||||
|
onClosed: {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfirmationDialog {
|
||||||
|
id: removeContactConfirmationDialog
|
||||||
|
// % "Remove contact"
|
||||||
|
header.title: qsTrId("remove-contact")
|
||||||
|
//% "Are you sure you want to remove this contact?"
|
||||||
|
confirmationText: qsTrId("are-you-sure-you-want-to-remove-this-contact-")
|
||||||
|
onConfirmButtonClicked: {
|
||||||
|
let pk = chatColumn.contactToRemove
|
||||||
|
if (Utils.getContactDetailsAsJson(pk).isContact) {
|
||||||
|
root.contactsStore.removeContact(pk)
|
||||||
|
}
|
||||||
|
removeContactConfirmationDialog.parentPopup.close();
|
||||||
|
removeContactConfirmationDialog.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageContextMenuView {
|
||||||
|
id: quickActionMessageOptionsMenu
|
||||||
|
store: root.rootStore
|
||||||
|
|
||||||
|
onOpenProfileClicked: {
|
||||||
|
Global.openProfilePopup(publicKey)
|
||||||
|
}
|
||||||
|
onCreateOneToOneChat: {
|
||||||
|
Global.changeAppSectionBySectionType(Constants.appSection.chat)
|
||||||
|
root.rootStore.chatCommunitySectionModule.createOneToOneChat(communityId, chatId, ensName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,9 @@ Item {
|
||||||
//property int chatGroupsListViewCount: communityChatListAndCategories.chatList.count
|
//property int chatGroupsListViewCount: communityChatListAndCategories.chatList.count
|
||||||
property Component pinnedMessagesPopupComponent
|
property Component pinnedMessagesPopupComponent
|
||||||
|
|
||||||
|
signal infoButtonClicked
|
||||||
|
signal manageButtonClicked
|
||||||
|
|
||||||
StatusChatInfoToolBar {
|
StatusChatInfoToolBar {
|
||||||
id: communityHeader
|
id: communityHeader
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
@ -49,11 +52,7 @@ Item {
|
||||||
chatInfoButton.image.source: communityData.image
|
chatInfoButton.image.source: communityData.image
|
||||||
chatInfoButton.icon.color: communityData.color
|
chatInfoButton.icon.color: communityData.color
|
||||||
menuButton.visible: communityData.amISectionAdmin && communityData.canManageUsers
|
menuButton.visible: communityData.amISectionAdmin && communityData.canManageUsers
|
||||||
chatInfoButton.onClicked: Global.openPopup(communityProfilePopup, {
|
chatInfoButton.onClicked: root.infoButtonClicked()
|
||||||
store: root.store,
|
|
||||||
community: communityData,
|
|
||||||
communitySectionModule: root.communitySectionModule
|
|
||||||
})
|
|
||||||
|
|
||||||
popupMenu: StatusPopupMenu {
|
popupMenu: StatusPopupMenu {
|
||||||
StatusMenuItem {
|
StatusMenuItem {
|
||||||
|
@ -360,6 +359,7 @@ Item {
|
||||||
store: root.store
|
store: root.store
|
||||||
hasAddedContacts: root.hasAddedContacts
|
hasAddedContacts: root.hasAddedContacts
|
||||||
communitySectionModule: root.communitySectionModule
|
communitySectionModule: root.communitySectionModule
|
||||||
|
onManageCommunityClicked: root.manageButtonClicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,183 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
|
import QtGraphicalEffects 1.13
|
||||||
|
|
||||||
|
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.Layout 0.1
|
||||||
|
import StatusQ.Components 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Controls.Validators 0.1
|
||||||
|
|
||||||
|
import "../panels/communities"
|
||||||
|
import "../layouts"
|
||||||
|
|
||||||
|
StatusAppTwoPanelLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
// TODO: get this model from backend?
|
||||||
|
property var model: [{name: qsTr("Overview"), icon: "help"},
|
||||||
|
{name: qsTr("Members"), icon: "group-chat"},
|
||||||
|
// {name: qsTr("Permissions"), icon: "objects"},
|
||||||
|
// {name: qsTr("Tokens"), icon: "token"},
|
||||||
|
// {name: qsTr("Airdrops"), icon: "airdrop"},
|
||||||
|
// {name: qsTr("Token sales"), icon: "token-sale"},
|
||||||
|
// {name: qsTr("Subscriptions"), icon: "subscription"},
|
||||||
|
{name: qsTr("Notifications"), icon: "notification"}]
|
||||||
|
|
||||||
|
property var rootStore
|
||||||
|
property var community
|
||||||
|
property var chatCommunitySectionModule
|
||||||
|
|
||||||
|
signal backToCommunityClicked
|
||||||
|
signal openLegacyPopupClicked // TODO: remove me when migration to new settings is done
|
||||||
|
|
||||||
|
leftPanel: ColumnLayout {
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
margins: 8
|
||||||
|
topMargin: 16
|
||||||
|
bottomMargin: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
StatusNavigationPanelHeadline {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: qsTr("Settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: listView
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: contentItem.childrenRect.height
|
||||||
|
|
||||||
|
model: root.model
|
||||||
|
delegate: StatusNavigationListItem {
|
||||||
|
width: listView.width
|
||||||
|
title: modelData.name
|
||||||
|
icon.name: modelData.icon
|
||||||
|
selected: d.currentIndex == index
|
||||||
|
onClicked: d.currentIndex = index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove me when migration to new settings is done
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: qsTr("Open legacy popup (to be removed)")
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
font.pixelSize: 10
|
||||||
|
font.underline: true
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.openLegacyPopupClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: "<- " + qsTr("Back to community")
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
font.pixelSize: 15
|
||||||
|
font.underline: true
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.backToCommunityClicked()
|
||||||
|
hoverEnabled: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rightPanel: Loader {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 16
|
||||||
|
|
||||||
|
active: root.community
|
||||||
|
|
||||||
|
sourceComponent: StackLayout {
|
||||||
|
currentIndex: d.currentIndex
|
||||||
|
|
||||||
|
CommunityOverviewSettingsPanel {
|
||||||
|
name: root.community.name
|
||||||
|
description: root.community.description
|
||||||
|
image: root.community.image
|
||||||
|
color: root.community.color
|
||||||
|
editable: root.community.amISectionAdmin
|
||||||
|
|
||||||
|
onEdited: {
|
||||||
|
root.chatCommunitySectionModule.editCommunity(
|
||||||
|
Utils.filterXSS(item.name),
|
||||||
|
Utils.filterXSS(item.description),
|
||||||
|
root.community.access,
|
||||||
|
false, // FIXME
|
||||||
|
item.color.toString().toUpperCase(),
|
||||||
|
item.image === root.community.image ? "" : item.image,
|
||||||
|
item.imageAx,
|
||||||
|
item.imageAy,
|
||||||
|
item.imageBx,
|
||||||
|
item.imageBy,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CommunityMembersSettingsPanel {
|
||||||
|
membersModel: root.community.members
|
||||||
|
editable: root.community.amISectionAdmin
|
||||||
|
pendingRequests: root.community.pendingRequestsToJoin ? root.community.pendingRequestsToJoin.count : 0
|
||||||
|
|
||||||
|
onUserProfileClicked: Global.openProfilePopup(id)
|
||||||
|
onKickUserClicked: root.rootStore.removeUserFromCommunity(id)
|
||||||
|
onBanUserClicked: console.debug("NOT IMPLEMENTED") // TODO: implement me
|
||||||
|
onMembershipRequestsClicked: Global.openPopup(membershipRequestPopup, {
|
||||||
|
communitySectionModule: root.chatCommunitySectionModule
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPageLayout {
|
||||||
|
title: qsTr("Notifications")
|
||||||
|
|
||||||
|
content: ColumnLayout {
|
||||||
|
StatusListItem {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
title: qsTr("Enabled")
|
||||||
|
icon.name: "notification"
|
||||||
|
sensor.cursorShape: Qt.ArrowCursor
|
||||||
|
components: [
|
||||||
|
StatusSwitch {
|
||||||
|
checked: !root.community.muted
|
||||||
|
onClicked: root.chatCommunitySectionModule.setCommunityMuted(!checked)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
property int currentIndex: 0
|
||||||
|
}
|
||||||
|
}
|
|
@ -511,17 +511,17 @@ Item {
|
||||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
pinnedMessagesListPopupComponent: pinnedMessagesPopupComponent
|
chatView.pinnedMessagesListPopupComponent: pinnedMessagesPopupComponent
|
||||||
emojiPopup: statusEmojiPopup
|
chatView.emojiPopup: statusEmojiPopup
|
||||||
|
|
||||||
contactsStore: appMain.rootStore.contactStore
|
contactsStore: appMain.rootStore.contactStore
|
||||||
rootStore.emojiReactionsModel: appMain.rootStore.emojiReactionsModel
|
rootStore.emojiReactionsModel: appMain.rootStore.emojiReactionsModel
|
||||||
|
|
||||||
onProfileButtonClicked: {
|
chatView.onProfileButtonClicked: {
|
||||||
Global.changeAppSectionBySectionType(Constants.appSection.profile);
|
Global.changeAppSectionBySectionType(Constants.appSection.profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenAppSearch: {
|
chatView.onOpenAppSearch: {
|
||||||
appSearch.openSearchPopup()
|
appSearch.openSearchPopup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,17 +601,17 @@ Item {
|
||||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
pinnedMessagesListPopupComponent: pinnedMessagesPopupComponent
|
chatView.pinnedMessagesListPopupComponent: pinnedMessagesPopupComponent
|
||||||
emojiPopup: statusEmojiPopup
|
chatView.emojiPopup: statusEmojiPopup
|
||||||
|
|
||||||
contactsStore: appMain.rootStore.contactStore
|
contactsStore: appMain.rootStore.contactStore
|
||||||
rootStore.emojiReactionsModel: appMain.rootStore.emojiReactionsModel
|
rootStore.emojiReactionsModel: appMain.rootStore.emojiReactionsModel
|
||||||
|
|
||||||
onProfileButtonClicked: {
|
chatView.onProfileButtonClicked: {
|
||||||
Global.changeAppSectionBySectionType(Constants.appSection.profile);
|
Global.changeAppSectionBySectionType(Constants.appSection.profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenAppSearch: {
|
chatView.onOpenAppSearch: {
|
||||||
appSearch.openSearchPopup()
|
appSearch.openSearchPopup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue