feat(StatusQ/Layout)!: Cleaning up Layouts for consistency (#836)

- Created StatusMainLayout to be used as the apps' main
  layout
- Created StatusSectionLayout to be used for all sections as
  their base
  - Created StatusToolBar as part of StatusAppLayout with
    standard component the ActivityButton and posibility to
    add custom implementation components

Needed for https://github.com/status-im/status-desktop/issues/6635
This commit is contained in:
Alexandra Betouni 2022-09-02 10:25:43 +03:00 committed by Michał Cieślak
parent 4f723b4278
commit 5d3bd00cd8
17 changed files with 689 additions and 641 deletions

View File

@ -63,7 +63,7 @@ Rectangle {
visible: titleStyle === "windows"
}
StatusAppLayout {
StatusMainLayout {
id: statusAppLayout
anchors.top: windowsTitle.visible ? windowsTitle.bottom : demoApp.top
anchors.left: demoApp.left
@ -73,7 +73,7 @@ Rectangle {
height: demoApp.height - demoApp.border.width * 2
width: demoApp.width - demoApp.border.width * 2
appNavBar: StatusAppNavBar {
leftPanel: StatusAppNavBar {
id: navBar
@ -181,7 +181,7 @@ Rectangle {
}
}
appView: Loader {
rightPanel: Loader {
id: appView
anchors.fill: parent
sourceComponent: statusAppChatView

View File

@ -12,93 +12,73 @@ import StatusQ.Popups 0.1
Column {
spacing: 10
StatusChatToolBar {
toolbarComponent: chatInfoButton1
StatusToolBar {
width: 518
Component {
id: chatInfoButton1
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
}
headerContent: StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
}
}
StatusChatToolBar {
toolbarComponent: chatInfoButton2
StatusToolBar {
width: 518
Component {
id: chatInfoButton2
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.PublicChat
pinnedMessagesCount: 1
muted: true
}
headerContent: StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.PublicChat
pinnedMessagesCount: 1
muted: true
}
}
StatusChatToolBar {
StatusToolBar {
notificationCount: 1
toolbarComponent: chatInfoButton3
width: 518
Component {
id: chatInfoButton3
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
pinnedMessagesCount: 1
}
headerContent: StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
pinnedMessagesCount: 1
}
}
StatusChatToolBar {
StatusToolBar {
notificationCount: 1
toolbarComponent: tagSelector
width: 518
Component {
id: tagSelector
StatusTagSelector {
namesModel: ListModel {
ListElement {
publicId: "0x0"
name: "Maria"
icon: ""
isIdenticon: false
onlineStatus: 3
isReadonly: true
tagIcon: "crown"
}
ListElement {
publicId: "0x1"
name: "James"
icon: ""
isIdenticon: false
onlineStatus: 1
isReadonly: false
tagIcon: ""
}
StatusTagSelector {
namesModel: ListModel {
ListElement {
publicId: "0x0"
name: "Maria"
icon: ""
isIdenticon: false
onlineStatus: 3
isReadonly: true
tagIcon: "crown"
}
ListElement {
publicId: "0x1"
name: "James"
icon: ""
isIdenticon: false
onlineStatus: 1
isReadonly: false
tagIcon: ""
}
toLabelText: qsTr("To: ")
warningText: qsTr("USER LIMIT REACHED")
}
toLabelText: qsTr("To: ")
warningText: qsTr("USER LIMIT REACHED")
}
}

View File

@ -10,10 +10,113 @@ import StatusQ.Core.Theme 0.1
import "data" 1.0
StatusAppThreePanelLayout {
StatusSectionLayout {
id: root
property bool createChat: false
notificationCount: 1
onNotificationButtonClicked: { notificationCount = 0; }
showHeader: !root.createChat
headerContent: RowLayout {
id: chatHeader
signal chatInfoButtonClicked()
signal menuButtonClicked()
signal membersButtonClicked()
signal searchButtonClicked()
StatusChatInfoButton {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: padding
title: "Amazing Funny Squirrel"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
pinnedMessagesCount: 1
}
RowLayout {
id: actionButtons
Layout.alignment: Qt.AlignRight
Layout.rightMargin: padding
spacing: 8
StatusFlatRoundButton {
id: menuButton
objectName: "chatToolbarMoreOptionsButton"
width: 32
height: 32
icon.name: "more"
type: StatusFlatRoundButton.Type.Secondary
// initializing the tooltip
tooltip.visible: !!tooltip.text && menuButton.hovered && !contextMenu.open
tooltip.text: qsTr("More")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
property bool showMoreMenu: false
onClicked: {
menuButton.highlighted = true
let originalOpenHandler = contextMenu.openHandler
let originalCloseHandler = contextMenu.closeHandler
contextMenu.openHandler = function () {
if (!!originalOpenHandler) {
originalOpenHandler()
}
}
contextMenu.closeHandler = function () {
menuButton.highlighted = false
if (!!originalCloseHandler) {
originalCloseHandler()
}
}
contextMenu.openHandler = originalOpenHandler
contextMenu.popup(-contextMenu.width + menuButton.width, menuButton.height + 4)
}
StatusPopupMenu {
id: contextMenu
StatusMenuItem {
text: "Mute Chat"
icon.name: "notification"
}
StatusMenuItem {
text: "Mark as Read"
icon.name: "checkmark-circle"
}
StatusMenuItem {
text: "Clear History"
icon.name: "close-circle"
}
StatusMenuSeparator {}
StatusMenuItem {
text: "Leave Chat"
icon.name: "arrow-left"
type: StatusMenuItem.Type.Danger
}
}
}
Rectangle {
width: 1
height: 24
color: Theme.palette.directColor7
Layout.alignment: Qt.AlignVCenter
visible: (notificationButton.visible && menuButton.visible)
}
}
}
leftPanel: Item {
anchors.fill: parent
anchors.margins: 16
@ -166,56 +269,4 @@ StatusAppThreePanelLayout {
}
}
}
rightPanel: Item {
anchors.fill: parent
StatusChatToolBar {
width: parent.width
toolbarComponent: statusChatInfoButton
searchButton.visible: false
membersButton.visible: false
notificationCount: 1
onNotificationButtonClicked: notificationCount = 0
popupMenu: StatusPopupMenu {
id: contextMenu
StatusMenuItem {
text: "Mute Chat"
icon.name: "notification"
}
StatusMenuItem {
text: "Mark as Read"
icon.name: "checkmark-circle"
}
StatusMenuItem {
text: "Clear History"
icon.name: "close-circle"
}
StatusMenuSeparator {}
StatusMenuItem {
text: "Leave Chat"
icon.name: "arrow-left"
type: StatusMenuItem.Type.Danger
}
}
Component {
id: statusChatInfoButton
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Amazing Funny Squirrel"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
pinnedMessagesCount: 1
}
}
}
}
}

View File

@ -5,12 +5,12 @@ import QtQuick.Layouts 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Layout 0.1
import StatusQ.Components 0.1
import "../demoapp/data" 1.0
StatusScrollView {
StatusSectionLayout {
id: root
QtObject {
@ -31,124 +31,129 @@ StatusScrollView {
console.info("Clicked community ID: " + communityId)
}
}
centerPanel: Item {
anchors.fill: parent
clip: true
StatusScrollView {
anchors.fill: parent
contentHeight: column.height + d.layoutVMargin
contentWidth: column.width + d.layoutHMargin
contentHeight: column.height + d.layoutVMargin
contentWidth: column.width + d.layoutHMargin
clip: true
ColumnLayout {
id: column
spacing: 18
ColumnLayout {
id: column
spacing: 18
StatusBaseText {
Layout.topMargin: d.layoutVMargin
Layout.leftMargin: d.layoutHMargin
text: qsTr("Find community")
font.weight: Font.Bold
font.pixelSize: d.titlePixelSize
color: Theme.palette.directColor1
}
// Tags definition - Now hidden - Out of scope
// TODO: Replace by `StatusListItemTagRow`
Row {
visible: d.tagsModel.count > 0
Layout.leftMargin: d.layoutHMargin
Layout.rightMargin: d.layoutHMargin
width: 1234 // by design
spacing: d.stylePadding/2
Repeater {
model: d.tagsModel
delegate: StatusListItemTag {
border.color: Theme.palette.baseColor2
color: "transparent"
height: 32
radius: 36
closeButtonVisible: false
icon.emoji: model.emoji
icon.height: 32
icon.width: icon.height
icon.color: "transparent"
icon.isLetterIdenticon: true
title: model.name
titleText.font.pixelSize: 15
titleText.color: Theme.palette.primaryColor1
StatusBaseText {
Layout.topMargin: d.layoutVMargin
Layout.leftMargin: d.layoutHMargin
text: qsTr("Find community")
font.weight: Font.Bold
font.pixelSize: d.titlePixelSize
color: Theme.palette.directColor1
}
}
}
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Featured")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
// Tags definition - Now hidden - Out of scope
// TODO: Replace by `StatusListItemTagRow`
Row {
visible: d.tagsModel.count > 0
Layout.leftMargin: d.layoutHMargin
Layout.rightMargin: d.layoutHMargin
width: 1234 // by design
spacing: d.stylePadding/2
GridLayout {
id: featuredGrid
Layout.leftMargin: d.layoutHMargin
columns: 3
columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
Repeater {
model: d.featuredCommunitiesModel
delegate: StatusCommunityCard {
locale: "es"
communityId: model.communityId
loaded: model.available
logo: model.logo
name: model.name
description: model.description
members: model.members
popularity: model.popularity
communityColor: model.communityColor
categories: ListModel {
ListElement { name: "sport"; emoji: "🎾"}
ListElement { name: "food"; emoji: "🥑"}
ListElement { name: "privacy"; emoji: "👻"}
Repeater {
model: d.tagsModel
delegate: StatusListItemTag {
border.color: Theme.palette.baseColor2
color: "transparent"
height: 32
radius: 36
closeButtonVisible: false
icon.emoji: model.emoji
icon.height: 32
icon.width: icon.height
icon.color: "transparent"
icon.isLetterIdenticon: true
title: model.name
titleText.font.pixelSize: 15
titleText.color: Theme.palette.primaryColor1
}
}
onClicked: { d.navigateToCommunity(communityId) }
}
}
}
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Popular")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Featured")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
GridLayout {
Layout.leftMargin: d.layoutHMargin
columns: 3
columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
GridLayout {
id: featuredGrid
Layout.leftMargin: d.layoutHMargin
columns: 3
columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
Repeater {
model: d.popularCommunitiesModel
delegate: StatusCommunityCard {
locale: "es"
communityId: model.communityId
loaded: model.available
logo: model.logo
name: model.name
description: model.description
members: model.members
activeUsers: model.activeUsers
popularity: model.popularity
tokenLogo: model.tokenLogo
isPrivate: model.isPrivate
banner: model.banner
Repeater {
model: d.featuredCommunitiesModel
delegate: StatusCommunityCard {
locale: "es"
communityId: model.communityId
loaded: model.available
logo: model.logo
name: model.name
description: model.description
members: model.members
popularity: model.popularity
communityColor: model.communityColor
categories: ListModel {
ListElement { name: "sport"; emoji: "🎾"}
ListElement { name: "food"; emoji: "🥑"}
ListElement { name: "privacy"; emoji: "👻"}
}
onClicked: { d.navigateToCommunity(communityId) }
onClicked: { d.navigateToCommunity(communityId) }
}
}
}
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Popular")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
GridLayout {
Layout.leftMargin: d.layoutHMargin
columns: 3
columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
Repeater {
model: d.popularCommunitiesModel
delegate: StatusCommunityCard {
locale: "es"
communityId: model.communityId
loaded: model.available
logo: model.logo
name: model.name
description: model.description
members: model.members
activeUsers: model.activeUsers
popularity: model.popularity
tokenLogo: model.tokenLogo
isPrivate: model.isPrivate
banner: model.banner
onClicked: { d.navigateToCommunity(communityId) }
}
}
}
}
}

View File

@ -1,5 +1,6 @@
import QtQuick 2.12
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.12
import StatusQ.Core 0.1
import StatusQ.Popups 0.1
@ -10,7 +11,7 @@ import StatusQ.Core.Theme 0.1
import "data" 1.0
StatusAppThreePanelLayout {
StatusSectionLayout {
id: root
property string communityDetailModalTitle: ""
@ -22,6 +23,101 @@ StatusAppThreePanelLayout {
color: SplitHandle.pressed ? Theme.palette.baseColor2
: (SplitHandle.hovered ? Qt.darker(Theme.palette.baseColor5, 1.1) : "transparent")
}
headerContent: RowLayout {
id: statusToolBar
StatusFlatRoundButton {
id: searchButton
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: padding
icon.name: "search"
type: StatusFlatRoundButton.Type.Secondary
// initializing the tooltip
tooltip.text: qsTr("Search")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
onClicked: {
searchButton.highlighted = !searchButton.highlighted;
searchPopup.setSearchSelection(communityDetailModalTitle,
"",
communityDetailModalImage);
searchPopup.open();
}
}
StatusChatInfoButton {
Layout.preferredWidth: Math.min(implicitWidth, parent.width)
Layout.fillHeight: true
title: "general"
subTitle: "Community Chat"
icon.color: Theme.palette.miscColor6
type: StatusChatInfoButton.Type.CommunityChat
}
Item {
Layout.fillWidth: true
}
StatusFlatRoundButton {
id: membersButton
icon.name: "group-chat"
type: StatusFlatRoundButton.Type.Secondary
// initializing the tooltip
tooltip.text: qsTr("Members")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
onClicked: {
membersButton.highlighted = !membersButton.highlighted;
root.showRightPanel = !root.showRightPanel;
}
}
StatusSearchPopup {
id: searchPopup
searchOptionsPopupMenu: searchPopupMenu
onAboutToHide: {
if (searchPopupMenu.visible) {
searchPopupMenu.close();
}
//clear menu
for (var i = 2; i < searchPopupMenu.count; i++) {
searchPopupMenu.removeItem(searchPopupMenu.takeItem(i));
}
}
onClosed: {
statusToolBar.searchButton.highlighted = false
searchPopupMenu.dismiss();
}
onSearchTextChanged: {
if (searchPopup.searchText !== "") {
searchPopup.loading = true;
searchModelSimTimer.start();
} else {
searchPopup.searchResults = [];
searchModelSimTimer.stop();
}
}
Timer {
id: searchModelSimTimer
interval: 500
onTriggered: {
if (searchPopup.searchText.startsWith("c")) {
searchPopup.searchResults = Models.searchResultsA;
} else {
searchPopup.searchResults = Models.searchResultsB;
}
searchPopup.loading = false;
}
}
}
StatusSearchLocationMenu {
id: searchPopupMenu
searchPopup: searchPopup
locationModel: Models.optionsModel
}
}
leftPanel: Item {
id: leftPanel
@ -164,79 +260,12 @@ StatusAppThreePanelLayout {
}
centerPanel: Item {
StatusChatToolBar {
id: statusChatToolBar
width: parent.width
toolbarComponent: statusChatInfoButton
onSearchButtonClicked: {
searchButton.highlighted = !searchButton.highlighted;
searchPopup.setSearchSelection(communityDetailModalTitle,
"",
communityDetailModalImage);
searchPopup.open();
}
membersButton.onClicked: membersButton.highlighted = !membersButton.highlighted
onMembersButtonClicked: {
root.showRightPanel = !root.showRightPanel;
}
Component {
id: statusChatInfoButton
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "general"
subTitle: "Community Chat"
icon.color: Theme.palette.miscColor6
type: StatusChatInfoButton.Type.CommunityChat
}
}
}
StatusSearchPopup {
id: searchPopup
searchOptionsPopupMenu: searchPopupMenu
onAboutToHide: {
if (searchPopupMenu.visible) {
searchPopupMenu.close();
}
//clear menu
for (var i = 2; i < searchPopupMenu.count; i++) {
searchPopupMenu.removeItem(searchPopupMenu.takeItem(i));
}
}
onClosed: {
statusChatToolBar.searchButton.highlighted = false
searchPopupMenu.dismiss();
}
onSearchTextChanged: {
if (searchPopup.searchText !== "") {
searchPopup.loading = true;
searchModelSimTimer.start();
} else {
searchPopup.searchResults = [];
searchModelSimTimer.stop();
}
}
Timer {
id: searchModelSimTimer
interval: 500
onTriggered: {
if (searchPopup.searchText.startsWith("c")) {
searchPopup.searchResults = Models.searchResultsA;
} else {
searchPopup.searchResults = Models.searchResultsB;
}
searchPopup.loading = false;
}
}
}
StatusSearchLocationMenu {
id: searchPopupMenu
searchPopup: searchPopup
locationModel: Models.optionsModel
anchors.fill: parent
StatusBaseText {
id: titleText
anchors.centerIn: parent
font.pixelSize: 15
text: qsTr("Community content here")
}
}

View File

@ -8,7 +8,7 @@ import StatusQ.Core.Theme 0.1
import "data" 1.0
StatusAppTwoPanelLayout {
StatusSectionLayout {
id: root
leftPanel: Item {

View File

@ -63,11 +63,11 @@ StatusWindow {
}
}
StatusAppLayout {
StatusMainLayout {
id: appLayout
anchors.fill: parent
appNavBar: StatusAppNavBar {
leftPanel: StatusAppNavBar {
height: rootWindow.height
communityTypeRole: "sectionType"
@ -105,30 +105,34 @@ StatusWindow {
}
}
appView: StackView {
id: stackView
rightPanel: Item {
anchors.fill: parent
initialItem: libraryDocumentationCmp
}
ThemeSwitch {
anchors.top: parent.top
anchors.topMargin: 32
anchors.right: parent.right
anchors.rightMargin: 32
lightThemeEnabled: storeSettings.lightTheme
onLightThemeEnabledChanged: {
Theme.palette = lightThemeEnabled ? rootWindow.darkTheme : rootWindow.lightTheme
storeSettings.lightTheme = lightThemeEnabled
StackView {
id: stackView
anchors.fill: parent
initialItem: libraryDocumentationCmp
}
ThemeSwitch {
anchors.top: parent.top
anchors.topMargin: 32
anchors.right: parent.right
anchors.rightMargin: 32
lightThemeEnabled: storeSettings.lightTheme
onLightThemeEnabledChanged: {
Theme.palette = lightThemeEnabled ? rootWindow.darkTheme : rootWindow.lightTheme
storeSettings.lightTheme = lightThemeEnabled
}
}
}
}
Component {
id: libraryDocumentationCmp
StatusAppTwoPanelLayout {
StatusSectionLayout {
id: mainPageView
showHeader: false
function page(name, fillPage) {
storeSettings.fillPage = fillPage ? true : false
@ -343,8 +347,8 @@ StatusWindow {
}
}
rightPanel: Item {
id: rightPanel
centerPanel: Item {
id: centerPanel
anchors.fill: parent
StatusScrollView {
@ -357,7 +361,7 @@ StatusWindow {
Item {
id: pageWrapper
width: rightPanel.width
width: centerPanel.width
anchors.top: parent.top
height: Math.max(rootWindow.height, viewLoader.height + 128)
scale: rootWindow.factor
@ -415,8 +419,9 @@ StatusWindow {
Component {
id: examplesCmp
StatusAppTwoPanelLayout {
StatusSectionLayout {
id: examplesView
showHeader: false
function example(name) {
examplesLoader.source = Qt.resolvedUrl("./examples/" + name + ".qml")
@ -444,16 +449,19 @@ StatusWindow {
}
}
rightPanel: StatusScrollView {
id: examplesRightPanel
centerPanel: Item {
anchors.fill: parent
anchors.margins: 64
anchors.topMargin: anchors.margins + 32
StatusScrollView {
id: examplesCenterPanel
anchors.fill: parent
anchors.margins: 64
anchors.topMargin: anchors.margins + 32
Loader {
id: examplesLoader
width: examplesRightPanel.availableWidth
source: storeSettings.selectedExample !== "" ? storeSettings.selectedExample : examplesView.defaultExampleSource
Loader {
id: examplesLoader
width: examplesCenterPanel.availableWidth
source: storeSettings.selectedExample !== "" ? storeSettings.selectedExample : examplesView.defaultExampleSource
}
}
}
}

View File

@ -1,149 +0,0 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
Item {
id: statusChatToolBar
property alias menuButton: menuButton
property alias notificationButton: notificationButton
property alias membersButton: membersButton
property alias searchButton: searchButton
property int padding: 8
property int notificationCount: 0
property Component popupMenu
property var toolbarComponent
signal chatInfoButtonClicked()
signal menuButtonClicked()
signal notificationButtonClicked()
signal membersButtonClicked()
signal searchButtonClicked()
implicitWidth: 518
implicitHeight: 60
onPopupMenuChanged: {
if (!!popupMenu) {
popupMenuSlot.sourceComponent = popupMenu
}
}
RowLayout {
width: parent.width
spacing: padding / 2
Loader {
id: loader
sourceComponent: statusChatToolBar.toolbarComponent
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
Layout.topMargin: padding
Layout.leftMargin: padding
}
RowLayout {
id: actionButtons
Layout.alignment: Qt.AlignTop | Qt.AlignRight
Layout.topMargin: padding
Layout.rightMargin: padding
spacing: 8
StatusFlatRoundButton {
id: searchButton
width: 32
height: 32
icon.name: "search"
type: StatusFlatRoundButton.Type.Secondary
onClicked: statusChatToolBar.searchButtonClicked()
// initializing the tooltip
tooltip.text: qsTr("Search")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
}
StatusFlatRoundButton {
id: membersButton
width: 32
height: 32
icon.name: "group-chat"
type: StatusFlatRoundButton.Type.Secondary
onClicked: statusChatToolBar.membersButtonClicked()
// initializing the tooltip
tooltip.text: qsTr("Members")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
}
StatusFlatRoundButton {
id: menuButton
objectName: "chatToolbarMoreOptionsButton"
width: 32
height: 32
icon.name: "more"
type: StatusFlatRoundButton.Type.Secondary
visible: !!statusChatToolBar.popupMenu
// initializing the tooltip
tooltip.visible: !!tooltip.text && menuButton.hovered && !popupMenuSlot.item.opened
tooltip.text: qsTr("More")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
property bool showMoreMenu: false
onClicked: {
menuButton.highlighted = true
let originalOpenHandler = popupMenuSlot.item.openHandler
let originalCloseHandler = popupMenuSlot.item.closeHandler
popupMenuSlot.item.openHandler = function () {
if (!!originalOpenHandler) {
originalOpenHandler()
}
}
popupMenuSlot.item.closeHandler = function () {
menuButton.highlighted = false
if (!!originalCloseHandler) {
originalCloseHandler()
}
}
popupMenuSlot.item.openHandler = originalOpenHandler
popupMenuSlot.item.popup(-popupMenuSlot.item.width + menuButton.width, menuButton.height + 4)
statusChatToolBar.menuButtonClicked()
}
Loader {
id: popupMenuSlot
active: !!statusChatToolBar.popupMenu
}
}
Rectangle {
height: 24
width: 1
color: Theme.palette.directColor7
Layout.alignment: Qt.AlignVCenter
visible: notificationButton.visible &&
(menuButton.visible || membersButton.visible || searchButton.visible)
}
StatusActivityCenterButton {
id: notificationButton
width: 32
height: width
unreadNotificationsCount: statusChatToolBar.notificationCount
onClicked: statusChatToolBar.notificationButtonClicked()
}
}
}
}

View File

@ -0,0 +1,44 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
ToolBar {
id: root
property int notificationCount: 0
property Item headerContent
property alias notificationButton: notificationButton
signal notificationButtonClicked()
implicitWidth: visible ? 518 : 0
implicitHeight: visible ? 60 : 0
padding: 8
background: null
RowLayout {
anchors.fill: parent
spacing: 0
Control {
id: headerContentItem
Layout.fillWidth: !!headerContent
Layout.fillHeight: !!headerContent
background: null
contentItem: (!!headerContent) ? headerContent : null
}
Item {
Layout.fillWidth: !headerContent
}
StatusActivityCenterButton {
id: notificationButton
unreadNotificationsCount: root.notificationCount
onClicked: root.notificationButtonClicked()
}
}
}

View File

@ -9,7 +9,7 @@ StatusChatListItem 0.1 StatusChatListItem.qml
StatusChatListCategory 0.1 StatusChatListCategory.qml
StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml
StatusChatListAndCategories 0.1 StatusChatListAndCategories.qml
StatusChatToolBar 0.1 StatusChatToolBar.qml
StatusToolBar 0.1 StatusToolBar.qml
StatusContactRequestsIndicatorListItem 0.1 StatusContactRequestsIndicatorListItem.qml
StatusEmoji 0.1 StatusEmoji.qml
StatusContactVerificationIcons 0.1 StatusContactVerificationIcons.qml

View File

@ -1,49 +0,0 @@
import QtQuick 2.13
import QtQuick.Layouts 1.13
import QtQuick.Controls 2.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
Rectangle {
id: statusAppLayout
implicitWidth: 900
implicitHeight: 600
color: Theme.palette.statusAppLayout.backgroundColor
property StatusAppNavBar appNavBar
property Item appView
onAppNavBarChanged: {
if (!!appNavBar) {
appNavBar.parent = appNavBarSlot
}
}
onAppViewChanged: {
if (!!appView) {
appView.parent = appViewSlot
}
}
Row {
id: rowLayout
spacing: 0
height: statusAppLayout.height
width: statusAppLayout.width
Item {
id: appNavBarSlot
height: statusAppLayout.height
width: 78
}
Item {
id: appViewSlot
height: statusAppLayout.height
width: statusAppLayout.width - appNavBarSlot.width
}
}
}

View File

@ -1,54 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import StatusQ.Core.Theme 0.1
SplitView {
id: root
implicitWidth: 822
implicitHeight: 600
handle: Item { }
property Item leftPanel
property Item centerPanel
property Component rightPanel
property bool showRightPanel
Control {
SplitView.minimumWidth: 300
SplitView.preferredWidth: 300
SplitView.fillHeight: true
contentItem: (!!leftPanel) ? leftPanel : null
background: Rectangle {
anchors.fill: parent
color: Theme.palette.baseColor4
}
}
Control {
SplitView.minimumWidth: 300
SplitView.fillWidth: true
SplitView.fillHeight: true
leftPadding: -5
contentItem: (!!centerPanel) ? centerPanel : null
background: Rectangle {
anchors.fill: parent
color: Theme.palette.statusAppLayout.rightPanelBackgroundColor
}
}
Control {
SplitView.preferredWidth: root.showRightPanel ? 250 : 0
SplitView.minimumWidth: root.showRightPanel ? 58 : 0
opacity: root.showRightPanel ? 1.0 : 0.0
visible: (opacity > 0.1)
contentItem: Loader {
anchors.fill: parent
sourceComponent: (!!rightPanel) ? rightPanel : null
}
background: Rectangle {
anchors.fill: parent
color: Theme.palette.baseColor4
}
}
}

View File

@ -1,46 +0,0 @@
import QtQuick 2.13
import QtQuick.Layouts 1.13
import QtQuick.Controls 2.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
FocusScope {
id: statusAppTwoPanelLayout
implicitWidth: 822
implicitHeight: 600
property Item leftPanel
property Item rightPanel
onLeftPanelChanged: {
if (!!leftPanel) {
leftPanel.parent = leftPanelSlot
}
}
onRightPanelChanged: {
if (!!rightPanel) {
rightPanel.parent = rightPanelSlot
}
}
Row {
anchors.fill: parent
Rectangle {
id: leftPanelSlot
height: parent.height
width: 304
color: Theme.palette.baseColor4
}
Rectangle {
id: rightPanelSlot
height: parent.height
width: parent.width - leftPanelSlot.width
color: Theme.palette.statusAppLayout.rightPanelBackgroundColor
}
}
}

View File

@ -0,0 +1,71 @@
import QtQuick 2.13
import QtQuick.Layouts 1.13
import QtQuick.Controls 2.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
/*!
\qmltype StatusMainLayout
\inherits SplitView
\inqmlmodule StatusQ.Layout
\since StatusQ.Layout 0.1
\brief Displays a two column layout.
Inherits \l{https://doc.qt.io/qt-6/qml-qtquick-controls2-splitview.html}{SplitView}.
The \c StatusMainLayout displays a two column to be used as the base layout of the entire application.
For example:
\qml
StatusMainLayout {
leftPanel: StatusAppNavBar {
...
}
rightPanel: StatusAppChatView {
...
}
}
\endqml
For a list of components available see StatusQ.
*/
SplitView {
id: statusAppLayout
implicitWidth: 900
implicitHeight: 600
/*!
\qmlproperty Item StatusMainLayout::leftPanel
This property holds the left panel of the component.
*/
property Item leftPanel
/*!
\qmlproperty Item StatusMainLayout::rightPanel
This property holds the right panel of the component.
*/
property Item rightPanel
handle: Item { }
background: Rectangle {
color: Theme.palette.statusAppLayout.backgroundColor
}
Control {
SplitView.minimumWidth: 78
SplitView.preferredWidth: 78
SplitView.fillHeight: true
background: null
contentItem: (!!leftPanel) ? leftPanel : null
}
Control {
SplitView.fillWidth: true
SplitView.fillHeight: true
background: null
contentItem: (!!rightPanel) ? rightPanel : null
}
}

View File

@ -0,0 +1,162 @@
import QtQuick 2.13
import QtQuick.Layouts 1.14
import QtQuick.Controls 2.13
import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1
/*!
\qmltype StatusSectionLayout
\inherits SplitView
\inqmlmodule StatusQ.Layout
\since StatusQ.Layout 0.1
\brief Displays a three column layout with a header in the central panel.
Inherits \l{https://doc.qt.io/qt-6/qml-qtquick-controls2-splitview.html}{SplitView}.
The \c StatusSectionLayout displays a three column layout with a header in the central panel to be used as the base layout of all application
sections.
For example:
\qml
StatusSectionLayout {
id: root
notificationCount: 1
onNotificationButtonClicked: { showActivityCenter(); }
headerContent: RowLayout {
...
}
leftPanel: Item {
...
}
centerPanel: Item {
...
}
rightPanel: Item {
...
}
}
\endqml
For a list of components available see StatusQ.
*/
SplitView {
id: root
implicitWidth: 822
implicitHeight: 600
handle: Item { }
/*!
\qmlproperty Item StatusAppLayout::leftPanel
This property holds the left panel of the component.
*/
property Item leftPanel
/*!
\qmlproperty Item StatusAppLayout::centerPanel
This property holds the center panel of the component.
*/
property Item centerPanel
/*!
\qmlproperty Component StatusAppLayout::rightPanel
This property holds the right panel of the component.
*/
property Component rightPanel
/*!
\qmlproperty bool StatusAppLayout::showRightPanel
This property sets the right panel component's visibility to true/false.
Default value is false.
*/
property bool showRightPanel: false
/*!
\qmlproperty bool StatusAppLayout::showHeader
This property sets the header component's visibility to true/false.
Default value is true.
*/
property bool showHeader: true
/*!
\qmlproperty int StatusAppLayout::notificationCount
This property holds the number of notifications to be displayed in the notifications
button of the header component.
*/
property int notificationCount
/*!
\qmlproperty alias StatusAppLayout::headerContent
This property holds a reference to the custom header content of
the header component.
*/
property alias headerContent: statusToolBar.headerContent
/*!
\qmlproperty alias StatusAppLayout::notificationButton
This property holds a reference to the notification button of the header
component.
*/
property alias notificationButton: statusToolBar.notificationButton
/*!
\qmlsignal
This signal is emitted when the notification button of the header component
is pressed.
*/
signal notificationButtonClicked()
onCenterPanelChanged: {
if (!!centerPanel) {
centerPanel.parent = centerPanelSlot;
}
}
Control {
SplitView.minimumWidth: (!!leftPanel) ? 300 : 0
SplitView.preferredWidth: (!!leftPanel) ? 300 : 0
SplitView.fillHeight: (!!leftPanel)
background: Rectangle {
color: Theme.palette.baseColor4
}
contentItem: (!!leftPanel) ? leftPanel : null
}
Control {
SplitView.minimumWidth: (!!centerPanel) ? 300 : 0
SplitView.fillWidth: (!!centerPanel)
SplitView.fillHeight: (!!centerPanel)
background: Rectangle {
color: Theme.palette.statusAppLayout.rightPanelBackgroundColor
}
contentItem: Item {
StatusToolBar {
id: statusToolBar
width: visible ? parent.width : 0
visible: root.showHeader
onNotificationButtonClicked: {
root.notificationButtonClicked();
}
}
Item {
id: centerPanelSlot
width: parent.width
anchors.top: statusToolBar.bottom
anchors.bottom: parent.bottom
}
}
}
Control {
SplitView.preferredWidth: root.showRightPanel ? 250 : 0
SplitView.minimumWidth: root.showRightPanel ? 58 : 0
opacity: root.showRightPanel ? 1.0 : 0.0
visible: (opacity > 0.1)
background: Rectangle {
color: Theme.palette.baseColor4
}
contentItem: Loader {
sourceComponent: (!!rightPanel) ? rightPanel : null
}
}
}

View File

@ -1,6 +1,5 @@
module StatusQ.Layout
StatusAppLayout 0.1 StatusAppLayout.qml
StatusMainLayout 0.1 StatusMainLayout.qml
StatusSectionLayout 0.1 StatusSectionLayout.qml
StatusAppNavBar 0.1 StatusAppNavBar.qml
StatusAppTwoPanelLayout 0.1 StatusAppTwoPanelLayout.qml
StatusAppThreePanelLayout 0.1 StatusAppThreePanelLayout.qml

View File

@ -24,7 +24,7 @@
<file>StatusQ/Components/StatusChatListCategory.qml</file>
<file>StatusQ/Components/StatusChatListCategoryItem.qml</file>
<file>StatusQ/Components/StatusChatListItem.qml</file>
<file>StatusQ/Components/StatusChatToolBar.qml</file>
<file>StatusQ/Components/StatusToolBar.qml</file>
<file>StatusQ/Components/StatusColorSpace.qml</file>
<file>StatusQ/Components/StatusCommunityCard.qml</file>
<file>StatusQ/Components/StatusCommunityTags.qml</file>
@ -143,10 +143,7 @@
<file>StatusQ/Core/StatusScrollView.qml</file>
<file>StatusQ/Core/StatusTooltipSettings.qml</file>
<file>StatusQ/Layout/qmldir</file>
<file>StatusQ/Layout/StatusAppLayout.qml</file>
<file>StatusQ/Layout/StatusAppNavBar.qml</file>
<file>StatusQ/Layout/StatusAppThreePanelLayout.qml</file>
<file>StatusQ/Layout/StatusAppTwoPanelLayout.qml</file>
<file>StatusQ/Platform/qmldir</file>
<file>StatusQ/Platform/StatusMacNotification.qml</file>
<file>StatusQ/Platform/StatusMacTrafficLights.qml</file>