refactor(StatusAppNavBar): simplify navbar

- removed imperative filtering
- removed imperative size calculation
- removed all ugly hacks

fixes: #7167
fixes: #8463
This commit is contained in:
Patryk Osmaczko 2022-11-28 12:32:29 +01:00 committed by osmaczko
parent 87d51ab039
commit 5d305a5221
5 changed files with 245 additions and 281 deletions

View File

@ -13,7 +13,6 @@ mainWindow_ScrollView_2 = {"container": statusDesktop_mainWindow, "occurrence":
mainWindow_ProfileNavBarButton = {"container": statusDesktop_mainWindow, "objectName": "statusProfileNavBarTabButton", "type": "StatusNavBarTabButton", "visible": True}
settings_navbar_settings_icon_StatusIcon = {"container": mainWindow_navBarListView_ListView, "objectName": "settings-icon", "type": "StatusIcon", "visible": True}
splashScreen = {"container": statusDesktop_mainWindow, "objectName": "splashScreen", "type": "SplashScreen"}
navBarListView_Chat_navbar_StatusNavBarTabButton = {"checkable": True, "container": mainWindow_navBarListView_ListView, "objectName": "Chat-navbar", "type": "StatusNavBarTabButton", "visible": True}
mainWindow_StatusToolBar = {"container": statusDesktop_mainWindow, "objectName": "statusToolBar", "type": "StatusToolBar", "visible": True}
main_toolBar_back_button = {"container": mainWindow_StatusToolBar, "objectName": "toolBarBackButton", "type": "StatusFlatButton", "visible": True}
mainWindow_emptyChatPanelImage = {"container": statusDesktop_mainWindow, "objectName": "emptyChatPanelImage", "type": "Image", "visible": True}
@ -33,7 +32,8 @@ modal_Close_Button = {"container": statusDesktop_mainWindow_overlay, "objectName
delete_Channel_ConfirmationDialog_DeleteButton = {"container": statusDesktop_mainWindow_overlay, "objectName": "deleteChatConfirmationDialogDeleteButton", "type": "StatusButton"}
# Main Window - chat related:
navBarListView_Chat_navbar_StatusNavBarTabButton = {"checkable": True, "container": mainWindow_navBarListView_ListView, "objectName": "Chat-navbar", "type": "StatusNavBarTabButton", "visible": True}
mainWindow_statusChatNavBarListView_ListView = {"container": statusDesktop_mainWindow, "objectName": "statusChatNavBarListView", "type": "ListView", "visible": True}
navBarListView_Chat_navbar_StatusNavBarTabButton = {"checkable": True, "container": mainWindow_statusChatNavBarListView_ListView, "objectName": "Chat-navbar", "type": "StatusNavBarTabButton", "visible": True}
mainWindow_public_chat_icon_StatusIcon = {"container": statusDesktop_mainWindow, "objectName": "public-chat-icon", "source": "qrc:/StatusQ/src/assets/img/icons/public-chat.svg", "type": "StatusIcon", "visible": True}
chatList_Repeater = {"container": statusDesktop_mainWindow, "objectName": "chatListItems", "type": "Repeater"}
chatList = {"container": statusDesktop_mainWindow, "objectName": "ContactsColumnView_chatList", "type": "StatusChatList"}
@ -44,7 +44,6 @@ chatView_StatusChatInfoButton = {"container": statusDesktop_mainWindow, "objectN
chatInfoButton_Pin_Text = {"container": chatView_StatusChatInfoButton, "objectName": "StatusChatInfo_pinText", "type": "StatusBaseText", "visible": True}
joinPublicChat_input = {"container": statusDesktop_mainWindow_overlay, "objectName": "joinPublicChannelInput", "type": "TextEdit", "visible": True}
startChat_Btn = {"container": statusDesktop_mainWindow_overlay, "objectName": "startChatButton", "type": "StatusButton"}
navBarListView_Chat_navbar_StatusNavBarTabButton = {"checkable": True, "container": mainWindow_navBarListView_ListView, "objectName": "Chat-navbar", "type": "StatusNavBarTabButton", "visible": True}
# My Profile Popup
ProfileHeader_userImage = {"container": statusDesktop_mainWindow_overlay, "objectName": "ProfileHeader_userImage", "type": "UserImage", "visible": True}

View File

@ -12,6 +12,8 @@ import StatusQ.Platform 0.1
import "demoapp"
import "demoapp/data" 1.0
import SortFilterProxyModel 0.2
Rectangle {
id: demoApp
height: 602
@ -74,65 +76,27 @@ Rectangle {
width: demoApp.width - demoApp.border.width * 2
leftPanel: StatusAppNavBar {
id: navBar
communityTypeRole: "sectionType"
communityTypeValue: appSectionType.community
sectionModel: Models.demoAppSectionsModel
property bool communityAdded: false
onAboutToUpdateFilteredRegularModel: {
communityAdded = false
}
filterRegularItem: function(item) {
if(item.sectionType === appSectionType.community)
if(communityAdded)
return false
else
communityAdded = true
return true
}
filterCommunityItem: function(item) {
return item.sectionType === appSectionType.community
}
regularNavBarButton: StatusNavBarTabButton {
anchors.horizontalCenter: parent.horizontalCenter
name: model.icon.length > 0? "" : model.name
icon.name: model.icon
icon.source: model.image
tooltip.text: model.name
autoExclusive: true
checked: model.active
badge.value: model.notificationsCount
badge.visible: model.hasNotification
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusBadge.borderColor
badge.border.width: 2
onClicked: {
if(model.sectionType === appSectionType.chat)
{
appView.sourceComponent = statusAppChatView
demoApp.setActiveItem(model.sectionId)
}
else if(model.sectionType === appSectionType.communitiesPortal)
{
appView.sourceComponent = statusCommunityPortalView
demoApp.setActiveItem(model.sectionId)
}
else if(model.sectionType === appSectionType.profileSettings)
{
appView.sourceComponent = statusAppProfileSettingsView
demoApp.setActiveItem(model.sectionId)
}
chatItemsModel: SortFilterProxyModel {
sourceModel: Models.demoAppSectionsModel
filters: ValueFilter {
roleName: "sectionType"
value: appSectionType.chat
}
}
communityNavBarButton: StatusNavBarTabButton {
chatItemDelegate: navButtonComponent
communityItemsModel: SortFilterProxyModel {
sourceModel: Models.demoAppSectionsModel
filters: ValueFilter {
roleName: "sectionType"
value: appSectionType.community
}
}
communityItemDelegate: StatusNavBarTabButton {
anchors.horizontalCenter: parent.horizontalCenter
name: model.icon.length > 0? "" : model.name
icon.name: model.icon
@ -179,6 +143,52 @@ Rectangle {
}
}
}
regularItemsModel: SortFilterProxyModel {
sourceModel: Models.demoAppSectionsModel
filters: RangeFilter {
roleName: "sectionType"
minimumValue: appSectionType.communitiesPortal
maximumValue: appSectionType.demoApp
}
}
regularItemDelegate: navButtonComponent
delegateHeight: 40
Component {
id: navButtonComponent
StatusNavBarTabButton {
anchors.horizontalCenter: parent.horizontalCenter
name: model.icon.length > 0? "" : model.name
icon.name: model.icon
icon.source: model.image
tooltip.text: model.name
autoExclusive: true
checked: model.active
badge.value: model.notificationsCount
badge.visible: model.hasNotification
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusBadge.borderColor
badge.border.width: 2
onClicked: {
if(model.sectionType === appSectionType.chat)
{
appView.sourceComponent = statusAppChatView
demoApp.setActiveItem(model.sectionId)
}
else if(model.sectionType === appSectionType.communitiesPortal)
{
appView.sourceComponent = statusCommunityPortalView
demoApp.setActiveItem(model.sectionId)
}
else if(model.sectionType === appSectionType.profileSettings)
{
appView.sourceComponent = statusAppProfileSettingsView
demoApp.setActiveItem(model.sectionId)
}
}
}
}
}
rightPanel: Loader {

View File

@ -70,11 +70,8 @@ StatusWindow {
leftPanel: StatusAppNavBar {
height: rootWindow.height
communityTypeRole: "sectionType"
communityTypeValue: appSectionType.community
sectionModel: Models.mainAppSectionsModel
regularNavBarButton: StatusNavBarTabButton {
regularItemsModel: Models.mainAppSectionsModel
regularItemDelegate: StatusNavBarTabButton {
anchors.horizontalCenter: parent.horizontalCenter
name: model.icon.length > 0? "" : model.name
icon.name: model.icon
@ -103,6 +100,7 @@ StatusWindow {
rootWindow.setActiveItem(model.sectionId)
}
}
delegateHeight: 40
}
rightPanel: Item {

View File

@ -1,8 +1,5 @@
import QtQuick 2.13
import QtQuick.Layouts 1.13
import QtQuick.Controls 2.13
import QtQml.Models 2.13
import Qt.labs.qmlmodels 1.0
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
@ -10,186 +7,129 @@ import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
Rectangle {
id: statusAppNavBar
id: root
property alias chatItemsModel: chatItemsListView.model
property alias chatItemDelegate: chatItemsListView.delegate
property alias communityItemsModel: communityItemsListView.model
property alias communityItemDelegate: communityItemsListView.delegate
property alias regularItemsModel: regularItemsListView.model
property alias regularItemDelegate: regularItemsListView.delegate
property real delegateHeight
property alias cameraComponent: cameraItemLoader.sourceComponent
property alias profileComponent: profileItemLoader.sourceComponent
implicitWidth: 78
implicitHeight: layout.implicitHeight
width: 78
implicitHeight: 600
color: Theme.palette.statusAppNavBar.backgroundColor
property var sectionModel: []
property string communityTypeRole: ""
property int communityTypeValue: -1
property int navBarButtonSpacing: 12
QtObject {
id: d
property StatusNavBarTabButton navBarCameraButton
property StatusNavBarTabButton navBarProfileButton
property Component regularNavBarButton
property Component communityNavBarButton
readonly property real spacing: 12
readonly property real separatorWidth: 30
property var filterRegularItem: function(item) { return true; }
property var filterCommunityItem: function(item) { return true; }
signal aboutToUpdateFilteredRegularModel()
signal aboutToUpdateFilteredCommunityModel()
onNavBarProfileButtonChanged: {
if (!!navBarProfileButton) {
navBarProfileButton.parent = navBarProfileButtonSlot
function implicitListViewHeight(listView) {
return listView.count ? listView.count * root.delegateHeight + (listView.count - 1) * listView.spacing : 0
}
}
onNavBarCameraButtonChanged: {
if (!!navBarCameraButton) {
navBarCameraButton.parent = navBarCameraButtonSlot
}
ColumnLayout {
id: layout
anchors {
fill: parent
topMargin: 48
bottomMargin: 24
}
function triggerUpdate(){
navBarModel.update()
}
StatusAppNavBarFilterModel {
id: navBarModel
filterAcceptsItem: filterRegularItem
model: statusAppNavBar.sectionModel
onAboutToUpdateFilteredModel: {
statusAppNavBar.aboutToUpdateFilteredRegularModel()
}
DelegateChooser {
id: delegateChooser
role: communityTypeRole
DelegateChoice { roleValue: communityTypeValue; delegate: communityNavButton }
DelegateChoice { delegate: regularNavBarButton }
}
delegate: delegateChooser
}
Component {
id: communityNavButton
Item {
width: parent.width
height: (necessaryHightForCommunities > maxHightForCommunities)?
maxHightForCommunities : necessaryHightForCommunities
property int communityNavBarButtonHeight: 40
property int maxHightForCommunities: {
let numOfOtherThanCommunityBtns = navBarListView.model.count - 1
let numOfSpacingsForNavBar = navBarListView.model.count - 1
return navBarListView.height -
numOfOtherThanCommunityBtns * communityNavBarButtonHeight -
numOfSpacingsForNavBar * navBarButtonSpacing
}
property int necessaryHightForCommunities: {
let numOfSpacingsForCommunities = communityListView.model.count - 1
return communityListView.model.count * communityNavBarButtonHeight +
numOfSpacingsForCommunities * navBarButtonSpacing +
separatorBottom.height
}
StatusAppNavBarFilterModel {
id: navBarCommunityModel
filterAcceptsItem: filterCommunityItem
model: statusAppNavBar.sectionModel
delegate: communityNavBarButton
onAboutToUpdateFilteredModel: {
statusAppNavBar.aboutToUpdateFilteredCommunityModel()
}
}
Item {
id: separatorTop
width: parent.width
height: navBarButtonSpacing
anchors.top: parent.top
visible: parent.necessaryHightForCommunities > parent.maxHightForCommunities
Rectangle {
height: 1
width: 30
color: Theme.palette.directColor7
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
}
}
spacing: d.spacing
ListView {
id: communityListView
anchors.left: parent.left
anchors.right: parent.right
anchors.top: separatorTop.visible? separatorTop.bottom : parent.top
anchors.bottom: separatorBottom.top
id: chatItemsListView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: root.delegateHeight
Layout.preferredHeight: d.implicitListViewHeight(this)
Layout.maximumHeight: Layout.preferredHeight
objectName: "statusChatNavBarListView"
visible: count
clip: true
spacing: d.spacing
boundsBehavior: contentHeight > height ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
spacing: navBarButtonSpacing
model: navBarCommunityModel
}
Item {
id: separatorBottom
width: parent.width
height: navBarButtonSpacing
anchors.bottom: parent.bottom
Rectangle {
height: 1
width: 30
id: firstSectionSeparator
implicitHeight: 1
Layout.preferredWidth: d.separatorWidth
Layout.alignment: Qt.AlignHCenter
color: Theme.palette.directColor7
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
visible: chatItemsListView.count && communityItemsListView.contentHeight > communityItemsListView.height
}
ListView {
id: navBarListView
id: communityItemsListView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: root.delegateHeight
Layout.preferredHeight: d.implicitListViewHeight(this)
Layout.maximumHeight: Layout.preferredHeight
visible: count
clip: true
spacing: d.spacing
boundsBehavior: contentHeight > height ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
}
Rectangle {
id: secondSectionSeparator
implicitHeight: 1
Layout.preferredWidth: d.separatorWidth
Layout.alignment: Qt.AlignHCenter
color: Theme.palette.directColor7
visible: chatItemsListView.count || communityItemsListView.count
}
ListView {
id: regularItemsListView
Layout.fillWidth: true
Layout.preferredHeight: d.implicitListViewHeight(this)
objectName: "statusMainNavBarListView"
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 48
anchors.bottom: navBarProfileButtonSlot.top
anchors.bottomMargin: navBarButtonSpacing
spacing: navBarButtonSpacing
boundsBehavior: Flickable.StopAtBounds
model: navBarModel
visible: count
clip: true
spacing: d.spacing
boundsBehavior: contentHeight > height ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
}
Item {
id: navBarCameraButtonSlot
anchors.horizontalCenter: parent.horizontalCenter
height: visible? statusAppNavBar.navBarProfileButton.height : 0
width: visible? statusAppNavBar.navBarProfileButton.width : 0
visible: !!statusAppNavBar.navBarCameraButton
anchors.bottom: navBarProfileButtonSlot.visible ? navBarProfileButtonSlot.top : parent.bottom
anchors.bottomMargin: visible ? 12 : 0
Layout.fillWidth: true
Layout.fillHeight: true
}
Loader {
id: cameraItemLoader
Layout.alignment: Qt.AlignHCenter
}
Item {
id: navBarProfileButtonSlot
anchors.horizontalCenter: parent.horizontalCenter
height: visible? statusAppNavBar.navBarProfileButton.height : 0
width: visible? statusAppNavBar.navBarProfileButton.width : 0
visible: !!statusAppNavBar.navBarProfileButton
anchors.bottom: parent.bottom
anchors.bottomMargin: visible ? 24 : 0
Loader {
id: profileItemLoader
Layout.alignment: Qt.AlignHCenter
}
}
}

View File

@ -34,9 +34,10 @@ import StatusQ.Popups.Dialog 0.1
import StatusQ.Core 0.1
import AppLayouts.Browser.stores 1.0 as BrowserStores
import AppLayouts.stores 1.0
import SortFilterProxyModel 0.2
import "popups"
import "panels"
import "activitycenter/popups"
@ -320,58 +321,35 @@ Item {
anchors.fill: parent
leftPanel: StatusAppNavBar {
communityTypeRole: "sectionType"
communityTypeValue: Constants.appSection.community
sectionModel: appMain.rootStore.mainModuleInst.sectionsModel
Component.onCompleted: {
appMain.rootStore.mainModuleInst.sectionsModel.sectionVisibilityUpdated.connect(function(){
triggerUpdate()
})
chatItemsModel: SortFilterProxyModel {
sourceModel: appMain.rootStore.mainModuleInst.sectionsModel
filters: [
ValueFilter {
roleName: "sectionType"
value: Constants.appSection.chat
},
ValueFilter {
roleName: "enabled"
value: true
}
property bool communityAdded: false
onAboutToUpdateFilteredRegularModel: {
communityAdded = false
]
}
chatItemDelegate: navbarButton
filterRegularItem: function(item) {
if(!item.enabled)
return false
if(item.sectionType === Constants.appSection.community)
if(communityAdded)
return false
else
communityAdded = true
return true
communityItemsModel: SortFilterProxyModel {
sourceModel: appMain.rootStore.mainModuleInst.sectionsModel
filters: [
ValueFilter {
roleName: "sectionType"
value: Constants.appSection.community
},
ValueFilter {
roleName: "enabled"
value: true
}
filterCommunityItem: function(item) {
return item.sectionType === Constants.appSection.community
]
}
regularNavBarButton: StatusNavBarTabButton {
id: navbar
objectName: model.name + "-navbar"
anchors.horizontalCenter: parent.horizontalCenter
name: model.icon.length > 0? "" : model.name
icon.name: model.icon
icon.source: model.image
tooltip.text: model.name
checked: model.active
badge.value: model.notificationsCount
badge.visible: model.hasNotification
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusBadge.borderColor
badge.border.width: 2
onClicked: {
changeAppSectionBySectionId(model.id)
}
}
communityNavBarButton: StatusNavBarTabButton {
communityItemDelegate: StatusNavBarTabButton {
objectName: "CommunityNavBarButton"
anchors.horizontalCenter: parent.horizontalCenter
name: model.icon.length > 0? "" : model.name
@ -433,15 +411,33 @@ Item {
}
}
navBarProfileButton: StatusNavBarTabButton {
regularItemsModel: SortFilterProxyModel {
sourceModel: appMain.rootStore.mainModuleInst.sectionsModel
filters: [
RangeFilter {
roleName: "sectionType"
minimumValue: Constants.appSection.wallet
maximumValue: Constants.appSection.communitiesPortal
},
ValueFilter {
roleName: "enabled"
value: true
}
]
}
regularItemDelegate: navbarButton
delegateHeight: 40
profileComponent: StatusNavBarTabButton {
id: profileButton
objectName: "statusProfileNavBarTabButton"
property bool opened: false
name: appMain.rootStore.userProfileInst.name
icon.source: appMain.rootStore.userProfileInst.icon
width: 32
height: 32
implicitWidth: 32
implicitHeight: 32
identicon.asset.width: width
identicon.asset.height: height
identicon.asset.charactersLen: 2
@ -481,6 +477,27 @@ Item {
store: appMain.rootStore
}
}
Component {
id: navbarButton
StatusNavBarTabButton {
id: navbar
objectName: model.name + "-navbar"
anchors.horizontalCenter: parent.horizontalCenter
name: model.icon.length > 0? "" : model.name
icon.name: model.icon
icon.source: model.image
tooltip.text: model.name
checked: model.active
badge.value: model.notificationsCount
badge.visible: model.hasNotification
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusBadge.borderColor
badge.border.width: 2
onClicked: {
changeAppSectionBySectionId(model.id)
}
}
}
}
rightPanel: ColumnLayout {