feat: implement redesign of communities on the left tab

This commit is contained in:
Jonathan Rainville 2021-02-17 11:31:59 -05:00 committed by Iuri Matias
parent 534cb23e18
commit 64d38b6049
12 changed files with 290 additions and 286 deletions

View File

@ -29,23 +29,14 @@ Item {
id: communityHeader id: communityHeader
width: parent.width width: parent.width
height: communityHeaderButton.height height: communityHeaderButton.height
anchors.left: parent.left
anchors.leftMargin: 12
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: Style.current.padding anchors.topMargin: Style.current.padding
StatusIconButton {
id: backArrow
icon.name: "arrow-right"
iconRotation: 180
iconColor: Style.current.inputColor
anchors.left: parent.left
anchors.leftMargin: Style.current.bigPadding
anchors.verticalCenter: communityHeaderButton.verticalCenter
onClicked: chatsModel.communities.activeCommunity.active = false
}
CommunityHeaderButton { CommunityHeaderButton {
id: communityHeaderButton id: communityHeaderButton
anchors.left: backArrow.right anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: -4 anchors.topMargin: -4
} }

View File

@ -5,98 +5,48 @@ import "../../../../shared/status"
import "../../../../imports" import "../../../../imports"
import "../components" import "../components"
Rectangle { StatusIconTabButton {
property string communityId: "" property string communityId: ""
property string name: "channelName" property string name: "channelName"
property string description: "channel description"
property string unviewedMessagesCount: "0" property string unviewedMessagesCount: "0"
property string image property string image
property bool hasMentions: false property bool hasMentions: false
property string searchStr: ""
property bool isCompact: appSettings.useCompactMode
property bool hovered: false
id: communityButton id: communityButton
color: { anchors.horizontalCenter: parent.horizontalCenter
if (communityButton.hovered) { iconSource: communityButton.image
return Style.current.secondaryBackground anchors.topMargin: 0
}
return Style.current.background
}
anchors.right: parent.right
anchors.top: applicationWindow.top
anchors.left: parent.left
radius: Style.current.radius
// Hide the box if it is filtered out
property bool isVisible: searchStr === "" ||
communityButton.name.toLowerCase().includes(searchStr) ||
communityButton.description.toLowerCase().includes(searchStr)
visible: isVisible ? true : false
height: isVisible ? !isCompact ? 64 : communityImage.height + Style.current.smallPadding * 2 : 0
RoundedImage { section: Constants.community
id: communityImage
height: !isCompact ? 40 : 20
width: !isCompact ? 40 : 20
source: communityButton.image
anchors.left: parent.left
anchors.leftMargin: !isCompact ? Style.current.padding : Style.current.smallPadding
anchors.verticalCenter: parent.verticalCenter
}
StyledText { checked: chatsModel.communities.activeCommunity.active && chatsModel.communities.activeCommunity.id === communityId
id: contactInfo
text: communityButton.name borderOnChecked: true
anchors.right: contactNumberChatsCircle.left doNotHandleClick: true
anchors.rightMargin: Style.current.smallPadding onClicked: {
elide: Text.ElideRight appMain.changeAppSection(Constants.chat)
font.weight: Font.Medium chatsModel.communities.setActiveCommunity(communityId)
font.pixelSize: 15
anchors.left: communityImage.right
anchors.leftMargin: Style.current.padding
anchors.verticalCenter: parent.verticalCenter
} }
Rectangle { Rectangle {
id: contactNumberChatsCircle id: chatBadge
width: 22 visible: unviewedMessagesCount > 0
anchors.top: parent.top
anchors.left: parent.right
anchors.leftMargin: -17
anchors.topMargin: 1
radius: height / 2
color: Style.current.blue
border.color: Style.current.background
border.width: 2
width: unviewedMessagesCount < 10 ? 22 : messageCount.width + 14
height: 22 height: 22
radius: 50 Text {
anchors.right: parent.right id: messageCount
anchors.rightMargin: !isCompact ? Style.current.padding : Style.current.smallPadding font.pixelSize: chatsModel.unreadMessagesCount > 99 ? 10 : 12
anchors.verticalCenter: parent.verticalCenter
color: Style.current.primary
visible: (unviewedMessagesCount > 0) || communityButton.hasMentions
StyledText {
id: contactNumberChats
text: communityButton.hasMentions ? '@' : (communityButton.unviewedMessagesCount < 100 ? communityButton.unviewedMessagesCount : "99")
font.pixelSize: 12
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: Style.current.white color: Style.current.white
anchors.centerIn: parent
text: unviewedMessagesCount > 99 ? "99+" : unviewedMessagesCount
} }
} }
MouseArea {
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
hoverEnabled: true
onEntered: {
communityButton.hovered = true
}
onExited: {
communityButton.hovered = false
}
onClicked: {
chatsModel.communities.setActiveCommunity(communityId)
}
}
} }
/*##^##
Designer {
D{i:0;formeditorColor:"#ffffff";height:64;width:640}
}
##^##*/

View File

@ -6,50 +6,18 @@ import "../../../../imports"
import "../components" import "../components"
import "./" import "./"
Item { ListView {
property string searchStr: ""
id: root
width: parent.width
height: Math.max(communityListView.height, noSearchResults.height)
ListView {
id: communityListView id: communityListView
spacing: Style.current.halfPadding spacing: 12
anchors.top: parent.top
height: childrenRect.height height: childrenRect.height
visible: height > 10 visible: height > 10
width:parent.width width:parent.width
interactive: false interactive: false
model: chatsModel.communities.joinedCommunities model: chatsModel.communities.joinedCommunities
delegate: CommunityButton { delegate: CommunityButton {
communityId: model.id communityId: model.id
name: model.name name: model.name
description: model.description
searchStr: root.searchStr
image: model.thumbnailImage image: model.thumbnailImage
} }
}
Item {
id: noSearchResults
anchors.top: parent.top
height: visible ? 200 : 0
visible: !communityListView.visible && root.searchStr !== ""
width: parent.width
StyledText {
font.pixelSize: 15
color: Style.current.darkGrey
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
//% "No search results in Communities"
text: qsTrId("no-search-results-in-communities")
}
}
} }
/*##^##
Designer {
D{i:0;autoSize:true;height:480;width:640}
}
##^##*/

View File

@ -120,37 +120,8 @@ Item {
contentHeight: communitiesListLoader.height + channelList.height + 2 * Style.current.padding + emptyViewAndSuggestions.height contentHeight: communitiesListLoader.height + channelList.height + 2 * Style.current.padding + emptyViewAndSuggestions.height
clip: true clip: true
Loader {
id: communitiesListLoader
active: appSettings.communitiesEnabled
width: parent.width
height: {
if (item && active) {
return item.height
}
return 0
}
sourceComponent: Component {
CommunityList {
id: communityList
visible: appSettings.communitiesEnabled
searchStr: contactsColumn.searchStr.toLowerCase()
}
}
}
Separator {
id: communitySep
visible: communitiesListLoader.active && communitiesListLoader.height > 0
anchors.top: communitiesListLoader.bottom
anchors.topMargin: visible ? Style.current.halfPadding : 0
}
ChannelList { ChannelList {
id: channelList id: channelList
anchors.top: communitySep.bottom
anchors.topMargin: Style.current.halfPadding
searchStr: contactsColumn.searchStr.toLowerCase() searchStr: contactsColumn.searchStr.toLowerCase()
channelModel: chatsModel.chats channelModel: chatsModel.chats
} }

View File

@ -0,0 +1,76 @@
import QtQuick 2.3
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import Qt.labs.platform 1.1
import "../../../../imports"
import "../../../../shared"
import "../../../../shared/status"
Column {
spacing: 12
width: parent.width
height: childrenRect.height
Rectangle {
width: 40
height: 1
color: Style.current.border
anchors.horizontalCenter: parent.horizontalCenter
}
StatusIconTabButton {
id: walletBtn
enabled: isExperimental === "1" || appSettings.walletEnabled
icon.name: "wallet"
section: Constants.wallet
}
StatusIconTabButton {
id: browserBtn
enabled: isExperimental === "1" || appSettings.browserEnabled
icon.name: "compass"
section: Constants.browser
}
StatusIconTabButton {
id: timelineBtn
enabled: isExperimental === "1" || appSettings.timelineEnabled
icon.name: "timeline"
section: Constants.timeline
}
StatusIconTabButton {
id: profileBtn
icon.name: "profile"
section: Constants.profile
Rectangle {
id: profileBadge
visible: !profileModel.mnemonic.isBackedUp && sLayout.children[sLayout.currentIndex] !== profileLayoutContainer
anchors.top: parent.top
anchors.right: parent.right
anchors.rightMargin: 4
anchors.topMargin: 5
radius: height / 2
color: Style.current.blue
border.color: profileBtn.hovered ? Style.current.secondaryBackground : Style.current.background
border.width: 2
width: 14
height: 14
}
}
StatusIconTabButton {
id: nodeBtn
enabled: isExperimental === "1" && appSettings.nodeManagementEnabled
icon.name: "node"
section: Constants.node
}
StatusIconTabButton {
id: uiComponentBtn
enabled: isExperimental === "1"
icon.name: "node"
section: Constants.ui
}
}

View File

@ -10,6 +10,7 @@ import "./AppLayouts"
import "./AppLayouts/Timeline" import "./AppLayouts/Timeline"
import "./AppLayouts/Wallet" import "./AppLayouts/Wallet"
import "./AppLayouts/Chat/components" import "./AppLayouts/Chat/components"
import "./AppLayouts/Chat/CommunityComponents"
import Qt.labs.settings 1.0 import Qt.labs.settings 1.0
RowLayout { RowLayout {
@ -282,45 +283,45 @@ RowLayout {
} }
function changeAppSection(section) { function changeAppSection(section) {
let sectionId = -1 sLayout.currentIndex = Utils.getAppSectionIndex(section)
switch (section) {
case Constants.chat: sectionId = 0; break;
case Constants.wallet: sectionId = 1; break;
case Constants.browser: sectionId = 2; break;
case Constants.profile: sectionId = 4; break;
case Constants.node: sectionId = 5; break;
case Constants.ui: sectionId = 6; break;
}
if (sectionId === -1) {
throw new Exception ("Unknown section name. Check the Constants to know the available ones")
}
tabBar.setCurrentIndex(sectionId)
} }
TabBar {
id: tabBar Item {
width: 78 id: leftTab
Layout.maximumWidth: 80 Layout.topMargin: 50
Layout.preferredWidth: 80 Layout.maximumWidth: 78
Layout.minimumWidth: 80 Layout.minimumWidth: 78
currentIndex: 0 Layout.preferredWidth: 78
topPadding: 57
rightPadding: 19
leftPadding: 19
transformOrigin: Item.Top
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true Layout.fillHeight: true
spacing: 5 height: parent.height
background: Rectangle {
color: "#00000000" ScrollView {
border.color: Style.current.border id: scrollView
} width: leftTab.width
anchors.top: parent.top
anchors.bottom: leftTabButtons.visible ? leftTabButtons.top : parent.bottom
anchors.bottomMargin: tabBar.spacing
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Column {
id: tabBar
spacing: 12
width: scrollView.width
StatusIconTabButton { StatusIconTabButton {
id: chatBtn id: chatBtn
anchors.horizontalCenter: parent.horizontalCenter
icon.name: "message" icon.name: "message"
anchors.topMargin: 0 section: Constants.chat
doNotHandleClick: true
onClicked: {
chatsModel.communities.activeCommunity.active = false
appMain.changeAppSection(Constants.chat)
}
checked: !chatsModel.communities.activeCommunity.active && sLayout.currentIndex === Utils.getAppSectionIndex(Constants.chat)
Rectangle { Rectangle {
id: chatBadge id: chatBadge
@ -345,61 +346,49 @@ RowLayout {
} }
} }
StatusIconTabButton { Loader {
id: walletBtn id: communitiesListLoader
anchors.top: chatBtn.top active: appSettings.communitiesEnabled
enabled: isExperimental === "1" || appSettings.walletEnabled anchors.horizontalCenter: parent.horizontalCenter
icon.name: "wallet" width: parent.width
height: {
if (item && active) {
return item.height
} }
StatusIconTabButton { return 0
id: browserBtn }
anchors.top: walletBtn.top sourceComponent: Component {
enabled: isExperimental === "1" || appSettings.browserEnabled CommunityList {}
icon.name: "compass" }
} }
StatusIconTabButton { Loader {
id: timelineBtn active: !leftTabButtons.visible
anchors.top: browserBtn.enabled ? browserBtn.top : walletBtn.top width: parent.width
enabled: isExperimental === "1" || appSettings.timelineEnabled height: {
icon.name: "timeline" if (item && active) {
return item.height
}
return 0
}
sourceComponent: LeftTabBottomButtons {}
}
}
} }
StatusIconTabButton { LeftTabBottomButtons {
id: profileBtn id: leftTabButtons
anchors.top: timelineBtn.enabled ? timelineBtn.top : browserBtn.top visible: scrollView.contentHeight > leftTab.height
icon.name: "profile" anchors.bottom: parent.bottom
anchors.bottomMargin: Style.current.padding
Rectangle {
id: profileBadge
visible: !profileModel.mnemonic.isBackedUp && sLayout.children[sLayout.currentIndex] !== profileLayoutContainer
anchors.top: parent.top
anchors.right: parent.right
anchors.rightMargin: 4
anchors.topMargin: 5
radius: height / 2
color: Style.current.blue
border.color: profileBtn.hovered ? Style.current.secondaryBackground : Style.current.background
border.width: 2
width: 14
height: 14
} }
} }
StatusIconTabButton { Rectangle {
id: nodeBtn height: parent.height
enabled: isExperimental === "1" && appSettings.nodeManagementEnabled width: 1
anchors.top: profileBtn.top color: Style.current.border
icon.name: "node"
}
StatusIconTabButton {
id: uiComponentBtn
enabled: isExperimental === "1"
anchors.top: nodeBtn.top
icon.name: "node"
}
} }
StackLayout { StackLayout {
@ -407,7 +396,7 @@ RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true Layout.fillHeight: true
currentIndex: tabBar.currentIndex currentIndex: 0
onCurrentIndexChanged: { onCurrentIndexChanged: {
if (typeof this.children[currentIndex].onActivated === "function") { if (typeof this.children[currentIndex].onActivated === "function") {
this.children[currentIndex].onActivated() this.children[currentIndex].onActivated()
@ -494,6 +483,6 @@ RowLayout {
/*##^## /*##^##
Designer { Designer {
D{i:0;formeditorZoom:0.33000001311302185;height:770;width:1232} D{i:0;formeditorZoom:1.75;height:770;width:1232}
} }
##^##*/ ##^##*/

View File

@ -26,10 +26,12 @@ QtObject {
readonly property string chat: "chat" readonly property string chat: "chat"
readonly property string wallet: "wallet" readonly property string wallet: "wallet"
readonly property string timeline: "timeline"
readonly property string browser: "browser" readonly property string browser: "browser"
readonly property string profile: "profile" readonly property string profile: "profile"
readonly property string node: "node" readonly property string node: "node"
readonly property string ui: "ui" readonly property string ui: "ui"
readonly property string community: "community"
readonly property int fontSizeXS: 0 readonly property int fontSizeXS: 0
readonly property int fontSizeS: 1 readonly property int fontSizeS: 1

View File

@ -30,6 +30,24 @@ QtObject {
(!startsWith0x(value) && value.length === 64)) (!startsWith0x(value) && value.length === 64))
} }
function getAppSectionIndex(section) {
let sectionId = -1
switch (section) {
case Constants.chat: sectionId = 0; break;
case Constants.wallet: sectionId = 1; break;
case Constants.browser: sectionId = 2; break;
case Constants.timeline: sectionId = 3; break;
case Constants.profile: sectionId = 4; break;
case Constants.node: sectionId = 5; break;
case Constants.ui: sectionId = 6; break;
case Constants.community: sectionId = 99; break;
}
if (sectionId === -1) {
throw new Exception ("Unknown section name. Check the Constants to know the available ones")
}
return sectionId
}
function getDisplayName(publicKey, contactIndex) { function getDisplayName(publicKey, contactIndex) {
if (contactIndex === undefined) { if (contactIndex === undefined) {
contactIndex = profileModel.contacts.list.getContactIndexByPubkey(publicKey) contactIndex = profileModel.contacts.list.getContactIndexByPubkey(publicKey)

View File

@ -156,6 +156,7 @@ DISTFILES += \
app/AppLayouts/Chat/components/EmojiCategoryButton.qml \ app/AppLayouts/Chat/components/EmojiCategoryButton.qml \
app/AppLayouts/Chat/components/EmojiPopup.qml \ app/AppLayouts/Chat/components/EmojiPopup.qml \
app/AppLayouts/Chat/components/EmojiReaction.qml \ app/AppLayouts/Chat/components/EmojiReaction.qml \
app/AppLayouts/Chat/components/LeftTabBottomButtons.qml \
app/AppLayouts/Chat/components/NoFriendsRectangle.qml \ app/AppLayouts/Chat/components/NoFriendsRectangle.qml \
app/AppLayouts/Chat/components/ProfilePopup.qml \ app/AppLayouts/Chat/components/ProfilePopup.qml \
app/AppLayouts/Chat/components/EmojiSection.qml \ app/AppLayouts/Chat/components/EmojiSection.qml \

View File

@ -5,6 +5,7 @@ import "../imports"
Rectangle { Rectangle {
id: root id: root
property bool noHover: false property bool noHover: false
property bool noMouseArea: false
property alias source: image.source property alias source: image.source
property alias fillMode: image.fillMode property alias fillMode: image.fillMode
property bool showLoadingIndicator: true property bool showLoadingIndicator: true
@ -156,6 +157,7 @@ Rectangle {
} }
} }
MouseArea { MouseArea {
enabled: !noMouseArea
cursorShape: noHover ? Qt.ArrowCursor : Qt.PointingHandCursor cursorShape: noHover ? Qt.ArrowCursor : Qt.PointingHandCursor
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {

View File

@ -4,6 +4,7 @@ import QtGraphicalEffects 1.0
Rectangle { Rectangle {
id: root id: root
signal clicked signal clicked
property bool noMouseArea: false
property bool noHover: false property bool noHover: false
property alias showLoadingIndicator: imgStickerPackThumb.showLoadingIndicator property alias showLoadingIndicator: imgStickerPackThumb.showLoadingIndicator
property alias source: imgStickerPackThumb.source property alias source: imgStickerPackThumb.source
@ -27,6 +28,7 @@ Rectangle {
ImageLoader { ImageLoader {
id: imgStickerPackThumb id: imgStickerPackThumb
noMouseArea: root.noMouseArea
noHover: root.noHover noHover: root.noHover
opacity: 1 opacity: 1
smooth: false smooth: false

View File

@ -10,11 +10,25 @@ TabButton {
visible: enabled visible: enabled
width: 40 width: 40
height: enabled ? 40 : 0 height: enabled ? 40 : 0
anchors.topMargin: enabled ? 50 : 0
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
property color iconColor: Style.current.secondaryText property color iconColor: Style.current.secondaryText
property color disabledColor: iconColor property color disabledColor: iconColor
property int iconRotation: 0 property int iconRotation: 0
property string iconSource
property string section
property int sectionIndex: Utils.getAppSectionIndex(section)
property bool doNotHandleClick: false
property bool borderOnChecked: false
onClicked: {
if (doNotHandleClick) {
return
}
appMain.changeAppSection(section)
}
checked: sLayout.currentIndex === sectionIndex
icon.height: 24 icon.height: 24
icon.width: 24 icon.width: 24
@ -26,35 +40,55 @@ TabButton {
} }
onIconChanged: { onIconChanged: {
if (iconSource) {
icon.source = iconSource
return
}
icon.source = icon.name ? "../../app/img/" + icon.name + ".svg" : "" icon.source = icon.name ? "../../app/img/" + icon.name + ".svg" : ""
} }
contentItem: Item { contentItem: Item {
anchors.fill: parent anchors.fill: parent
Loader {
active: true
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
sourceComponent: !!iconSource ? imageIcon : defaultIcon
}
Component {
id: defaultIcon
SVGImage { SVGImage {
id: iconImg id: iconImg
visible: false
source: control.icon.source source: control.icon.source
height: control.icon.height height: control.icon.height
width: control.icon.width width: control.icon.width
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
rotation: control.iconRotation rotation: control.iconRotation
}
ColorOverlay { ColorOverlay {
anchors.fill: iconImg anchors.fill: iconImg
source: iconImg source: iconImg
color: control.icon.color color: control.icon.color
antialiasing: true antialiasing: true
smooth: true smooth: true
rotation: control.iconRotation }
}
} }
Component {
id: imageIcon
RoundedImage {
source: iconSource
noMouseArea: true
}
}
} }
background: Rectangle { background: Rectangle {
color: hovered ? Style.current.secondaryBackground : "transparent" color: hovered || (borderOnChecked && checked) ? Style.current.secondaryBackground : "transparent"
border.color: Style.current.primary
border.width: borderOnChecked && checked ? 1 : 0
radius: control.width / 2 radius: control.width / 2
} }