diff --git a/ui/app/AppLayouts/Chat/CommunityColumn.qml b/ui/app/AppLayouts/Chat/CommunityColumn.qml index a614ffd12a..9a73c87267 100644 --- a/ui/app/AppLayouts/Chat/CommunityColumn.qml +++ b/ui/app/AppLayouts/Chat/CommunityColumn.qml @@ -29,23 +29,14 @@ Item { id: communityHeader width: parent.width height: communityHeaderButton.height + anchors.left: parent.left + anchors.leftMargin: 12 anchors.top: parent.top 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 { id: communityHeaderButton - anchors.left: backArrow.right + anchors.left: parent.left anchors.top: parent.top anchors.topMargin: -4 } diff --git a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityButton.qml b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityButton.qml index a9815e0681..95d46e5a17 100644 --- a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityButton.qml +++ b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityButton.qml @@ -5,98 +5,48 @@ import "../../../../shared/status" import "../../../../imports" import "../components" -Rectangle { +StatusIconTabButton { property string communityId: "" property string name: "channelName" - property string description: "channel description" property string unviewedMessagesCount: "0" property string image property bool hasMentions: false - property string searchStr: "" - property bool isCompact: appSettings.useCompactMode - property bool hovered: false id: communityButton - color: { - if (communityButton.hovered) { - return Style.current.secondaryBackground - } - 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 + anchors.horizontalCenter: parent.horizontalCenter + iconSource: communityButton.image + anchors.topMargin: 0 - RoundedImage { - 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 - } + section: Constants.community - StyledText { - id: contactInfo - text: communityButton.name - anchors.right: contactNumberChatsCircle.left - anchors.rightMargin: Style.current.smallPadding - elide: Text.ElideRight - font.weight: Font.Medium - font.pixelSize: 15 - anchors.left: communityImage.right - anchors.leftMargin: Style.current.padding - anchors.verticalCenter: parent.verticalCenter + checked: chatsModel.communities.activeCommunity.active && chatsModel.communities.activeCommunity.id === communityId + + borderOnChecked: true + doNotHandleClick: true + onClicked: { + appMain.changeAppSection(Constants.chat) + chatsModel.communities.setActiveCommunity(communityId) } Rectangle { - id: contactNumberChatsCircle - width: 22 + id: chatBadge + 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 - radius: 50 - anchors.right: parent.right - anchors.rightMargin: !isCompact ? Style.current.padding : Style.current.smallPadding - 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 + Text { + id: messageCount + font.pixelSize: chatsModel.unreadMessagesCount > 99 ? 10 : 12 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} -} -##^##*/ diff --git a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityList.qml b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityList.qml index 55eb1c8bc1..18b1e90be9 100644 --- a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityList.qml +++ b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityList.qml @@ -6,50 +6,18 @@ import "../../../../imports" import "../components" import "./" -Item { - property string searchStr: "" - id: root - width: parent.width - height: Math.max(communityListView.height, noSearchResults.height) - ListView { - id: communityListView - spacing: Style.current.halfPadding - anchors.top: parent.top - height: childrenRect.height - visible: height > 10 - width:parent.width - interactive: false - model: chatsModel.communities.joinedCommunities - delegate: CommunityButton { - communityId: model.id - name: model.name - description: model.description - searchStr: root.searchStr - image: model.thumbnailImage - } - } +ListView { + id: communityListView + spacing: 12 + height: childrenRect.height + visible: height > 10 + width:parent.width + interactive: false - 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") - } + model: chatsModel.communities.joinedCommunities + delegate: CommunityButton { + communityId: model.id + name: model.name + image: model.thumbnailImage } } - - -/*##^## -Designer { - D{i:0;autoSize:true;height:480;width:640} -} -##^##*/ diff --git a/ui/app/AppLayouts/Chat/ContactsColumn.qml b/ui/app/AppLayouts/Chat/ContactsColumn.qml index 61f0f003cf..ef8e2efa3d 100644 --- a/ui/app/AppLayouts/Chat/ContactsColumn.qml +++ b/ui/app/AppLayouts/Chat/ContactsColumn.qml @@ -120,37 +120,8 @@ Item { contentHeight: communitiesListLoader.height + channelList.height + 2 * Style.current.padding + emptyViewAndSuggestions.height 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 { id: channelList - anchors.top: communitySep.bottom - anchors.topMargin: Style.current.halfPadding searchStr: contactsColumn.searchStr.toLowerCase() channelModel: chatsModel.chats } diff --git a/ui/app/AppLayouts/Chat/components/LeftTabBottomButtons.qml b/ui/app/AppLayouts/Chat/components/LeftTabBottomButtons.qml new file mode 100644 index 0000000000..293b282bc1 --- /dev/null +++ b/ui/app/AppLayouts/Chat/components/LeftTabBottomButtons.qml @@ -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 + } +} diff --git a/ui/app/AppMain.qml b/ui/app/AppMain.qml index e5b7d24635..bed9153654 100644 --- a/ui/app/AppMain.qml +++ b/ui/app/AppMain.qml @@ -10,6 +10,7 @@ import "./AppLayouts" import "./AppLayouts/Timeline" import "./AppLayouts/Wallet" import "./AppLayouts/Chat/components" +import "./AppLayouts/Chat/CommunityComponents" import Qt.labs.settings 1.0 RowLayout { @@ -282,124 +283,112 @@ RowLayout { } function changeAppSection(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.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) + sLayout.currentIndex = Utils.getAppSectionIndex(section) } - TabBar { - id: tabBar - width: 78 - Layout.maximumWidth: 80 - Layout.preferredWidth: 80 - Layout.minimumWidth: 80 - currentIndex: 0 - topPadding: 57 - rightPadding: 19 - leftPadding: 19 - transformOrigin: Item.Top - Layout.alignment: Qt.AlignLeft | Qt.AlignTop + + Item { + id: leftTab + Layout.topMargin: 50 + Layout.maximumWidth: 78 + Layout.minimumWidth: 78 + Layout.preferredWidth: 78 Layout.fillHeight: true - spacing: 5 - background: Rectangle { - color: "#00000000" - border.color: Style.current.border - } + height: parent.height - StatusIconTabButton { - id: chatBtn - anchors.horizontalCenter: parent.horizontalCenter - icon.name: "message" - anchors.topMargin: 0 + ScrollView { + id: scrollView + width: leftTab.width + anchors.top: parent.top + anchors.bottom: leftTabButtons.visible ? leftTabButtons.top : parent.bottom + anchors.bottomMargin: tabBar.spacing + clip: true - Rectangle { - id: chatBadge - visible: chatsModel.unreadMessagesCount > 0 - anchors.top: parent.top - anchors.left: parent.right - anchors.leftMargin: -17 - anchors.topMargin: 1 - radius: height / 2 - color: Style.current.blue - border.color: chatBtn.hovered ? Style.current.secondaryBackground : Style.current.background - border.width: 2 - width: chatsModel.unreadMessagesCount < 10 ? 22 : messageCount.width + 14 - height: 22 - Text { - id: messageCount - font.pixelSize: chatsModel.unreadMessagesCount > 99 ? 10 : 12 - color: Style.current.white - anchors.centerIn: parent - text: chatsModel.unreadMessagesCount > 99 ? "99+" : chatsModel.unreadMessagesCount - } - } - } + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - StatusIconTabButton { - id: walletBtn - anchors.top: chatBtn.top - enabled: isExperimental === "1" || appSettings.walletEnabled - icon.name: "wallet" - } + Column { + id: tabBar + spacing: 12 + width: scrollView.width - StatusIconTabButton { - id: browserBtn - anchors.top: walletBtn.top - enabled: isExperimental === "1" || appSettings.browserEnabled - icon.name: "compass" - } + StatusIconTabButton { + id: chatBtn + icon.name: "message" + section: Constants.chat + doNotHandleClick: true + onClicked: { + chatsModel.communities.activeCommunity.active = false + appMain.changeAppSection(Constants.chat) + } - StatusIconTabButton { - id: timelineBtn - anchors.top: browserBtn.enabled ? browserBtn.top : walletBtn.top - enabled: isExperimental === "1" || appSettings.timelineEnabled - icon.name: "timeline" - } + checked: !chatsModel.communities.activeCommunity.active && sLayout.currentIndex === Utils.getAppSectionIndex(Constants.chat) - StatusIconTabButton { - id: profileBtn - anchors.top: timelineBtn.enabled ? timelineBtn.top : browserBtn.top - icon.name: "profile" + Rectangle { + id: chatBadge + visible: chatsModel.unreadMessagesCount > 0 + anchors.top: parent.top + anchors.left: parent.right + anchors.leftMargin: -17 + anchors.topMargin: 1 + radius: height / 2 + color: Style.current.blue + border.color: chatBtn.hovered ? Style.current.secondaryBackground : Style.current.background + border.width: 2 + width: chatsModel.unreadMessagesCount < 10 ? 22 : messageCount.width + 14 + height: 22 + Text { + id: messageCount + font.pixelSize: chatsModel.unreadMessagesCount > 99 ? 10 : 12 + color: Style.current.white + anchors.centerIn: parent + text: chatsModel.unreadMessagesCount > 99 ? "99+" : chatsModel.unreadMessagesCount + } + } + } - 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 + Loader { + id: communitiesListLoader + active: appSettings.communitiesEnabled + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + height: { + if (item && active) { + return item.height + } + + return 0 + } + sourceComponent: Component { + CommunityList {} + } + } + + Loader { + active: !leftTabButtons.visible + width: parent.width + height: { + if (item && active) { + return item.height + } + return 0 + } + sourceComponent: LeftTabBottomButtons {} + } } } - StatusIconTabButton { - id: nodeBtn - enabled: isExperimental === "1" && appSettings.nodeManagementEnabled - anchors.top: profileBtn.top - icon.name: "node" + LeftTabBottomButtons { + id: leftTabButtons + visible: scrollView.contentHeight > leftTab.height + anchors.bottom: parent.bottom + anchors.bottomMargin: Style.current.padding } + } - StatusIconTabButton { - id: uiComponentBtn - enabled: isExperimental === "1" - anchors.top: nodeBtn.top - icon.name: "node" - } + Rectangle { + height: parent.height + width: 1 + color: Style.current.border } StackLayout { @@ -407,7 +396,7 @@ RowLayout { Layout.fillWidth: true Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.fillHeight: true - currentIndex: tabBar.currentIndex + currentIndex: 0 onCurrentIndexChanged: { if (typeof this.children[currentIndex].onActivated === "function") { this.children[currentIndex].onActivated() @@ -494,6 +483,6 @@ RowLayout { /*##^## Designer { - D{i:0;formeditorZoom:0.33000001311302185;height:770;width:1232} + D{i:0;formeditorZoom:1.75;height:770;width:1232} } ##^##*/ diff --git a/ui/imports/Constants.qml b/ui/imports/Constants.qml index cfc77aa401..d83579baaa 100644 --- a/ui/imports/Constants.qml +++ b/ui/imports/Constants.qml @@ -26,10 +26,12 @@ QtObject { readonly property string chat: "chat" readonly property string wallet: "wallet" + readonly property string timeline: "timeline" readonly property string browser: "browser" readonly property string profile: "profile" readonly property string node: "node" readonly property string ui: "ui" + readonly property string community: "community" readonly property int fontSizeXS: 0 readonly property int fontSizeS: 1 diff --git a/ui/imports/Utils.qml b/ui/imports/Utils.qml index 26028c5cbf..6d548747e8 100644 --- a/ui/imports/Utils.qml +++ b/ui/imports/Utils.qml @@ -30,6 +30,24 @@ QtObject { (!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) { if (contactIndex === undefined) { contactIndex = profileModel.contacts.list.getContactIndexByPubkey(publicKey) diff --git a/ui/nim-status-client.pro b/ui/nim-status-client.pro index 8ab535a387..f2d9315902 100644 --- a/ui/nim-status-client.pro +++ b/ui/nim-status-client.pro @@ -156,6 +156,7 @@ DISTFILES += \ app/AppLayouts/Chat/components/EmojiCategoryButton.qml \ app/AppLayouts/Chat/components/EmojiPopup.qml \ app/AppLayouts/Chat/components/EmojiReaction.qml \ + app/AppLayouts/Chat/components/LeftTabBottomButtons.qml \ app/AppLayouts/Chat/components/NoFriendsRectangle.qml \ app/AppLayouts/Chat/components/ProfilePopup.qml \ app/AppLayouts/Chat/components/EmojiSection.qml \ diff --git a/ui/shared/ImageLoader.qml b/ui/shared/ImageLoader.qml index 4ad546875b..4802aa59c9 100644 --- a/ui/shared/ImageLoader.qml +++ b/ui/shared/ImageLoader.qml @@ -5,6 +5,7 @@ import "../imports" Rectangle { id: root property bool noHover: false + property bool noMouseArea: false property alias source: image.source property alias fillMode: image.fillMode property bool showLoadingIndicator: true @@ -156,6 +157,7 @@ Rectangle { } } MouseArea { + enabled: !noMouseArea cursorShape: noHover ? Qt.ArrowCursor : Qt.PointingHandCursor anchors.fill: parent onClicked: { diff --git a/ui/shared/RoundedImage.qml b/ui/shared/RoundedImage.qml index f6453fc94a..967969e7ee 100644 --- a/ui/shared/RoundedImage.qml +++ b/ui/shared/RoundedImage.qml @@ -4,6 +4,7 @@ import QtGraphicalEffects 1.0 Rectangle { id: root signal clicked + property bool noMouseArea: false property bool noHover: false property alias showLoadingIndicator: imgStickerPackThumb.showLoadingIndicator property alias source: imgStickerPackThumb.source @@ -27,6 +28,7 @@ Rectangle { ImageLoader { id: imgStickerPackThumb + noMouseArea: root.noMouseArea noHover: root.noHover opacity: 1 smooth: false diff --git a/ui/shared/status/StatusIconTabButton.qml b/ui/shared/status/StatusIconTabButton.qml index b9b5a6ca13..2f9c0188f9 100644 --- a/ui/shared/status/StatusIconTabButton.qml +++ b/ui/shared/status/StatusIconTabButton.qml @@ -10,11 +10,25 @@ TabButton { visible: enabled width: 40 height: enabled ? 40 : 0 - anchors.topMargin: enabled ? 50 : 0 anchors.horizontalCenter: parent.horizontalCenter property color iconColor: Style.current.secondaryText property color disabledColor: iconColor 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.width: 24 @@ -26,35 +40,55 @@ TabButton { } onIconChanged: { + if (iconSource) { + icon.source = iconSource + return + } + icon.source = icon.name ? "../../app/img/" + icon.name + ".svg" : "" } contentItem: Item { anchors.fill: parent - SVGImage { - id: iconImg - visible: false - source: control.icon.source - height: control.icon.height - width: control.icon.width + Loader { + active: true anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter - fillMode: Image.PreserveAspectFit - rotation: control.iconRotation - } - ColorOverlay { - anchors.fill: iconImg - source: iconImg - color: control.icon.color - antialiasing: true - smooth: true - rotation: control.iconRotation + sourceComponent: !!iconSource ? imageIcon : defaultIcon } + Component { + id: defaultIcon + SVGImage { + id: iconImg + source: control.icon.source + height: control.icon.height + width: control.icon.width + fillMode: Image.PreserveAspectFit + rotation: control.iconRotation + ColorOverlay { + anchors.fill: iconImg + source: iconImg + color: control.icon.color + antialiasing: true + smooth: true + } + } + } + + Component { + id: imageIcon + RoundedImage { + source: iconSource + noMouseArea: true + } + } } 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 }