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

View File

@ -12,93 +12,73 @@ import StatusQ.Popups 0.1
Column { Column {
spacing: 10 spacing: 10
StatusChatToolBar { StatusToolBar {
toolbarComponent: chatInfoButton1
width: 518 width: 518
headerContent: StatusChatInfoButton {
Component { width: Math.min(implicitWidth, parent.width)
id: chatInfoButton1 title: "Some contact"
subTitle: "Contact"
StatusChatInfoButton { icon.color: Theme.palette.miscColor7
width: Math.min(implicitWidth, parent.width) type: StatusChatInfoButton.Type.OneToOneChat
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
}
} }
} }
StatusChatToolBar { StatusToolBar {
toolbarComponent: chatInfoButton2
width: 518 width: 518
Component { headerContent: StatusChatInfoButton {
id: chatInfoButton2 width: Math.min(implicitWidth, parent.width)
StatusChatInfoButton { title: "Some contact"
width: Math.min(implicitWidth, parent.width) subTitle: "Contact"
title: "Some contact" icon.color: Theme.palette.miscColor7
subTitle: "Contact" type: StatusChatInfoButton.Type.PublicChat
icon.color: Theme.palette.miscColor7 pinnedMessagesCount: 1
type: StatusChatInfoButton.Type.PublicChat muted: true
pinnedMessagesCount: 1
muted: true
}
} }
} }
StatusChatToolBar { StatusToolBar {
notificationCount: 1 notificationCount: 1
toolbarComponent: chatInfoButton3
width: 518 width: 518
Component { headerContent: StatusChatInfoButton {
id: chatInfoButton3 width: Math.min(implicitWidth, parent.width)
title: "Some contact"
StatusChatInfoButton { subTitle: "Contact"
width: Math.min(implicitWidth, parent.width) icon.color: Theme.palette.miscColor7
title: "Some contact" type: StatusChatInfoButton.Type.OneToOneChat
subTitle: "Contact" pinnedMessagesCount: 1
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
pinnedMessagesCount: 1
}
} }
} }
StatusChatToolBar { StatusToolBar {
notificationCount: 1 notificationCount: 1
toolbarComponent: tagSelector
width: 518 width: 518
Component { StatusTagSelector {
id: tagSelector namesModel: ListModel {
ListElement {
StatusTagSelector { publicId: "0x0"
namesModel: ListModel { name: "Maria"
ListElement { icon: ""
publicId: "0x0" isIdenticon: false
name: "Maria" onlineStatus: 3
icon: "" isReadonly: true
isIdenticon: false tagIcon: "crown"
onlineStatus: 3 }
isReadonly: true ListElement {
tagIcon: "crown" publicId: "0x1"
} name: "James"
ListElement { icon: ""
publicId: "0x1" isIdenticon: false
name: "James" onlineStatus: 1
icon: "" isReadonly: false
isIdenticon: false tagIcon: ""
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 import "data" 1.0
StatusAppThreePanelLayout { StatusSectionLayout {
id: root id: root
property bool createChat: false 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 { leftPanel: Item {
anchors.fill: parent anchors.fill: parent
anchors.margins: 16 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 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Layout 0.1
import StatusQ.Components 0.1 import StatusQ.Components 0.1
import "../demoapp/data" 1.0 import "../demoapp/data" 1.0
StatusSectionLayout {
StatusScrollView {
id: root id: root
QtObject { QtObject {
@ -31,124 +31,129 @@ StatusScrollView {
console.info("Clicked community ID: " + communityId) 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 ColumnLayout {
contentWidth: column.width + d.layoutHMargin id: column
clip: true spacing: 18
ColumnLayout { StatusBaseText {
id: column Layout.topMargin: d.layoutVMargin
spacing: 18 Layout.leftMargin: d.layoutHMargin
text: qsTr("Find community")
StatusBaseText { font.weight: Font.Bold
Layout.topMargin: d.layoutVMargin font.pixelSize: d.titlePixelSize
Layout.leftMargin: d.layoutHMargin color: Theme.palette.directColor1
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 { // Tags definition - Now hidden - Out of scope
Layout.leftMargin: d.layoutHMargin // TODO: Replace by `StatusListItemTagRow`
Layout.topMargin: 20 Row {
text: qsTr("Featured") visible: d.tagsModel.count > 0
font.weight: Font.Bold Layout.leftMargin: d.layoutHMargin
font.pixelSize: d.subtitlePixelSize Layout.rightMargin: d.layoutHMargin
color: Theme.palette.directColor1 width: 1234 // by design
} spacing: d.stylePadding/2
GridLayout { Repeater {
id: featuredGrid model: d.tagsModel
Layout.leftMargin: d.layoutHMargin delegate: StatusListItemTag {
columns: 3 border.color: Theme.palette.baseColor2
columnSpacing: d.stylePadding color: "transparent"
rowSpacing: d.stylePadding height: 32
radius: 36
Repeater { closeButtonVisible: false
model: d.featuredCommunitiesModel icon.emoji: model.emoji
delegate: StatusCommunityCard { icon.height: 32
locale: "es" icon.width: icon.height
communityId: model.communityId icon.color: "transparent"
loaded: model.available icon.isLetterIdenticon: true
logo: model.logo title: model.name
name: model.name titleText.font.pixelSize: 15
description: model.description titleText.color: Theme.palette.primaryColor1
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) }
} }
}
}
StatusBaseText { StatusBaseText {
Layout.leftMargin: d.layoutHMargin Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20 Layout.topMargin: 20
text: qsTr("Popular") text: qsTr("Featured")
font.weight: Font.Bold font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1 color: Theme.palette.directColor1
} }
GridLayout { GridLayout {
Layout.leftMargin: d.layoutHMargin id: featuredGrid
columns: 3 Layout.leftMargin: d.layoutHMargin
columnSpacing: d.stylePadding columns: 3
rowSpacing: d.stylePadding columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
Repeater { Repeater {
model: d.popularCommunitiesModel model: d.featuredCommunitiesModel
delegate: StatusCommunityCard { delegate: StatusCommunityCard {
locale: "es" locale: "es"
communityId: model.communityId communityId: model.communityId
loaded: model.available loaded: model.available
logo: model.logo logo: model.logo
name: model.name name: model.name
description: model.description description: model.description
members: model.members members: model.members
activeUsers: model.activeUsers popularity: model.popularity
popularity: model.popularity communityColor: model.communityColor
tokenLogo: model.tokenLogo categories: ListModel {
isPrivate: model.isPrivate ListElement { name: "sport"; emoji: "🎾"}
banner: model.banner 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 2.12
import QtQuick.Controls 2.14 import QtQuick.Controls 2.14
import QtQuick.Layouts 1.12
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Popups 0.1 import StatusQ.Popups 0.1
@ -10,7 +11,7 @@ import StatusQ.Core.Theme 0.1
import "data" 1.0 import "data" 1.0
StatusAppThreePanelLayout { StatusSectionLayout {
id: root id: root
property string communityDetailModalTitle: "" property string communityDetailModalTitle: ""
@ -22,6 +23,101 @@ StatusAppThreePanelLayout {
color: SplitHandle.pressed ? Theme.palette.baseColor2 color: SplitHandle.pressed ? Theme.palette.baseColor2
: (SplitHandle.hovered ? Qt.darker(Theme.palette.baseColor5, 1.1) : "transparent") : (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 { leftPanel: Item {
id: leftPanel id: leftPanel
@ -164,79 +260,12 @@ StatusAppThreePanelLayout {
} }
centerPanel: Item { centerPanel: Item {
StatusChatToolBar { anchors.fill: parent
id: statusChatToolBar StatusBaseText {
id: titleText
width: parent.width anchors.centerIn: parent
toolbarComponent: statusChatInfoButton font.pixelSize: 15
text: qsTr("Community content here")
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
} }
} }

View File

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

View File

@ -63,11 +63,11 @@ StatusWindow {
} }
} }
StatusAppLayout { StatusMainLayout {
id: appLayout id: appLayout
anchors.fill: parent anchors.fill: parent
appNavBar: StatusAppNavBar { leftPanel: StatusAppNavBar {
height: rootWindow.height height: rootWindow.height
communityTypeRole: "sectionType" communityTypeRole: "sectionType"
@ -105,30 +105,34 @@ StatusWindow {
} }
} }
appView: StackView { rightPanel: Item {
id: stackView
anchors.fill: parent anchors.fill: parent
initialItem: libraryDocumentationCmp StackView {
} id: stackView
anchors.fill: parent
ThemeSwitch { initialItem: libraryDocumentationCmp
anchors.top: parent.top }
anchors.topMargin: 32 ThemeSwitch {
anchors.right: parent.right anchors.top: parent.top
anchors.rightMargin: 32 anchors.topMargin: 32
lightThemeEnabled: storeSettings.lightTheme anchors.right: parent.right
onLightThemeEnabledChanged: { anchors.rightMargin: 32
Theme.palette = lightThemeEnabled ? rootWindow.darkTheme : rootWindow.lightTheme lightThemeEnabled: storeSettings.lightTheme
storeSettings.lightTheme = lightThemeEnabled onLightThemeEnabledChanged: {
Theme.palette = lightThemeEnabled ? rootWindow.darkTheme : rootWindow.lightTheme
storeSettings.lightTheme = lightThemeEnabled
}
} }
} }
} }
Component { Component {
id: libraryDocumentationCmp id: libraryDocumentationCmp
StatusAppTwoPanelLayout { StatusSectionLayout {
id: mainPageView id: mainPageView
showHeader: false
function page(name, fillPage) { function page(name, fillPage) {
storeSettings.fillPage = fillPage ? true : false storeSettings.fillPage = fillPage ? true : false
@ -343,8 +347,8 @@ StatusWindow {
} }
} }
rightPanel: Item { centerPanel: Item {
id: rightPanel id: centerPanel
anchors.fill: parent anchors.fill: parent
StatusScrollView { StatusScrollView {
@ -357,7 +361,7 @@ StatusWindow {
Item { Item {
id: pageWrapper id: pageWrapper
width: rightPanel.width width: centerPanel.width
anchors.top: parent.top anchors.top: parent.top
height: Math.max(rootWindow.height, viewLoader.height + 128) height: Math.max(rootWindow.height, viewLoader.height + 128)
scale: rootWindow.factor scale: rootWindow.factor
@ -415,8 +419,9 @@ StatusWindow {
Component { Component {
id: examplesCmp id: examplesCmp
StatusAppTwoPanelLayout { StatusSectionLayout {
id: examplesView id: examplesView
showHeader: false
function example(name) { function example(name) {
examplesLoader.source = Qt.resolvedUrl("./examples/" + name + ".qml") examplesLoader.source = Qt.resolvedUrl("./examples/" + name + ".qml")
@ -444,16 +449,19 @@ StatusWindow {
} }
} }
rightPanel: StatusScrollView { centerPanel: Item {
id: examplesRightPanel
anchors.fill: parent anchors.fill: parent
anchors.margins: 64 StatusScrollView {
anchors.topMargin: anchors.margins + 32 id: examplesCenterPanel
anchors.fill: parent
anchors.margins: 64
anchors.topMargin: anchors.margins + 32
Loader { Loader {
id: examplesLoader id: examplesLoader
width: examplesRightPanel.availableWidth width: examplesCenterPanel.availableWidth
source: storeSettings.selectedExample !== "" ? storeSettings.selectedExample : examplesView.defaultExampleSource 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 StatusChatListCategory 0.1 StatusChatListCategory.qml
StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml
StatusChatListAndCategories 0.1 StatusChatListAndCategories.qml StatusChatListAndCategories 0.1 StatusChatListAndCategories.qml
StatusChatToolBar 0.1 StatusChatToolBar.qml StatusToolBar 0.1 StatusToolBar.qml
StatusContactRequestsIndicatorListItem 0.1 StatusContactRequestsIndicatorListItem.qml StatusContactRequestsIndicatorListItem 0.1 StatusContactRequestsIndicatorListItem.qml
StatusEmoji 0.1 StatusEmoji.qml StatusEmoji 0.1 StatusEmoji.qml
StatusContactVerificationIcons 0.1 StatusContactVerificationIcons.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 module StatusQ.Layout
StatusAppLayout 0.1 StatusAppLayout.qml StatusMainLayout 0.1 StatusMainLayout.qml
StatusSectionLayout 0.1 StatusSectionLayout.qml
StatusAppNavBar 0.1 StatusAppNavBar.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/StatusChatListCategory.qml</file>
<file>StatusQ/Components/StatusChatListCategoryItem.qml</file> <file>StatusQ/Components/StatusChatListCategoryItem.qml</file>
<file>StatusQ/Components/StatusChatListItem.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/StatusColorSpace.qml</file>
<file>StatusQ/Components/StatusCommunityCard.qml</file> <file>StatusQ/Components/StatusCommunityCard.qml</file>
<file>StatusQ/Components/StatusCommunityTags.qml</file> <file>StatusQ/Components/StatusCommunityTags.qml</file>
@ -143,10 +143,7 @@
<file>StatusQ/Core/StatusScrollView.qml</file> <file>StatusQ/Core/StatusScrollView.qml</file>
<file>StatusQ/Core/StatusTooltipSettings.qml</file> <file>StatusQ/Core/StatusTooltipSettings.qml</file>
<file>StatusQ/Layout/qmldir</file> <file>StatusQ/Layout/qmldir</file>
<file>StatusQ/Layout/StatusAppLayout.qml</file>
<file>StatusQ/Layout/StatusAppNavBar.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/qmldir</file>
<file>StatusQ/Platform/StatusMacNotification.qml</file> <file>StatusQ/Platform/StatusMacNotification.qml</file>
<file>StatusQ/Platform/StatusMacTrafficLights.qml</file> <file>StatusQ/Platform/StatusMacTrafficLights.qml</file>