Compare commits

..
Author SHA1 Message Date
Alexandra Betouni d924768892 fix(Components/StatusTagSelector): Updates and fixes in the component
Moved `remove` function below remove contact signal
also removed online status badge from CreateChatView

Fixed as well name tags to be adapting on parent's
width and scrolling the list to the end when this is
bigger than the available width. Switcehd to use
nameCountLimit property where needed
2022-02-21 23:37:46 +02:00
Boris Melnik 9e6fbe955a feat(StatusChatList): Highlight chat item at creation time
Part of: https://github.com/status-im/status-desktop/issues/4767
2022-02-21 08:46:20 +01:00
Noelia 1217771fd0 feat(StatusPinInput): Introduce StatusPinInput control
It creates `StatusPinInput` control that allows customzing its circle diameter, circle spacing and pin length. It contains a `TextInput` object that will provide the component, input text management like validation rules.

It incorporates a blinking animation when the control is focused and feedback (mouse shape changed) when hovering it.

It adds new page in sandbox to play with `StatusPinInput` control.

It adds component documentation.

Also it creates 2 new `StatusValidator` controls with their corresponding documentation:
- `StatusRegularExpressionValidator` which wraps a QML type `RegularExpressionValidator`.

- `StatusIntValidator` which wraps a QML type `IntValidator`.

Closes #524
2022-02-18 09:25:05 +01:00
Noelia 3b86d13a96 feat(StatusSmartIdenticon): Add support for color rings in StatusSmartIdenticon (#553)
Created new control `StatusIdenticonRing` and used in `StatusSmartIdenticon` component.

Added property assignments in sandbox models to display the `StatusIdenticonRing` when needed.

Added first documentation approach for `StatusIdenticonRing` and `StatusIdenticonRingSettings`.

Closes #517
2022-02-17 09:20:17 +01:00
Noelia c0f825c690 feat(StatusContactVerificationIcons): Create new row control that includes mutual connect and trust indicator icons (#559)
Create `StatusContactVerificationIcons` row component.

Refactor in `StatusMemberListItem`. It now uses `StatusContactVerificationIcons` component.

Refactor in `StatusListItem`. It now contains a Loader for dynamically decide if a row icons component is defined aside the title.

Refactor in `StatusMessageHeader` and `StatusMessage`. They now use `StatusContactVerificationIcons` component.

Closes #542

BREAKING CHANGES:

Removed `titleIcon1Visible` and `titleIcon1Visible` from `StatusListItem`.

Removed `ContactType` enumeration in `StatusMessage`. Now, contact verification type is managed by enum `TrustedType` in `StatusContactVerificationIcons` component.
2022-02-16 11:37:48 +01:00
Alexandra Betouni 825999b151 feat(StatusQ): Moving docs outside sandbox
To generate docs, from doc folder run
/path/to/Qt/installation/bin/qdoc statusq.qdocconf

A folder named "html" will be generated under doc,
open the statusq-index.html to get to the home page.
2022-02-15 08:43:33 +01:00
Alexandra Betouni cdf51fefbd fix(sandbox): Fix results popup component position
Fixed alignment when results are being filtered.
If the x position that the popup should be aligned
goes off the screen, the popup appears back on
position 0. Also fixed result list item was not
vertically centered.
2022-02-15 08:40:19 +01:00
Alexandra Betouni 665141f81d fix(StatusQ.Popups): removed overlay setting (#557)
A MouseArea was set as an Overlay to the PopupMenu
consuming all clicks outside the component until it
was closed. Removed it as it's not necessary anymore.

Closes https://github.com/status-im/status-desktop/issues/3599
2022-02-15 05:08:15 +02:00
Pascal Precht 9cbd19d658 chore: release v0.24.0 2022-02-14 10:02:02 +01:00
Alexandra Betouni 0e00fd24ab feat(StatusQ) Adding qdoc related files (#555)
Added qdoc conf & source files for each
StatusQ module. Documented StatusBaseText
from StatusQ.Core as an example

To generate docs, from sandbox/docs run
/path/to/Qt/installation/bin/qdoc statusq.qdocconf

A folder named "html" will be generated under sandbox/doc,
open the statusq-index.html to get to the home page.

Closes #550
2022-02-11 09:55:44 -05:00
Patryk Osmaczko 5780f183c7 feat(StatusListItem): add highlighted property 2022-02-09 10:00:41 +01:00
Alexandra Betouni b7d6554b80 feat(StatusQ.Components): Adding StatusWizardSteper component
Added StatusWizardStepper component

Also added corresponding page in API documentation

Closes #522
2022-02-09 09:21:46 +01:00
Pascal Precht 0fabd92d61 chore: cut 0.23.0 release 2022-02-08 09:40:35 +01:00
Alexandra Betouni 7b290ddd56 feat(StatusQ.Components): Adding StatusToastMessage
Added StatusToastMessage component, an example page
as well as a demonstration in chat view

Closes #521
2022-02-08 09:36:38 +01:00
Alexandra Betouni 094dee4928 feat(StatusQ.Components): Adding StatusTagSelector component
Added StatusTagSelector component needed for
creating new chat channels, either ono on
one or group based on updated designs on
Figma

Also added corresponding page in API Documentation

Closes #526
2022-02-02 10:26:45 +01:00
Noelia 5497bb3f5f chore(demoApp): restore DemoApp to have the latest changes from both master and base_bc
Updated DemoApp, main and Models to have the
latest changes from both master and base_bc
2022-02-02 10:18:03 +01:00
Richard Ramos d85ed4c3ed refactor: fix empty categories handling (#544)
* feat(StatusChatListCategory): display item if the model is a category
* fix(StatusChatListAndCategories): do not display categories in StatusChatList
2022-02-01 11:10:09 +01:00
Sale Djenic 77b89edbdb refactor(StatusAppNavBar): triggerUpdate function added 2022-02-01 11:10:09 +01:00
Sale Djenic 80396841f1 refactor(StatusChatToolBar): open/close handlers get called if they are set for popupMenu of StatusChatToolBar component 2022-02-01 11:10:09 +01:00
Sale Djenic c2e075178c fix(StatusChatList): unexisting property name for chat item fixed
`StatusChatList` component is able to display:
- chats for Chat section
- channels for Community section
- channels from a category from Community section

in cases 1. and 2. displayed items do not have `parentItemId` property and
it's not used in these cases.
This commit fixes that console error.
2022-02-01 11:10:09 +01:00
Sale Djenic e0f34a3e1d refactor(StatusChatList): categoryId parameter added to chatItemSelected signal 2022-02-01 11:10:09 +01:00
Sale Djenic c2bab872be refactor(StatusChatList): updates due to chat & communities models refactored
Updated Models.qml for chats and communities models to reflect changes due to
refactor in the actual backend.`StatusChatList` and `StatusChatListAndCategories`
components updated accordingly.
2022-02-01 11:10:09 +01:00
Alexandra Betouni 491f7d5d15 refactor(sandbox): remove obsolete timeline demo code
This feature is deprecated and shall be removed

Relates to #4177
2022-02-01 11:10:09 +01:00
Sale Djenic c6893b0c7f refactor(StatusAppNavBar): profile nav bar button added
Profile button of type `StatusNavBarTabButton` added to `StatusAppNavBar`
and exposed so it can be optionally set from outside of the component.
2022-02-01 11:10:09 +01:00
Sale Djenic 2ee91475e5 refactor(StatusAppNavBar): navigation bar displays buttons based on set model
`StatusAppNavBar` component is refactored in order to meet new changes we
have on the backend in the desktop app.
2022-02-01 11:10:09 +01:00
62 changed files with 3232 additions and 929 deletions
+1
View File
@@ -13,3 +13,4 @@ Makefile
*_qml.cpp
*_qmlcache.qrc
sandbox/qmlcache_loader.cpp
doc/html
+28
View File
@@ -1,3 +1,31 @@
<a name=""></a>
## 0.24.0 (2022-02-14)
#### Features
* **StatusListItem:** add highlighted property ([5780f183](5780f183))
* **StatusQ.Components:** Adding StatusWizardSteper component ([b7d6554b](b7d6554b), closes [#522](522))
<a name=""></a>
## Version 0.23.0 (2022-02-08)
#### Bug Fixes
* Icon components had wrong color in sandbox app ([b632c712](b632c712), closes [#538](538))
* **StatusChatList:** unexisting property name for chat item fixed ([c2e07517](c2e07517))
#### Features
* **StatusQ.Components:**
* Adding StatusToastMessage ([7b290ddd](7b290ddd), closes [#521](521))
* Adding StatusTagSelector component ([094dee49](094dee49), closes [#526](526))
<a name=""></a>
## Version 0.22.0 (2022-01-31)
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

+19
View File
@@ -0,0 +1,19 @@
/*!
\page statusq-index.html
\title StatusQ
\brief A components library for Status desktop client.
StatusQ provides a collection of components....
StatusQ - Components and Interfaces
\list
\li \l{StatusQ Components}{Components}
\li \l{StatusQ Controls}{Controls}
\li \l{StatusQ Core}{Core}
\li \l{StatusQ Layout}{Layout}
\li \l{StatusQ Platform}{Platform}
\li \l{StatusQ Popups}{Popups}
\endlist
*/
+41
View File
@@ -0,0 +1,41 @@
/*!
\qmlmodule StatusQ.Components 0.1
\title StatusQ Components
\brief Basic set of Components StatusQ components
This is a listing of all Components components.
This module is part of the \l{StatusQ}{StatusQ} project.
\list
\li \l{StatusAddress}
\li \l{StatusBadge}
\li \l{StatusChatInfoToolBar}
\li \l{StatusChatList}
\li \l{StatusChatListItem}
\li \l{StatusImageSettings}
\li \l{StatusChatListCategory}
\li \l{StatusChatListCategoryItem}
\li \l{StatusChatListAndCategories}
\li \l{StatusChatToolBar}
\li \l{StatusContactRequestsIndicatorListItem}
\li \l{StatusDescriptionListItem}
\li \l{StatusLetterIdenticon}
\li \l{StatusListItem}
\li \l{StatusListSectionHeadline}
\li \l{StatusLoadingIndicator}
\li \l{StatusMemberListItem}
\li \l{StatusNavigationListItem}
\li \l{StatusNavigationPanelHeadline}
\li \l{StatusRoundIcon}
\li \l{StatusRoundedImage}
\li \l{StatusMacWindowButtons}
\li \l{StatusListItemBadge}
\li \l{StatusExpandableItem}
\li \l{StatusSmartIdenticon}
\li \l{StatusMessage}
\li \l{StatusMessageDetails}
\li \l{StatusTagSelector}
\li \l{StatusToastMessage}
\endlist
*/
+47
View File
@@ -0,0 +1,47 @@
/*!
\qmlmodule StatusQ.Controls 0.1
\title StatusQ Controls
\brief Basic set of Controls StatusQ components
This is a listing of all Controls components.
This module is part of the \l{StatusQ}{StatusQ} project.
\list
\li \l{StatusAccountSelector}
\li \l{StatusAssetSelector}
\li \l{StatusBanner}
\li \l{StatusChatCommandButton}
\li \l{StatusChatInfoButton}
\li \l{StatusChatListCategoryItemButton}
\li \l{StatusColorSelector}
\li \l{StatusIconTabButton}
\li \l{StatusNavBarTabButton}
\li \l{StatusTabBarIconButton}
\li \l{StatusToolTip}
\li \l{StatusBaseButton}
\li \l{StatusButton}
\li \l{StatusFlatButton}
\li \l{StatusRoundButton}
\li \l{StatusFlatRoundButton}
\li \l{StatusSwitch}
\li \l{StatusRadioButton}
\li \l{StatusCheckBox}
\li \l{StatusSlider}
\li \l{StatusSelect}
\li \l{StatusBaseInput}
\li \l{StatusIdenticonRing}
\li \l{StatusInput}
\li \l{StatusPickerButton}
\li \l{StatusPinInput}
\li \l{StatusProgressBar}
\li \l{StatusPasswordStrengthIndicator}
\li \l{StatusSwitchTabButton}
\li \l{StatusSwitchTabBar}
\li \l{StatusSelectableText}
\li \l{StatusWalletColorButton}
\li \l{StatusWalletColorSelect}
\li \l{StatusRegularExpressionValidator}
\li \l{StatusIntValidator}
\endlist
*/
+23
View File
@@ -0,0 +1,23 @@
/*!
\qmlmodule StatusQ.Core 0.1
\title StatusQ Core
\brief Basic set of Core StatusQ components
This is a listing of all Core components. These
files are available for general import and they are based off the \l{https://doc.qt.io/qt-5/qtquick-qmlmodule.html}{Qt
Quick Primitives} and \l{https://doc.qt.io/archives/qt-5.11/qtquick-controls2-qmlmodule.html}{Qt Quick Controls 2}.
This module is part of the \l{StatusQ}{StatusQ} project.
\list
\li \l{StatusAppNavBarFilterModel}
\li \l{StatusBaseText}
\li \l{StatusIcon}
\li \l{StatusIconBackgroundSettings}
\li \l{StatusIconSettings}
\li \l{StatusIdenticonRingSettings}
\li \l{StatusImageSettings}
\li \l{StatusModalHeaderSettings}
\li \l{StatusTooltipSettings}
\endlist
*/
+16
View File
@@ -0,0 +1,16 @@
/*!
\qmlmodule StatusQ.Layout 0.1
\title StatusQ Layout
\brief Basic set of Layout StatusQ components
This is a listing of all Layout components.
This module is part of the \l{StatusQ}{StatusQ} project.
\list
\li \l{StatusAppLayout}
\li \l{StatusAppNavBar}
\li \l{StatusAppTwoPanelLayout}
\li \l{StatusAppThreePanelLayout}
\endlist
*/
+15
View File
@@ -0,0 +1,15 @@
/*!
\qmlmodule StatusQ.Platform 0.1
\title StatusQ Platform
\brief Basic set of Platform StatusQ components
This is a listing of all Platform components.
This module is part of the \l{StatusQ}{StatusQ} project.
\list
\li \l{StatusMacTrafficLights}
\li \l{StatusMacNotification}
\li \l{StatusWindowsTitleBar}
\endlist
*/
+22
View File
@@ -0,0 +1,22 @@
/*!
\qmlmodule StatusQ.Popups 0.1
\title StatusQ Popups
\brief Basic set of Popups StatusQ components
This is a listing of all Popups components.
This module is part of the \l{StatusQ}{StatusQ} project.
\list
\li \l{StatusMenuSeparator}
\li \l{StatusPopupMenu}
\li \l{StatusMenuItem}
\li \l{StatusMenuItemDelegate}
\li \l{StatusModal}
\li \l{StatusSearchPopup}
\li \l{StatusModalDivider}
\li \l{StatusSearchPopupMenuItem}
\li \l{StatusSearchLocationMenu}
\li \l{StatusSpellcheckingMenuItems}
\endlist
*/
+36
View File
@@ -0,0 +1,36 @@
project = StatusQ
version = 0.1
description = StatusQ Project
url = https://github.com/status-im/StatusQ
#These are set implictly by qdoc as well, but only with these the module header can be found
includepaths = -I . \
-I $PWD/../src/StatusQ
imagedirs = src/images
sourcedirs += src \
$PWD/../src/StatusQ/Components \
$PWD/../src/StatusQ/Controls \
$PWD/../src/StatusQ/Core \
$PWD/../src/StatusQ/Layout \
$PWD/../src/StatusQ/Platform \
$PWD/../src/StatusQ/Popups \
sources.fileextensions = "*.cpp *.qdoc *.qml"
depends += qtcore \
qtquick \
qtqml \
qtgui \
qtdoc \
qtquickcontrols2
navigation.homepage = "StatusQ"
outputdir = $PWD/html
outputformats = HTML
HTML.stylesheets = style.css
HTML.headerstyles = "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\"/>\n"
HTML.postheader = "<p class=\"header\"><small>StatusQ - A Components selection for Status dekstop client. </p></small></p><hr/>"
HTML.footer = "<hr/><div class=\"footer\"><p><acronym title=\"Copyright\">&copy;</acronym> 2022 Status. All rights reserved. <a href=\"https://status.im\" target=\"_blank\"><small>status.im</a></small></p></div>"
+41
View File
@@ -0,0 +1,41 @@
body {
font-family: "Verdana";
font-size: 14px;
max-width: 80%;
margin: auto;
}
h1, h2, h3 {
color: #4360DF;
}
div.sidebar {
float: right;
}
pre {
padding: 15px;
}
div.qmlproto {
padding-left: 15px;
padding-right: 15px;
}
pre, div.qmlproto {
font-family: "Courier New";
font-size: 20px;
margin-left: 2em;
background-color: #F0F2F5;
}
hr {
margin-top: 2em;
margin-bottom: 2em;
}
p.header {
margin-bottom: -1em;
}
p.footer {
text-align: right;
margin-top: -1em;
}
+91 -53
View File
@@ -1,12 +1,16 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Layout 0.1
import StatusQ.Popups 0.1
import StatusQ.Platform 0.1
import "demoapp"
import "demoapp/data" 1.0
Rectangle {
id: demoApp
@@ -17,6 +21,31 @@ Rectangle {
property string titleStyle: "osx"
QtObject {
id: appSectionType
readonly property int chat: 0
readonly property int community: 1
readonly property int wallet: 2
readonly property int browser: 3
readonly property int nodeManagement: 4
readonly property int profileSettings: 5
readonly property int apiDocumentation: 100
readonly property int demoApp: 101
}
function setActiveItem(sectionId) {
for (var i = 0; i < Models.demoAppSectionsModel.count; i++) {
let item = Models.demoAppSectionsModel.get(i)
if (item.sectionId !== sectionId)
{
Models.demoAppSectionsModel.setProperty(i, "active", false)
continue
}
Models.demoAppSectionsModel.setProperty(i, "active", true);
}
}
StatusMacTrafficLights {
anchors.left: parent.left
anchors.top: parent.top
@@ -47,32 +76,74 @@ Rectangle {
id: navBar
navBarChatButton: StatusNavBarTabButton {
icon.name: "chat"
tooltip.text: "Chat"
checked: appView.sourceComponent == statusAppChatView
onClicked: {
appView.sourceComponent = statusAppChatView
}
communityTypeRole: "sectionType"
communityTypeValue: appSectionType.community
sectionModel: Models.demoAppSectionsModel
property bool communityAdded: false
onAboutToUpdateFilteredRegularModel: {
communityAdded = false
}
navBarCommunityTabButtons.model: ListModel {
ListElement {
name: "Status Community"
tooltipText: "Status Community"
}
filterRegularItem: function(item) {
if(item.sectionType === appSectionType.community)
if(communityAdded)
return false
else
communityAdded = true
return true
}
navBarCommunityTabButtons.delegate: StatusNavBarTabButton {
id: communityBtn
filterCommunityItem: function(item) {
return item.sectionType === appSectionType.community
}
regularNavBarButton: StatusNavBarTabButton {
anchors.horizontalCenter: parent.horizontalCenter
name: model.name
tooltip.text: model.tooltipText
icon.color: Theme.palette.miscColor6
icon.source: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
checked: appView.sourceComponent == statusAppCommunityView
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: {
appView.sourceComponent = statusAppCommunityView
if(model.sectionType === appSectionType.chat)
{
appView.sourceComponent = statusAppChatView
demoApp.setActiveItem(model.sectionId)
}
else if(model.sectionType === appSectionType.profileSettings)
{
appView.sourceComponent = statusAppProfileSettingsView
demoApp.setActiveItem(model.sectionId)
}
}
}
communityNavBarButton: 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.community)
{
appView.sourceComponent = statusAppCommunityView
demoApp.setActiveItem(model.sectionId)
}
}
popupMenu: StatusPopupMenu {
@@ -103,40 +174,7 @@ Rectangle {
type: StatusMenuItem.Type.Danger
}
}
}
navBarTabButtons: [
StatusNavBarTabButton {
icon.name: "wallet"
tooltip.text: "Wallet"
},
StatusNavBarTabButton {
icon.name: "bigger/browser"
tooltip.text: "Browser"
},
StatusNavBarTabButton {
icon.name: "bigger/status-update"
tooltip.text: "Timeline"
},
StatusNavBarTabButton {
id: profileNavButton
icon.name: "bigger/settings"
badge.visible: true
badge.anchors.rightMargin: 4
badge.anchors.topMargin: 5
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusAppNavBar.backgroundColor
badge.border.width: 2
tooltip.text: "Profile"
checked: appView.sourceComponent == statusAppProfileSettingsView
onClicked: {
appView.sourceComponent = statusAppProfileSettingsView
}
}
]
}
appView: Loader {
+348 -200
View File
@@ -7,6 +7,7 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Layout 0.1
import StatusQ.Popups 0.1
Column {
spacing: 5
@@ -49,247 +50,394 @@ Column {
}
}
StatusAppNavBar {
navBarChatButton: StatusNavBarTabButton {
icon.name: "chat"
badge.value: 33
badge.visible: true
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusBadge.borderColor
badge.border.width: 2
tooltip.text: "Chat"
}
QtObject {
id: appSectionType
readonly property int chat: 0
readonly property int community: 1
readonly property int wallet: 2
readonly property int browser: 3
readonly property int nodeManagement: 4
readonly property int profileSettings: 5
}
StatusAppNavBar {
navBarChatButton: StatusNavBarTabButton {
icon.name: "chat"
badge.value: 33
badge.visible: true
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusBadge.borderColor
badge.border.width: 2
tooltip.text: "Chat"
sectionModel: ListModel {
ListElement {sectionId: "chat"; sectionType: 0; name: "Chat"; active: true; image: ""; icon: "chat"; color: ""; hasNotification: true; notificationsCount: 12}
}
navBarCommunityTabButtons.model: ListModel {
id: buttons
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
}
navBarCommunityTabButtons.delegate: StatusNavBarTabButton {
name: model.name
tooltip.text: model.name
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
}
navBarTabButtons: [
StatusNavBarTabButton {
icon.name: "wallet"
tooltip.text: "Wallet"
},
StatusNavBarTabButton {
icon.name: "browser"
tooltip.text: "Browser"
},
StatusNavBarTabButton {
icon.name: "status-update"
tooltip.text: "Timeline"
},
StatusNavBarTabButton {
icon.name: "profile"
badge.visible: true
badge.anchors.rightMargin: 4
badge.anchors.topMargin: 5
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusBadge.borderColor
badge.border.width: 2
tooltip.text: "Profile"
}
]
}
StatusAppNavBar {
navBarChatButton: StatusNavBarTabButton {
icon.name: "chat"
badge.value: 33
badge.visible: true
communityTypeRole: "sectionType"
communityTypeValue: appSectionType.community
sectionModel: ListModel {
ListElement {sectionId: "chat"; sectionType: 0; name: "Chat"; active: true; image: ""; icon: "chat"; color: ""; hasNotification: true; notificationsCount: 12}
ListElement {sectionId: "0x0001"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: true; notificationsCount: 12}
ListElement {sectionId: "wallet"; sectionType: 2; name: "Wallet"; active: false; image: ""; icon: "wallet"; color: ""; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "browser"; sectionType: 3; name: "Browser"; active: false; image: ""; icon: "bigger/browser"; color: ""; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "profile"; sectionType: 5; name: "Profile"; active: false; image: ""; icon: "bigger/settings"; color: ""; hasNotification: true; notificationsCount: 0}
}
property bool 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
tooltip.text: "Chat"
}
navBarCommunityTabButtons.model: ListModel {
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
}
navBarCommunityTabButtons.delegate: StatusNavBarTabButton {
name: model.name
tooltip.text: model.name
communityNavBarButton: 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
navBarTabButtons: [
StatusNavBarTabButton {
icon.name: "wallet"
tooltip.text: "Wallet"
},
StatusNavBarTabButton {
icon.name: "browser"
tooltip.text: "Browser"
popupMenu: StatusPopupMenu {
StatusMenuItem {
text: qsTr("Invite People")
icon.name: "share-ios"
}
StatusMenuItem {
text: qsTr("View Community")
icon.name: "group"
}
StatusMenuItem {
text: qsTr("Edit Community")
icon.name: "edit"
enabled: false
}
StatusMenuSeparator {}
StatusMenuItem {
text: qsTr("Leave Community")
icon.name: "arrow-right"
icon.width: 14
iconRotation: 180
type: StatusMenuItem.Type.Danger
}
}
]
}
}
StatusAppNavBar {
navBarChatButton: StatusNavBarTabButton {
icon.name: "chat"
badge.value: 33
badge.visible: true
communityTypeRole: "sectionType"
communityTypeValue: appSectionType.community
sectionModel: ListModel {
ListElement {sectionId: "chat"; sectionType: 0; name: "Chat"; active: true; image: ""; icon: "chat"; color: ""; hasNotification: true; notificationsCount: 12}
ListElement {sectionId: "0x0001"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: true; notificationsCount: 12}
ListElement {sectionId: "wallet"; sectionType: 2; name: "Wallet"; active: false; image: ""; icon: "wallet"; color: ""; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "browser"; sectionType: 3; name: "Browser"; active: false; image: ""; icon: "bigger/browser"; color: ""; hasNotification: false; notificationsCount: 0}
}
property bool 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
tooltip.text: "Chat"
}
navBarCommunityTabButtons.model: ListModel {
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
}
navBarCommunityTabButtons.delegate: StatusNavBarTabButton {
name: model.name
tooltip.text: model.name
communityNavBarButton: 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
popupMenu: StatusPopupMenu {
StatusMenuItem {
text: qsTr("Invite People")
icon.name: "share-ios"
}
StatusMenuItem {
text: qsTr("View Community")
icon.name: "group"
}
StatusMenuItem {
text: qsTr("Edit Community")
icon.name: "edit"
enabled: false
}
StatusMenuSeparator {}
StatusMenuItem {
text: qsTr("Leave Community")
icon.name: "arrow-right"
icon.width: 14
iconRotation: 180
type: StatusMenuItem.Type.Danger
}
}
}
}
StatusAppNavBar {
communityTypeRole: "sectionType"
communityTypeValue: appSectionType.community
sectionModel: ListModel {
ListElement {sectionId: "chat"; sectionType: 0; name: "Chat"; active: true; image: ""; icon: "chat"; color: ""; hasNotification: true; notificationsCount: 12}
ListElement {sectionId: "0x0001"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "0x0002"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "0x0003"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "0x0004"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: true; notificationsCount: 0}
ListElement {sectionId: "wallet"; sectionType: 2; name: "Wallet"; active: false; image: ""; icon: "wallet"; color: ""; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "browser"; sectionType: 3; name: "Browser"; active: false; image: ""; icon: "bigger/browser"; color: ""; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "profile"; sectionType: 5; name: "Profile"; active: false; image: ""; icon: "bigger/settings"; color: ""; hasNotification: false; notificationsCount: 0}
}
navBarTabButtons: [
StatusNavBarTabButton {
icon.name: "wallet"
tooltip.text: "Wallet"
},
StatusNavBarTabButton {
icon.name: "browser"
tooltip.text: "Browser"
},
StatusNavBarTabButton {
icon.name: "status-update"
tooltip.text: "Timeline"
},
StatusNavBarTabButton {
icon.name: "profile"
badge.visible: true
badge.anchors.rightMargin: 4
badge.anchors.topMargin: 5
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusBadge.borderColor
badge.border.width: 2
property bool communityAdded: false
tooltip.text: "Profile"
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
}
communityNavBarButton: 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
popupMenu: StatusPopupMenu {
StatusMenuItem {
text: qsTr("Invite People")
icon.name: "share-ios"
}
StatusMenuItem {
text: qsTr("View Community")
icon.name: "group"
}
StatusMenuItem {
text: qsTr("Edit Community")
icon.name: "edit"
enabled: false
}
StatusMenuSeparator {}
StatusMenuItem {
text: qsTr("Leave Community")
icon.name: "arrow-right"
icon.width: 14
iconRotation: 180
type: StatusMenuItem.Type.Danger
}
}
]
}
}
StatusAppNavBar {
id: test
navBarChatButton: StatusNavBarTabButton {
icon.name: "chat"
badge.value: 33
badge.visible: true
communityTypeRole: "sectionType"
communityTypeValue: appSectionType.community
sectionModel: ListModel {
ListElement {sectionId: "chat"; sectionType: 0; name: "Chat"; active: true; image: ""; icon: "chat"; color: ""; hasNotification: true; notificationsCount: 12}
ListElement {sectionId: "0x0001"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: true; notificationsCount: 12}
ListElement {sectionId: "0x0002"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "0x0003"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: true; notificationsCount: 0}
ListElement {sectionId: "0x0004"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: true; notificationsCount: 1}
ListElement {sectionId: "0x0005"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "0x0006"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: true; notificationsCount: 3}
ListElement {sectionId: "0x0007"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: true; notificationsCount: 5}
ListElement {sectionId: "0x0008"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: true; notificationsCount: 0}
ListElement {sectionId: "0x0009"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "0x0010"; sectionType: 1; name: "Test Community"; active: false; image: ""; icon: ""; color: "#00ff00"; hasNotification: true; notificationsCount: 11}
ListElement {sectionId: "wallet"; sectionType: 2; name: "Wallet"; active: false; image: ""; icon: "wallet"; color: ""; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "browser"; sectionType: 3; name: "Browser"; active: false; image: ""; icon: "bigger/browser"; color: ""; hasNotification: false; notificationsCount: 0}
ListElement {sectionId: "profile"; sectionType: 5; name: "Profile"; active: false; image: ""; icon: "bigger/settings"; color: ""; hasNotification: true; notificationsCount: 0}
}
property bool 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
tooltip.text: "Chat"
}
navBarCommunityTabButtons.model: ListModel {
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
ListElement {
name: "Test community"
tooltipText: "Test Community"
}
}
navBarCommunityTabButtons.delegate: StatusNavBarTabButton {
name: model.name
tooltip.text: model.name
communityNavBarButton: 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
navBarTabButtons: [
StatusNavBarTabButton {
icon.name: "wallet"
tooltip.text: "Wallet"
},
StatusNavBarTabButton {
icon.name: "browser"
tooltip.text: "Browser"
},
StatusNavBarTabButton {
icon.name: "status-update"
tooltip.text: "Timeline"
},
StatusNavBarTabButton {
icon.name: "profile"
badge.visible: true
badge.anchors.rightMargin: 4
badge.anchors.topMargin: 5
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusBadge.borderColor
badge.border.width: 2
popupMenu: StatusPopupMenu {
tooltip.text: "Profile"
StatusMenuItem {
text: qsTr("Invite People")
icon.name: "share-ios"
}
StatusMenuItem {
text: qsTr("View Community")
icon.name: "group"
}
StatusMenuItem {
text: qsTr("Edit Community")
icon.name: "edit"
enabled: false
}
StatusMenuSeparator {}
StatusMenuItem {
text: qsTr("Leave Community")
icon.name: "arrow-right"
icon.width: 14
iconRotation: 180
type: StatusMenuItem.Type.Danger
}
}
]
}
}
}
}
+18 -5
View File
@@ -85,7 +85,8 @@ GridLayout {
StatusChatListItem {
name: "has-mentions"
type: StatusChatListItem.Type.PublicChat
badge.value: 1
hasUnreadMessages: true
notificationsCount: 1
}
StatusChatListItem {
@@ -100,7 +101,7 @@ GridLayout {
type: StatusChatListItem.Type.PublicChat
muted: true
hasUnreadMessages: true
badge.value: 1
notificationsCount: 1
}
StatusChatListItem {
@@ -130,7 +131,7 @@ GridLayout {
selected: true
muted: true
hasUnreadMessages: true
badge.value: 1
notificationsCount: 1
}
@@ -350,18 +351,30 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
nickName: "This is an example"
userName: "annabelle"
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
trustIndicator: StatusMemberListItem.TrustedType.Verified
trustIndicator: StatusContactVerificationIcons.TrustedType.Verified
isMutualContact: true
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
image.isIdenticon: true
isOnline: true
ringSettings.ringSpecModel:
ListModel {
ListElement {colorId: 13; segmentLength: 5}
ListElement {colorId: 31; segmentLength: 5}
ListElement {colorId: 10; segmentLength: 1}
ListElement {colorId: 2; segmentLength: 5}
ListElement {colorId: 26; segmentLength: 2}
ListElement {colorId: 19; segmentLength: 4}
ListElement {colorId: 28; segmentLength: 3}
}
ringSettings.distinctiveColors: Theme.palette.identiconRingColors
ringSettings.totalRingUnits: 25
}
StatusMemberListItem {
nickName: "carmen.eth"
isOnline: false
trustIndicator: StatusMemberListItem.TrustedType.Untrustworthy
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
}
StatusMemberListItem {
+104
View File
@@ -0,0 +1,104 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQml.Models 2.2
import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
ListView {
id: messageList
anchors.fill: parent
anchors.margins: 15
clip: true
delegate: StatusMessage {
id: delegate
width: parent.width
audioMessageInfoText: "Audio Message"
cancelButtonText: "Cancel"
saveButtonText: "Save"
loadingImageText: "Loading image..."
errorLoadingImageText: "Error loading the image"
resendText: "Resend"
pinnedMsgInfoText: "Pinned by"
messageDetails: StatusMessageDetails {
contentType: model.contentType
messageContent: model.messageContent
amISender: model.amIsender
displayName: model.userName
secondaryName: model.localName !== "" && model.ensName.startsWith("@") ? model.ensName: ""
chatID: model.chatKey
profileImage: StatusImageSettings {
width: 40
height: 40
source: model.profileImage
isIdenticon: model.isIdenticon
}
messageText: model.message
hasMention: model.hasMention
isMutualContact: model.isMutualContact
trustIndicator: model.trustIndicator
isPinned: model.isPinned
pinnedBy: model.pinnedBy
hasExpired: model.hasExpired
}
timestamp.text: "10:00 am"
timestamp.tooltip.text: "10:01 am"
// reply related data
isAReply: model.isReply
replyDetails: StatusMessageDetails {
amISender: model.isReply ? model.replyAmISender : ""
displayName: model.isReply ? model.replySenderName: ""
profileImage: StatusImageSettings {
width: 20
height: 20
source: model.isReply ? model.replyProfileImage: ""
isIdenticon: model.isReply ? model.replyIsIdenticon: ""
}
messageText: model.isReply ? model.replyMessageText: ""
contentType: model.replyContentType
messageContent: model.replyMessageContent
}
quickActions: [
StatusFlatRoundButton {
id: emojiBtn
width: 32
height: 32
icon.name: "reaction-b"
type: StatusFlatRoundButton.Type.Tertiary
tooltip.text: "Add reaction"
},
StatusFlatRoundButton {
id: replyBtn
width: 32
height: 32
icon.name: "reply"
type: StatusFlatRoundButton.Type.Tertiary
tooltip.text: "Reply"
},
StatusFlatRoundButton {
width: 32
height: 32
icon.name: "tiny/edit"
type: StatusFlatRoundButton.Type.Tertiary
tooltip.text: "Edit"
onClicked: {
delegate.editMode = !delegate.editMode
}
},
StatusFlatRoundButton {
id: otherBtn
width: 32
height: 32
icon.name: "more"
type: StatusFlatRoundButton.Type.Tertiary
tooltip.text: "More"
}
]
}
}
+215
View File
@@ -0,0 +1,215 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQml.Models 2.2
import QtGraphicalEffects 1.0
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
Page {
id: root
anchors.fill: parent
anchors.margins: 16
property ListModel contactsModel: null
background: null
header: RowLayout {
id: headerRow
width: parent.width
height: tagSelector.height
anchors.right: parent.right
anchors.rightMargin: 8
StatusTagSelector {
id: tagSelector
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: 17
implicitHeight: 44
toLabelText: qsTr("To: ")
warningText: qsTr("5 USER LIMIT REACHED")
//simulate model filtering, TODO this
//makes more sense to be provided by the backend
//figure how real implementation should look like
property ListModel sortedList: ListModel { }
onTextChanged: {
sortedList.clear();
if (text !== "") {
for (var i = 0; i < contactsModel.count; i++ ) {
var entry = contactsModel.get(i);
if (entry.name.toLowerCase().includes(text.toLowerCase())) {
sortedList.insert(sortedList.count, {"publicId": entry.publicId, "name": entry.name,
"icon": entry.icon, "isIdenticon": entry.isIdenticon,
"onlineStatus": entry.onlineStatus});
userListView.model = sortedList;
}
}
} else {
userListView.model = contactsModel;
}
}
}
StatusButton {
implicitHeight: 44
enabled: (tagSelector.namesModel.count > 0)
text: "Confirm"
}
}
contentItem: Item {
anchors.fill: parent
anchors.topMargin: headerRow.height + 16
Item {
anchors.fill: parent
visible: (contactsModel.count > 0)
StatusBaseText {
id: contactsLabel
font.pixelSize: 15
anchors.left: parent.left
anchors.leftMargin: 8
color: Theme.palette.baseColor1
text: qsTr("Contacts")
}
Control {
width: 360
anchors {
top: contactsLabel.bottom
topMargin: 8//Style.current.padding
bottom: !statusPopupMenuBackgroundContent.visible ? parent.bottom : undefined
bottomMargin: 20//Style.current.bigPadding
}
height: 16 + (!statusPopupMenuBackgroundContent.visible ? parent.height :
(((userListView.count * 64) > parent.height) ? parent.height : (userListView.count * 64)))
x: (statusPopupMenuBackgroundContent.visible && (tagSelector.namesModel.count > 0) &&
((tagSelector.textEdit.x + 24 + statusPopupMenuBackgroundContent.width) < parent.width))
? (tagSelector.textEdit.x + 24) : 0
background: Rectangle {
id: statusPopupMenuBackgroundContent
anchors.fill: parent
visible: (tagSelector.sortedList.count > 0)
color: Theme.palette.statusPopupMenu.backgroundColor
radius: 8
layer.enabled: true
layer.effect: DropShadow {
width: statusPopupMenuBackgroundContent.width
height: statusPopupMenuBackgroundContent.height
x: statusPopupMenuBackgroundContent.x
visible: statusPopupMenuBackgroundContent.visible
source: statusPopupMenuBackgroundContent
horizontalOffset: 0
verticalOffset: 4
radius: 12
samples: 25
spread: 0.2
color: Theme.palette.dropShadow
}
}
contentItem: ListView {
id: userListView
anchors.fill: parent
anchors.topMargin: 8
anchors.bottomMargin: 8
clip: true
model: contactsModel
ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded
}
boundsBehavior: Flickable.StopAtBounds
delegate: Item {
id: wrapper
anchors.right: parent.right
anchors.left: parent.left
height: 64
property bool hovered: false
Rectangle {
id: rectangle
anchors.fill: parent
anchors.rightMargin: 8
anchors.leftMargin: 8
radius: 8
visible: (tagSelector.sortedList.count > 0)
color: (wrapper.hovered) ? Theme.palette.baseColor2 : "transparent"
}
StatusSmartIdenticon {
id: contactImage
anchors.left: parent.left
anchors.leftMargin: 16//Style.current.padding
anchors.verticalCenter: parent.verticalCenter
name: model.name
icon: StatusIconSettings {
width: 28
height: 28
letterSize: 15
}
image: StatusImageSettings {
width: 28
height: 28
source: model.icon
isIdenticon: model.isIdenticon
}
}
StatusBaseText {
id: contactInfo
text: model.name
anchors.right: parent.right
anchors.rightMargin: 8
anchors.left: contactImage.right
anchors.leftMargin: 16
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
color: Theme.palette.directColor1
font.weight: Font.Medium
font.pixelSize: 15
}
MouseArea {
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
hoverEnabled: true
onEntered: {
wrapper.hovered = true;
}
onExited: {
wrapper.hovered = false;
}
onClicked: {
tagSelector.insertTag(model.name, model.publicId);
}
}
}
}
}
Component.onCompleted: {
if (visible) {
tagSelector.textEdit.forceActiveFocus();
}
}
}
StatusBaseText {
visible: (contactsModel.count === 0)
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: 15
color: Theme.palette.baseColor1
text: qsTr("You can only send direct messages to your Contacts. \n\n
Send a contact request to the person you would like to chat with, you will be\n able to
chat with them once they have accepted your contact request.")
Component.onCompleted: {
if (visible) {
tagSelector.enabled = false;
}
}
}
}
}
+38 -192
View File
@@ -1,4 +1,5 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
@@ -11,6 +12,7 @@ import "data" 1.0
StatusAppThreePanelLayout {
id: root
property bool createChat: false
leftPanel: Item {
anchors.fill: parent
@@ -23,113 +25,35 @@ StatusAppThreePanelLayout {
text: "Chat"
}
Item {
RowLayout {
id: searchInputWrapper
anchors.top: headline.bottom
anchors.topMargin: 16
width: parent.width
height: searchInput.height
anchors.top: headline.bottom
anchors.topMargin: 16
anchors.right: parent.right
anchors.rightMargin: 8
StatusBaseInput {
id: searchInput
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.right: actionButton.left
anchors.leftMargin: 16
anchors.rightMargin: 16
height: 36
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: 17
implicitHeight: 36
topPadding: 8
bottomPadding: 0
placeholderText: "Search"
icon.name: "search"
}
StatusRoundButton {
id: actionButton
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 8
width: 32
height: 32
StatusIconTabButton {
icon.name: "public-chat"
}
type: StatusRoundButton.Type.Secondary
icon.name: "add"
state: "default"
onClicked: chatContextMenu.popup(actionButton.width-chatContextMenu.width, actionButton.height + 4)
states: [
State {
name: "default"
PropertyChanges {
target: actionButton
icon.rotation: 0
highlighted: false
}
},
State {
name: "pressed"
PropertyChanges {
target: actionButton
icon.rotation: 45
highlighted: true
}
}
]
transitions: [
Transition {
from: "default"
to: "pressed"
RotationAnimation {
duration: 150
direction: RotationAnimation.Clockwise
easing.type: Easing.InCubic
}
},
Transition {
from: "pressed"
to: "default"
RotationAnimation {
duration: 150
direction: RotationAnimation.Counterclockwise
easing.type: Easing.OutCubic
}
}
]
StatusPopupMenu {
id: chatContextMenu
onOpened: {
actionButton.state = "pressed"
}
onClosed: {
actionButton.state = "default"
}
StatusMenuItem {
text: "Start new chat"
icon.name: "private-chat"
}
StatusMenuItem {
text: "Start group chat"
icon.name: "group-chat"
}
StatusMenuItem {
text: "Join public chat"
icon.name: "public-chat"
}
StatusMenuItem {
text: "Communities"
icon.name: "communities"
}
StatusIconTabButton {
icon.name: "edit"
onClicked: {
root.createChat = !root.createChat;
}
}
}
@@ -149,10 +73,7 @@ StatusAppThreePanelLayout {
StatusChatList {
anchors.horizontalCenter: parent.horizontalCenter
chatListItems.model: Models.demoChatListItems
selectedChatId: "0"
onChatItemSelected: selectedChatId = id
model: Models.demoChatListItems
onChatItemUnmuted: {
for (var i = 0; i < Models.demoChatListItems.count; i++) {
let item = Models.demoChatListItems.get(i);
@@ -204,6 +125,25 @@ StatusAppThreePanelLayout {
}
}
centerPanel: Loader {
anchors.fill: parent
sourceComponent: root.createChat ? createChatView : chatChannelView
}
Component {
id: createChatView
CreateChatView {
contactsModel: Models.dummyContactsModel
}
}
Component {
id: chatChannelView
ChatChannelView {
model: Models.chatMessagesModel
}
}
rightPanel: Item {
anchors.fill: parent
@@ -251,98 +191,4 @@ StatusAppThreePanelLayout {
}
}
}
centerPanel: ListView {
id: messageList
anchors.fill: parent
anchors.margins: 15
clip: true
model: Models.chatMessagesModel
delegate: StatusMessage {
id: delegate
width: parent.width
audioMessageInfoText: "Audio Message"
cancelButtonText: "Cancel"
saveButtonText: "Save"
loadingImageText: "Loading image..."
errorLoadingImageText: "Error loading the image"
resendText: "Resend"
pinnedMsgInfoText: "Pinned by"
messageDetails: StatusMessageDetails {
contentType: model.contentType
messageContent: model.messageContent
amISender: model.amIsender
displayName: model.userName
secondaryName: model.localName !== "" && model.ensName.startsWith("@") ? model.ensName: ""
chatID: model.chatKey
profileImage: StatusImageSettings {
width: 40
height: 40
source: model.profileImage
isIdenticon: model.isIdenticon
}
messageText: model.message
hasMention: model.hasMention
contactType: model.contactType
isPinned: model.isPinned
pinnedBy: model.pinnedBy
hasExpired: model.hasExpired
}
timestamp.text: "10:00 am"
timestamp.tooltip.text: "10:01 am"
// reply related data
isAReply: model.isReply
replyDetails: StatusMessageDetails {
amISender: model.isReply ? model.replyAmISender : ""
displayName: model.isReply ? model.replySenderName: ""
profileImage: StatusImageSettings {
width: 20
height: 20
source: model.isReply ? model.replyProfileImage: ""
isIdenticon: model.isReply ? model.replyIsIdenticon: ""
}
messageText: model.isReply ? model.replyMessageText: ""
contentType: model.replyContentType
messageContent: model.replyMessageContent
}
quickActions: [
StatusFlatRoundButton {
id: emojiBtn
width: 32
height: 32
icon.name: "reaction-b"
type: StatusFlatRoundButton.Type.Tertiary
tooltip.text: "Add reaction"
},
StatusFlatRoundButton {
id: replyBtn
width: 32
height: 32
icon.name: "reply"
type: StatusFlatRoundButton.Type.Tertiary
tooltip.text: "Reply"
},
StatusFlatRoundButton {
width: 32
height: 32
icon.name: "tiny/edit"
type: StatusFlatRoundButton.Type.Tertiary
tooltip.text: "Edit"
onClicked: {
delegate.editMode = !delegate.editMode
}
},
StatusFlatRoundButton {
id: otherBtn
width: 32
height: 32
icon.name: "more"
type: StatusFlatRoundButton.Type.Tertiary
tooltip.text: "More"
}
]
}
}
}
+4 -3
View File
@@ -77,11 +77,9 @@ StatusAppThreePanelLayout {
draggableItems: true
draggableCategories: false
chatList.model: Models.demoCommunityChatListItems
categoryList.model: Models.demoCommunityCategoryItems
model: Models.demoCommunityChatListItems
showCategoryActionButtons: true
onChatItemSelected: selectedChatId = id
categoryPopupMenu: StatusPopupMenu {
@@ -268,6 +266,9 @@ StatusAppThreePanelLayout {
image.source: model.source
image.isIdenticon: model.isIdenticon
isOnline: model.isOnline
ringSettings.ringSpecModel: model.ringSpecModel
ringSettings.distinctiveColors: Theme.palette.identiconRingColors
ringSettings.totalRingUnits: model.totalRingUnits
}
}
}
+387 -101
View File
@@ -4,122 +4,268 @@ import StatusQ.Components 0.1
QtObject {
property ListModel demoChatListItems: ListModel {
property ListModel dummyContactsModel: ListModel {
ListElement {
publicId: "0x0"
name: "Maria"
icon: ""
isIdenticon: false
onlineStatus: 3
}
ListElement {
publicId: "0x1"
name: "James"
icon: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
isIdenticon: false
onlineStatus: 1
}
ListElement {
publicId: "0x2"
name: "Paul"
icon: ""
isIdenticon: false
onlineStatus: 2
}
ListElement {
publicId: "0x3"
name: "Tracy"
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
isIdenticon: true
onlineStatus: 3
}
ListElement {
publicId: "0x4"
name: "Nick"
icon: ""
isIdenticon: false
onlineStatus: 3
}
ListElement {
publicId: "0x5"
name: "Steven"
icon: ""
isIdenticon: false
onlineStatus: 2
}
ListElement {
publicId: "0x6"
name: "Helen"
icon: ""
isIdenticon: false
onlineStatus: 3
}
}
property var demoChatListItems: ListModel {
id: demoChatListItems
ListElement {
chatId: "0"
itemId: "x012340000"
name: "#status"
chatType: StatusChatListItem.Type.PublicChat
muted: false
unreadMessagesCount: 0
mentionsCount: 0
icon: ""
isIdenticon: false
color: "blue"
description: ""
type: StatusChatListItem.Type.PublicChat
hasUnreadMessages: true
notificationsCount: 0
muted: false
active: false
position: 0
isCategory: false
subItems: []
}
ListElement {
chatId: "1"
itemId: "x012340001"
name: "status-desktop"
chatType: StatusChatListItem.Type.PublicChat
muted: false
icon: ""
isIdenticon: false
color: "red"
unreadMessagesCount: 1
mentionsCount: 1
description: ""
type: StatusChatListItem.Type.PublicChat
hasUnreadMessages: true
notificationsCount: 1
muted: false
active: false
position: 1
isCategory: false
subItems: []
}
ListElement {
chatId: "2"
itemId: "x012340002"
name: "Amazing Funny Squirrel"
chatType: StatusChatListItem.Type.OneToOneChat
muted: false
color: "green"
identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
unreadMessagesCount: 0
position: 2
}
ListElement {
chatId: "3"
name: "Black Ops"
chatType: StatusChatListItem.Type.GroupChat
muted: false
color: "purple"
unreadMessagesCount: 0
position: 3
}
ListElement {
chatId: "4"
name: "Spectacular Growing Otter"
chatType: StatusChatListItem.Type.OneToOneChat
muted: true
color: "Orange"
unreadMessagesCount: 0
position: 4
}
ListElement {
chatId: "5"
name: "channel-with-a-super-duper-long-name"
chatType: StatusChatListItem.Type.PublicChat
muted: false
isIdenticon: true
color: "green"
unreadMessagesCount: 0
description: ""
type: StatusChatListItem.Type.OneToOneChat
hasUnreadMessages: false
notificationsCount: 0
muted: false
active: true
position: 2
isCategory: false
subItems: []
}
ListElement {
itemId: "x012340003"
name: "Black Ops"
icon: ""
isIdenticon: false
color: "purple"
description: ""
type: StatusChatListItem.Type.OneToOneChat
hasUnreadMessages: false
notificationsCount: 0
muted: false
active: false
position: 3
isCategory: false
subItems: []
}
ListElement {
itemId: "x012340004"
name: "Spectacular Growing Otter"
icon: ""
isIdenticon: false
color: "orange"
description: ""
type: StatusChatListItem.Type.OneToOneChat
hasUnreadMessages: false
notificationsCount: 0
muted: false
active: false
position: 4
isCategory: false
subItems: []
}
ListElement {
itemId: "x012340005"
name: "channel-with-a-super-duper-long-name"
icon: ""
isIdenticon: false
color: "green"
description: ""
type: StatusChatListItem.Type.PublicChat
hasUnreadMessages: false
notificationsCount: 0
muted: false
active: false
position: 5
isCategory: false
subItems: []
}
}
property var demoCommunityChatListItems: ListModel {
id: demoCommunityChatListItems
ListElement {
chatId: "0"
itemId: "x012340000"
name: "general"
chatType: StatusChatListItem.Type.CommunityChat
muted: false
unreadMessagesCount: 0
icon: ""
isIdenticon: false
color: "orange"
description: ""
type: StatusChatListItem.Type.Unknown0
hasUnreadMessages: true
notificationsCount: 0
muted: false
active: false
position: 0
isCategory: true
subItems: []
}
ListElement {
chatId: "1"
name: "random"
chatType: StatusChatListItem.Type.CommunityChat
itemId: "x0125340000"
name: "Pink Channel"
icon: ""
isIdenticon: false
color: "pink"
description: ""
type: StatusChatListItem.Type.CommunityChat
hasUnreadMessages: true
notificationsCount: 0
muted: false
unreadMessagesCount: 0
color: "orange"
categoryId: "public"
active: false
position: 0
isCategory: false
subItems: []
}
ListElement {
chatId: "2"
name: "watercooler"
chatType: StatusChatListItem.Type.CommunityChat
muted: false
unreadMessagesCount: 0
color: "orange"
categoryId: "public"
position: 1
}
ListElement {
chatId: "3"
name: "language-design"
chatType: StatusChatListItem.Type.CommunityChat
muted: false
unreadMessagesCount: 0
color: "orange"
categoryId: "dev"
position: 0
}
}
property var demoCommunityCategoryItems: ListModel {
id: demoCommunityCategoryItems
ListElement {
categoryId: "public"
itemId: "x012340001"
name: "Public"
position: 0
icon: ""
isIdenticon: false
color: "orange"
description: ""
type: StatusChatListItem.Type.Unknown0
hasUnreadMessages: false
notificationsCount: 0
muted: false
active: true
position: 1
isCategory: true
subItems: [
ListElement {
itemId: "x012340002"
parentItemId: "x012340001"
name: "random"
icon: ""
isIdenticon: false
color: "orange"
description: ""
hasUnreadMessages: true
notificationsCount: 4
muted: false
active: false
position: 0
},
ListElement {
itemId: "x012340003"
parentItemId: "x012340001"
name: "watercooler"
icon: ""
isIdenticon: false
color: "orange"
description: ""
hasUnreadMessages: false
notificationsCount: 0
muted: false
active: true
position: 1
}
]
}
ListElement {
categoryId: "dev"
itemId: "x012340004"
name: "Development"
position: 1
icon: ""
isIdenticon: false
color: "orange"
description: ""
type: StatusChatListItem.Type.Unknown0
hasUnreadMessages: false
notificationsCount: 0
muted: false
active: false
position: 2
isCategory: true
subItems: [
ListElement {
itemId: "x012340005"
parentItemId: "x012340004"
name: "language-design"
icon: ""
isIdenticon: false
color: "orange"
description: ""
hasUnreadMessages: false
notificationsCount: 0
muted: true
active: false
position: 0
}
]
}
}
@@ -351,7 +497,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f5789"
contactType: 2
isMutualContact: true
trustIndicator: StatusContactVerificationIcons.TrustedType.None
hasMention: false
editMode: false
isReply: false
@@ -379,7 +526,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f2333"
contactType: 3
isMutualContact: true
trustIndicator: StatusContactVerificationIcons.TrustedType.Verified
hasMention: false
editMode: false
isReply: false
@@ -406,7 +554,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAkUlEQVR4nOzYwQmDQBQG4SSkl3SQyizDyuzAavTi0cPK8sPwM9/Rw8rw4KH7eZUwhMYQGkNoDKGpCfmmDl63/bh7vvx/78T7aiZiCI0hNMMbJL2FZs+vmYghNIbQTG+cp9smtf1qJmIIjSEKqZmIITSG0Azfa6W/qfxDvBhCY4hCaiZiCI0hNIbQGEJzBgAA///3pSBjX42sYAAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f2333"
contactType: 3
isMutualContact: true
trustIndicator: StatusContactVerificationIcons.TrustedType.Verified
hasMention: false
editMode: false
isReply: false
@@ -433,7 +582,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f6789"
contactType: 4
isMutualContact: false
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
hasMention: false
editMode: false
isReply: false
@@ -461,7 +611,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f1234"
contactType: 0
isMutualContact: true
trustIndicator: StatusContactVerificationIcons.TrustedType.None
hasMention: false
editMode: false
isReply: false
@@ -489,7 +640,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f1234"
contactType: 0
isMutualContact: false
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
hasMention: false
editMode: false
isReply: false
@@ -517,7 +669,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f1234"
contactType: 0
isMutualContact: false
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
hasMention: true
editMode: false
isReply: false
@@ -546,7 +699,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f1234"
contactType: 0
isMutualContact: false
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
hasMention: false
editMode: false
isReply: true
@@ -575,7 +729,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f1234"
contactType: 0
isMutualContact: false
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
hasMention: false
editMode: false
isReply: true
@@ -604,7 +759,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f1234"
contactType: 0
isMutualContact: false
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
hasMention: false
editMode: false
isReply: true
@@ -633,7 +789,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f1234"
contactType: 0
isMutualContact: false
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
hasMention: false
editMode: false
isReply: true
@@ -661,7 +818,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f1234"
contactType: 0
isMutualContact: false
trustIndicator: StatusContactVerificationIcons.TrustedType.Verified
hasMention: false
editMode: false
isReply: false
@@ -688,7 +846,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f1234"
contactType: 0
isMutualContact: true
trustIndicator: StatusContactVerificationIcons.TrustedType.None
hasMention: false
editMode: false
isReply: false
@@ -715,7 +874,8 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
profileImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDKExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
chatKey: "0x04d1bed19c523299cbd07ddec7b8949ad7dd923819a68e0b733c9c0bc38cde276bd256f098e755f8f028395c2c91f438a22adaff6caded060b7cc0ef3f470f1234"
contactType: 0
isMutualContact: true
trustIndicator: StatusContactVerificationIcons.TrustedType.None
hasMention: false
editMode: false
isReply: false
@@ -737,36 +897,162 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
nickName: "This is an example"
userName: "annabelle"
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
trustIndicator: StatusMemberListItem.TrustedType.Verified
trustIndicator: StatusContactVerificationIcons.TrustedType.Verified
isMutualContact: true
isOnline: true
source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
isIdenticon: true
totalRingUnits: 25
ringSpecModel: [ ListElement {colorId: 13; segmentLength: 5},
ListElement {colorId: 31; segmentLength: 5},
ListElement {colorId: 10; segmentLength: 1},
ListElement {colorId: 2; segmentLength: 5},
ListElement {colorId: 26; segmentLength: 2},
ListElement {colorId: 19; segmentLength: 4},
ListElement {colorId: 28; segmentLength: 3} ]
}
ListElement {
nickName: "carmen.eth"
trustIndicator: StatusMemberListItem.TrustedType.Untrustworthy
userName: ""
chatKey: ""
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
isMutualContact: false
isOnline: false
source: ""
isIdenticon: false
}
ListElement {
nickName: "This girl I know from work"
userName: "annabelle"
chatKey: ""
trustIndicator: StatusContactVerificationIcons.TrustedType.None
isMutualContact: false
isOnline: true
source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAiElEQVR4nOzXUQpAQBRGYWQvLNAyLJDV8C5qpiGnv/M9al5Ot27X0IUwhMYQGkNoDKGJCRlLH67bftx9X+ap/+P9VcxEDK
ExhKZ4a9Uq3TZviZmIITSG0DRvlqcbqVbrlouZiCE0htD4h0hjCI0hNN5aNIbQGKKPxEzEEBpDaAyhMYTmDAAA//+gYCErzmCpCQAAAABJRU5ErkJggg=="
isIdenticon: true
totalRingUnits: 25
ringSpecModel: [ ListElement {colorId: 11; segmentLength: 1},
ListElement {colorId: 23; segmentLength: 5},
ListElement {colorId: 23; segmentLength: 5},
ListElement {colorId: 10; segmentLength: 4},
ListElement {colorId: 15; segmentLength: 3},
ListElement {colorId: 26; segmentLength: 2},
ListElement {colorId: 29; segmentLength: 5} ]
}
ListElement {
nickName: "Mark Cuban"
userName: "annabelle"
chatKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
trustIndicator: StatusMemberListItem.TrustedType.Untrustworthy
trustIndicator: StatusContactVerificationIcons.TrustedType.Untrustworthy
isMutualContact: true
isOnline: false
source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
isIdenticon: true
source: ""
isIdenticon: false
totalRingUnits: 25
ringSpecModel: [ ListElement {colorId: 0; segmentLength: 1},
ListElement {colorId: 28; segmentLength: 1},
ListElement {colorId: 31; segmentLength: 1},
ListElement {colorId: 22; segmentLength: 4},
ListElement {colorId: 28; segmentLength: 3},
ListElement {colorId: 27; segmentLength: 5},
ListElement {colorId: 7; segmentLength: 5},
ListElement {colorId: 13; segmentLength: 1},
ListElement {colorId: 25; segmentLength: 4}]
}
}
// App Section Types:
// chat: 0
// community: 1
// wallet: 2
// browser: 3
// nodeManagement: 4
// profileSettings: 5
// apiDocumentation: 100
// demoApp: 101
property ListModel mainAppSectionsModel: ListModel {
ListElement {
sectionId: "mainApp"
sectionType: 100
name: "API Documentation"
active: true
image: ""
icon: "edit"
color: ""
hasNotification: false
notificationsCount: 0
}
ListElement {
sectionId: "demoApp"
sectionType: 101
name: "Demo Application"
active: false
image: ""
icon: "status"
color: ""
hasNotification: false
notificationsCount: 0
}
}
property ListModel demoAppSectionsModel: ListModel {
ListElement {
sectionId: "chat"
sectionType: 0
name: "Chat"
active: true
image: ""
icon: "chat"
color: ""
hasNotification: false
notificationsCount: 0
}
ListElement {
sectionId: "0x123456789"
sectionType: 1
name: "Status Community"
active: false
image: "https://assets.brandfetch.io/51a495de903c46a.png"
icon: ""
color: ""
hasNotification: false
notificationsCount: 0
}
ListElement {
sectionId: "wallet"
sectionType: 2
name: "Wallet"
active: false
image: ""
icon: "wallet"
color: ""
hasNotification: false
notificationsCount: 0
}
ListElement {
sectionId: "browser"
sectionType: 3
name: "Browser"
active: false
image: ""
icon: "bigger/browser"
color: ""
hasNotification: false
notificationsCount: 0
}
ListElement {
sectionId: "profile"
sectionType: 6
name: "Profile"
active: false
image: ""
icon: "bigger/settings"
color: ""
hasNotification: true
notificationsCount: 0
}
}
}
+71 -29
View File
@@ -12,6 +12,8 @@ import StatusQ.Components 0.1
import StatusQ.Layout 0.1
import StatusQ.Platform 0.1
import "demoapp/data" 1.0
StatusWindow {
id: rootWindow
width: Qt.platform.os == "ios" || Qt.platform.os == "android" ? Screen.width
@@ -31,11 +33,33 @@ StatusWindow {
Component.onCompleted: {
Theme.palette = lightTheme
apiDocsButton.checked = true
rootWindow.updatePosition();
}
QtObject {
id: appSectionType
readonly property int chat: 0
readonly property int community: 1
readonly property int wallet: 2
readonly property int browser: 3
readonly property int nodeManagement: 4
readonly property int profileSettings: 5
readonly property int apiDocumentation: 100
readonly property int demoApp: 101
}
function setActiveItem(sectionId) {
for (var i = 0; i < Models.mainAppSectionsModel.count; i++) {
let item = Models.mainAppSectionsModel.get(i)
if (item.sectionId !== sectionId) {
Models.mainAppSectionsModel.setProperty(i, "active", false);
continue
}
Models.mainAppSectionsModel.setProperty(i, "active", true);
}
}
StatusAppLayout {
id: appLayout
anchors.fill: parent
@@ -43,37 +67,36 @@ StatusWindow {
appNavBar: StatusAppNavBar {
height: rootWindow.height
navBarChatButton: StatusNavBarTabButton {
icon.name: "refresh"
tooltip.text: "Reload App"
onClicked: app.restartQml()
}
communityTypeRole: "sectionType"
communityTypeValue: appSectionType.community
sectionModel: Models.mainAppSectionsModel
navBarTabButtons: [
StatusNavBarTabButton {
id: apiDocsButton
icon.name: "edit"
tooltip.text: "API Documentation"
onClicked: {
stackView.clear()
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: {
stackView.clear()
if(model.sectionType === appSectionType.apiDocumentation)
{
stackView.push(libraryDocumentationCmp)
checked = !checked
demoAppButton.checked = false
rootWindow.setActiveItem(sectionId)
}
},
StatusNavBarTabButton {
id: demoAppButton
icon.name: "status"
tooltip.text: "Demo Application"
checked: stackView.currentItem == demoAppCmp
onClicked: {
stackView.clear()
else if(model.sectionType === appSectionType.demoApp)
{
stackView.push(demoAppCmp)
checked = !checked
apiDocsButton.checked = false
rootWindow.setActiveItem(model.sectionId)
}
}
]
}
}
appView: StackView {
@@ -206,6 +229,11 @@ StatusWindow {
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
StatusNavigationListItem {
title: "StatusPinInput"
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
StatusListSectionHeadline { text: "StatusQ.Components" }
StatusNavigationListItem {
title: "StatusAddress"
@@ -232,6 +260,21 @@ StatusWindow {
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page("StatusExpandableSettingsItem");
}
StatusNavigationListItem {
title: "StatusTagSelector"
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
StatusNavigationListItem {
title: "StatusToastMessage"
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
StatusNavigationListItem {
title: "StatusWizardStepper"
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
StatusListSectionHeadline { text: "StatusQ.Popup" }
StatusNavigationListItem {
title: "StatusPopupMenu"
@@ -347,8 +390,7 @@ StatusWindow {
}
DemoApp {
id: demoApp
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
anchors.centerIn: parent
}
DropShadow {
anchors.fill: demoApp
+75
View File
@@ -0,0 +1,75 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core.Theme 0.1
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Controls.Validators 0.1
Column {
id: root
spacing: 25
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
// PIN input that accepts only numbers
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.palette.directColor1
text: "Enter Keycard PIN"
font.pixelSize: 30
font.bold: true
}
StatusPinInput {
id: numbersPinInput
anchors.horizontalCenter: parent.horizontalCenter
validator: StatusIntValidator{bottom: 0; top: 999999;}
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.palette.dangerColor1
text: "Only numbers allowed"
font.pixelSize: 16
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.palette.directColor1
text: "Introduced PIN: " + numbersPinInput.pinInput
font.pixelSize: 12
}
// PIN input that accepts input depending on the regular expression definition
StatusBaseText {
topPadding: 100
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.palette.directColor1
text: "Enter another Keycard PIN"
font.pixelSize: 30
font.bold: true
}
StatusPinInput {
id: regexPinInput
anchors.horizontalCenter: parent.horizontalCenter
validator: StatusRegularExpressionValidator { regularExpression: /[0-9A-Za-z@]+/ }
circleDiameter: 22
circleSpacing: 22
pinLen: 7
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.palette.dangerColor1
text: "Only alphanumeric characters and '@' allowed"
font.pixelSize: 16
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.palette.directColor1
text: "Introduced PIN: " + regexPinInput.pinInput
font.pixelSize: 12
}
}
+56
View File
@@ -0,0 +1,56 @@
import QtQuick 2.14
import StatusQ.Components 0.1
Item {
id: root
anchors.fill: parent
property ListModel asortedContacts: ListModel {
ListElement {
publicId: "0x0"
name: "Maria"
icon: ""
isIdenticon: false
onlineStatus: 3
}
ListElement {
publicId: "0x1"
name: "James"
icon: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
isIdenticon: false
onlineStatus: 1
}
ListElement {
publicId: "0x2"
name: "Paul"
icon: ""
isIdenticon: false
onlineStatus: 2
}
ListElement {
publicId: "0x3"
name: "Tracy"
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
isIdenticon: true
onlineStatus: 3
}
ListElement {
publicId: "0x4"
name: "Nick"
icon: ""
isIdenticon: false
onlineStatus: 3
}
}
StatusTagSelector {
id: tagSelector
width: 650
height: 44
anchors.centerIn: parent
namesModel: root.asortedContacts
toLabelText: qsTr("To: ")
warningText: qsTr("5 USER LIMIT REACHED")
}
}
+40
View File
@@ -0,0 +1,40 @@
import QtQuick 2.14
import StatusQ.Components 0.1
Item {
id: root
anchors.fill: parent
Column {
id: toastArea
anchors.centerIn: parent
spacing: 8
Repeater {
id: toastRepeater
width: parent.width
height: childrenRect.height
model: [
{"title":"anna.eth wants to verify your identity", "subTitle":"Provide the code in the letter I sent to you on February 1st.", "icon":"contact", "loading":false, "type":0,"url":""},
{"title":"Verification Request Sent", "subTitle":"", "icon":"checkmark-circle", "loading":false, "type":1,"url":""},
{"title":"Collectible is being minted...", "subTitle":"View on Etherscan", "icon":"", "loading":true, "type":0,"url":"http://google.com"},
{"title":"Contact request sent", "subTitle":"", "icon":"checkmark-circle", "loading":false, "type":1,"url":""}
]
delegate: StatusToastMessage {
primaryText: modelData.title
secondaryText: modelData.subTitle
icon.name: modelData.icon
loading: modelData.loading
type: modelData.type
linkUrl: modelData.url
onLinkActivated: {
Qt.openUrlExternally(link);
}
//simulate open
Component.onCompleted: {
open = true;
}
}
}
}
}
+100
View File
@@ -0,0 +1,100 @@
import QtQuick 2.14
import StatusQ.Core 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1
Item {
id: root
width: 800
height: 100
//Simulate animation between steps
property bool stepsCompleted: false
function reset() {
for (var i = 0; i < stepsListModel.count; i++) {
stepsListModel.setProperty(i, "loading", false);
stepsListModel.setProperty(i, "stepCompleted", false);
step1.loadingTime = 0;
step2.loadingTime = 0;
root.stepsCompleted = false;
}
}
ListModel {
id: stepsListModel
ListElement {description:"Send Request"; loadingTime: 0; stepCompleted: false}
ListElement {description:"Receive Response"; loadingTime: 0; stepCompleted: false}
ListElement {description:"Confirm Identity"; loadingTime: 0; stepCompleted: false}
}
Shortcut {
sequence: "Ctrl+R"
onActivated: {
if (!root.stepsCompleted) {
animate.running = true;
} else {
root.reset();
}
}
}
StatusBaseText {
id: indicLabel
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.palette.directColor1
text: "Press Ctrl+R to run the animation"
font.pixelSize: 17
}
SequentialAnimation {
id: animate
ScriptAction {
id: step1
property int loadingTime: 0
Behavior on loadingTime { NumberAnimation { duration: 2000 }}
onLoadingTimeChanged: {
stepsListModel.setProperty(1, "loadingTime", step1.loadingTime);
}
script: {
step1.loadingTime = 2000;
stepsListModel.setProperty(0, "loadingTime", step1.loadingTime);
stepsListModel.setProperty(0, "stepCompleted", true);
}
}
PauseAnimation {
duration: 2100
}
ScriptAction {
id: step2
property int loadingTime: 0
Behavior on loadingTime { NumberAnimation { duration: 2000 } }
onLoadingTimeChanged: {
stepsListModel.setProperty(2, "loadingTime", step2.loadingTime);
}
script: {
step2.loadingTime = 2000;
stepsListModel.setProperty(1, "stepCompleted", true);
}
}
PauseAnimation {
duration: 2100
}
ScriptAction {
script: {
stepsListModel.setProperty(2, "stepCompleted", true);
root.stepsCompleted = true;
}
}
}
//simulation code
StatusWizardStepper {
id: wizardStepper
width: (parent.width - 50)
anchors.top: indicLabel.bottom
anchors.topMargin: 16
anchors.horizontalCenter: parent.horizontalCenter
stepsModel: stepsListModel
}
}
+1 -1
View File
@@ -15,7 +15,7 @@ SOURCES += \
handler.cpp \
main.cpp \
sandboxapp.cpp \
spellchecker.cpp
spellchecker.cpp \
!macx {
SOURCES += statuswindow.cpp
+23 -37
View File
@@ -15,8 +15,7 @@ Column {
width: 288
property string categoryId: ""
property string selectedChatId: ""
property alias chatListItems: delegateModel
property var model: []
property bool draggableItems: false
property alias statusChatListItems: statusChatListItems
@@ -24,10 +23,8 @@ Column {
property Component popupMenu
property var filterFn
property var profileImageFn
property var chatNameFn
signal chatItemSelected(string id)
signal chatItemSelected(string categoryId, string id)
signal chatItemUnmuted(string id)
signal chatItemReordered(string id, int from, int to)
@@ -39,17 +36,16 @@ Column {
DelegateModel {
id: delegateModel
model: statusChatList.model
delegate: Item {
id: draggable
width: statusChatListItem.width
height: statusChatListItem.height
property alias chatListItem: statusChatListItem
visible: {
if (!!statusChatList.filterFn) {
return statusChatList.filterFn(model, statusChatList.categoryId)
return statusChatList.filterFn(model)
}
return true
}
@@ -96,34 +92,25 @@ Column {
StatusChatListItem {
id: statusChatListItem
property string profileImage: ""
opacity: dragSensor.active ? 0.0 : 1.0
Component.onCompleted: {
if (typeof statusChatList.profileImageFn === "function") {
profileImage = statusChatList.profileImageFn(model.chatId || model.id) || ""
}
}
originalOrder: model.position
chatId: model.chatId || model.id
categoryId: model.categoryId || ""
name: !!statusChatList.chatNameFn ? statusChatList.chatNameFn(model) : model.name
type: model.chatType
muted: !!model.muted
hasUnreadMessages: !!model.hasUnreadMessages || model.unviewedMessagesCount > 0
hasMention: model.mentionsCount > 0
badge.value: model.chatType === StatusChatListItem.Type.OneToOneChat ?
model.unviewedMessagesCount || 0 :
model.mentionsCount || 0
selected: (model.chatId || model.id) === statusChatList.selectedChatId
icon.color: model.color || ""
image.isIdenticon: !!!profileImage && !!!model.identityImage && !!model.identicon
image.source: profileImage || model.identityImage || model.identicon || ""
chatId: model.itemId
categoryId: model.parentItemId? model.parentItemId : ""
name: model.name
type: !!model.type ? model.type : StatusChatListItem.Type.CommunityChat
muted: model.muted
hasUnreadMessages: model.hasUnreadMessages
notificationsCount: model.notificationsCount
highlightWhenCreated: model.highlight
selected: model.active
icon.color: model.color
image.isIdenticon: model.isIdenticon
image.source: model.icon
sensor.cursorShape: dragSensor.cursorShape
onClicked: {
highlightWhenCreated = false
if (mouse.button === Qt.RightButton && !!statusChatList.popupMenu) {
statusChatListItem.highlighted = true
@@ -132,7 +119,7 @@ Column {
popupMenuSlot.item.openHandler = function () {
if (!!originalOpenHandler) {
originalOpenHandler((model.chatId || model.id))
originalOpenHandler(model.itemId)
}
}
@@ -152,10 +139,10 @@ Column {
return
}
if (!statusChatListItem.selected) {
statusChatList.chatItemSelected(model.chatId || model.id)
statusChatList.chatItemSelected(model.parentItemId, model.itemId)
}
}
onUnmute: statusChatList.chatItemUnmuted(model.chatId || model.id)
onUnmute: statusChatList.chatItemUnmuted(model.itemId)
}
}
@@ -204,9 +191,8 @@ Column {
type: draggable.chatListItem.type
muted: draggable.chatListItem.muted
dragged: true
hasUnreadMessages: draggable.chatListItem.hasUnreadMessages
hasMention: draggable.chatListItem.hasMention
badge.value: draggable.chatListItem.badge.value
hasUnreadMessages: model.hasUnreadMessages
notificationsCount: model.notificationsCount
selected: draggable.chatListItem.selected
icon.color: draggable.chatListItem.icon.color
@@ -20,11 +20,9 @@ Item {
text: "More"
}
property string selectedChatId: ""
property var model: []
property bool showCategoryActionButtons: false
property bool showPopupMenu: true
property alias chatList: statusChatList.chatListItems
property alias categoryList: delegateModel
property alias sensor: sensor
property bool draggableItems: false
property bool draggableCategories: false
@@ -36,7 +34,7 @@ Item {
property Component chatListPopupMenu
property Component popupMenu
signal chatItemSelected(string id)
signal chatItemSelected(string categoryId, string id)
signal chatItemUnmuted(string id)
signal chatItemReordered(string categoryId, string chatId, int from, int to)
signal chatListCategoryReordered(string categoryId, int from, int to)
@@ -71,26 +69,25 @@ Item {
StatusChatList {
id: statusChatList
anchors.horizontalCenter: parent.horizontalCenter
visible: chatListItems.count > 0
selectedChatId: statusChatListAndCategories.selectedChatId
onChatItemSelected: statusChatListAndCategories.chatItemSelected(id)
visible: statusChatList.model.count > 0
onChatItemSelected: statusChatListAndCategories.chatItemSelected(categoryId, id)
onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
onChatItemReordered: statusChatListAndCategories.chatItemReordered(categoryId, id, from, to)
draggableItems: statusChatListAndCategories.draggableItems
model: statusChatListAndCategories.model
filterFn: function (model) {
return !!!model.categoryId
return !model.isCategory
}
popupMenu: statusChatListAndCategories.chatListPopupMenu
}
DelegateModel {
id: delegateModel
model: statusChatListAndCategories.model
delegate: Item {
id: draggable
width: statusChatListCategory.width
height: statusChatListCategory.height
property alias chatListCategory: statusChatListCategory
StatusChatListCategory {
@@ -99,7 +96,7 @@ Item {
property bool dragActive: false
property real startY: 0
property real startX: 0
opacity: dragActive ? 0.0 : 1.0
dragSensor.drag.target: draggedListCategoryLoader.item
@@ -136,16 +133,15 @@ Item {
menuButton.tooltip: statusChatListAndCategories.categoryMenuButtonToolTip
originalOrder: model.position
categoryId: model.categoryId
categoryId: model.itemId
name: model.name
showActionButtons: statusChatListAndCategories.showCategoryActionButtons
addButton.onClicked: statusChatListAndCategories.categoryAddButtonClicked(model.categoryId)
addButton.onClicked: statusChatListAndCategories.categoryAddButtonClicked(model.itemId)
chatList.chatListItems.model: statusChatListAndCategories.chatList.model
chatList.selectedChatId: statusChatListAndCategories.selectedChatId
chatList.onChatItemSelected: statusChatListAndCategories.chatItemSelected(id)
chatList.model: model.subItems
chatList.onChatItemSelected: statusChatListAndCategories.chatItemSelected(categoryId, id)
chatList.onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
chatList.onChatItemReordered: statusChatListAndCategories.chatItemReordered(model.categoryId, id, from, to)
chatList.onChatItemReordered: statusChatListAndCategories.chatItemReordered(model.itemId, id, from, to)
chatList.draggableItems: statusChatListAndCategories.draggableItems
popupMenu: statusChatListAndCategories.categoryPopupMenu
@@ -154,7 +150,7 @@ Item {
// Used to set the initial value of "opened" when the
// model is bound/changed.
opened: {
let openedState = statusChatListAndCategories.openedCategoryState[model.categoryId]
let openedState = statusChatListAndCategories.openedCategoryState[model.itemId]
return openedState !== undefined ? openedState : true // defaults to open
}
@@ -163,7 +159,7 @@ Item {
// as the state would be lost each time the model is
// changed.
onOpenedChanged: {
statusChatListAndCategories.openedCategoryState[model.categoryId] = statusChatListCategory.opened
statusChatListAndCategories.openedCategoryState[model.itemId] = statusChatListCategory.opened
}
}
@@ -212,8 +208,7 @@ Item {
name: draggable.chatListCategory.name
showActionButtons: draggable.chatListCategory.showActionButtons
chatList.chatListItems.model: draggable.chatListCategory.chatList.chatListItems.model
chatList.selectedChatId: draggable.chatListCategory.chatList.selectedChatId
chatList.model: draggable.chatListCategory.chatList.model
}
}
}
@@ -35,11 +35,11 @@ Column {
StatusChatListCategoryItem {
id: statusChatListCategoryItem
title: statusChatListCategory.name
visible: model.isCategory
opened: statusChatListCategory.opened
sensor.pressAndHoldInterval: 150
showMenuButton: showActionButtons && !!statusChatListCategory.popupMenu
highlighted: statusChatListCategory.dragged
sensor.onClicked: {
if (sensor.enabled) {
@@ -68,7 +68,7 @@ Column {
visible: statusChatListCategory.opened
categoryId: statusChatListCategory.categoryId
filterFn: function (model) {
return !!model.categoryId && model.categoryId == statusChatList.categoryId
return !!model.parentItemId && model.parentItemId === statusChatList.categoryId
}
popupMenu: statusChatListCategory.chatListPopupMenu
+12 -8
View File
@@ -18,7 +18,7 @@ Rectangle {
property string name: ""
property alias badge: statusBadge
property bool hasUnreadMessages: false
property bool hasMention: false
property int notificationsCount: 0
property bool muted: false
property StatusImageSettings image: StatusImageSettings {
width: 24
@@ -32,6 +32,7 @@ Rectangle {
}
property int type: StatusChatListItem.Type.PublicChat
property bool highlighted: false
property bool highlightWhenCreated: false
property bool selected: false
property bool dragged: false
property alias sensor: sensor
@@ -98,8 +99,8 @@ Rectangle {
if (statusChatListItem.muted && !hoverHander.hovered && !statusChatListItem.highlighted) {
return 0.4
}
return statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages ||
return statusChatListItem.hasUnreadMessages ||
statusChatListItem.notificationsCount > 0 ||
statusChatListItem.selected ||
statusChatListItem.highlighted ||
statusBadge.visible ||
@@ -141,16 +142,18 @@ Rectangle {
if (statusChatListItem.muted && !hoverHander.hovered && !statusChatListItem.highlighted) {
return Theme.palette.directColor5
}
return statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages ||
return statusChatListItem.hasUnreadMessages ||
statusChatListItem.notificationsCount > 0 ||
statusChatListItem.selected ||
statusChatListItem.highlighted ||
statusChatListItem.highlightWhenCreated ||
hoverHander.hovered ||
statusBadge.visible ? Theme.palette.directColor1 : Theme.palette.directColor4
}
font.weight: !statusChatListItem.muted &&
(statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages ||
(statusChatListItem.hasUnreadMessages ||
statusChatListItem.notificationsCount > 0 ||
statusChatListItem.highlightWhenCreated ||
statusBadge.visible) ? Font.Bold : Font.Medium
font.pixelSize: 15
}
@@ -189,7 +192,8 @@ Rectangle {
color: statusChatListItem.muted ? Theme.palette.primaryColor2 : Theme.palette.primaryColor1
border.width: 4
border.color: color
visible: statusBadge.value > 0
value: statusChatListItem.notificationsCount
visible: statusChatListItem.notificationsCount > 0
}
}
}
+19 -9
View File
@@ -93,6 +93,25 @@ Rectangle {
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()
}
@@ -100,15 +119,6 @@ Rectangle {
Loader {
id: popupMenuSlot
active: !!statusChatToolBar.popupMenu
onLoaded: {
popupMenuSlot.item.closeHandler = function () {
menuButton.highlighted = false
}
popupMenuSlot.item.openHandler = function () {
menuButton.highlighted = true
}
}
}
}
@@ -0,0 +1,79 @@
import QtQuick 2.0
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
Row {
id: root
property bool isMutualContact: false
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
property StatusIconSettings mutualConnectionIcon: StatusIconSettings {
name: "tiny/tiny-contact"
color: Theme.palette.indirectColor1
width: dummyImage.width
height: dummyImage.height
background: StatusIconBackgroundSettings {
width: 10
height: 10
color: Theme.palette.primaryColor1
}
// Only used to get implicit width and height from the actual image
property Image dummyImage: Image {
source: mutualConnectionIcon.name ? "../../assets/img/icons/" + mutualConnectionIcon.name + ".svg": ""
visible: false
}
}
property StatusIconSettings trustContactIcon: StatusIconSettings {
// None and Untrustworthy types, same aspect (Icon will not be visible in case of None type):
name: root.trustIndicator === StatusContactVerificationIcons.TrustedType.Verified ? "tiny/tiny-checkmark" : "tiny/subtract"
color: Theme.palette.indirectColor1
width: dummyImage.width
height: dummyImage.height
background: StatusIconBackgroundSettings {
width: 10
height: 10
color: root.trustIndicator === StatusContactVerificationIcons.TrustedType.Verified ? Theme.palette.primaryColor1 : Theme.palette.dangerColor1
}
// Only used to get implicit width and height from the actual image
property Image dummyImage: Image {
source: trustContactIcon.name ? "../../assets/img/icons/" + trustContactIcon.name + ".svg": ""
visible: false
}
}
enum TrustedType {
None, //0
Verified, //1
Untrustworthy //2
}
spacing: 4
visible: root.isMutualContact || (root.trustIndicator !== StatusContactVerificationIcons.TrustedType.None)
StatusRoundIcon {
visible: root.isMutualContact
icon.name: root.mutualConnectionIcon.name
icon.width: root.mutualConnectionIcon.width
icon.height: root.mutualConnectionIcon.height
icon.rotation: root.mutualConnectionIcon.rotation
icon.color: root.mutualConnectionIcon.color
icon.background.color: root.mutualConnectionIcon.background.color
icon.background.width: root.mutualConnectionIcon.background.width
icon.background.height: root.mutualConnectionIcon.background.height
}
StatusRoundIcon {
visible: root.trustIndicator !== StatusContactVerificationIcons.TrustedType.None
icon.name: root.trustContactIcon.name
icon.width: root.trustContactIcon.width
icon.height: root.trustContactIcon.height
icon.rotation: root.trustContactIcon.rotation
icon.color: root.trustContactIcon.color
icon.background.color: root.trustContactIcon.background.color
icon.background.width: root.trustContactIcon.background.width
icon.background.height: root.trustContactIcon.background.height
}
}
+22 -61
View File
@@ -13,14 +13,13 @@ Rectangle {
property string titleId: ""
property string title: ""
property string titleAsideText: ""
property bool titleIcon1Visible
property bool titleIcon2Visible
property string subTitle: ""
property string tertiaryTitle: ""
property string label: ""
property real leftPadding: 16
property real rightPadding: 16
property bool enabled: true
property bool highlighted: false
property int type: StatusListItem.Type.Primary
property list<Item> components
@@ -51,31 +50,10 @@ Rectangle {
height: 40
isIdenticon: false
}
property StatusIconSettings titleIcon1: StatusIconSettings {
width: dummyImage.width
height: dummyImage.height
background: StatusIconBackgroundSettings {
width: 10
height: 10
}
// Only used to get implicit width and height from the actual image
property Image dummyImage: Image {
source: titleIcon1.name ? "../../assets/img/icons/" + titleIcon1.name + ".svg": ""
visible: false
}
}
property StatusIconSettings titleIcon2: StatusIconSettings {
width: dummyImage.width
height: dummyImage.height
background: StatusIconBackgroundSettings {
width: 10
height: 10
}
// Only used to get implicit width and height from the actual image
property Image dummyImage: Image {
source: titleIcon2.name ? "../../assets/img/icons/" + titleIcon2.name + ".svg": ""
visible: false
}
property StatusIdenticonRingSettings ringSettings: StatusIdenticonRingSettings {
totalRingUnits: 1
initalAngleRad: 0
ringPxSize: 1.5
}
property alias sensor: sensor
@@ -83,6 +61,7 @@ Rectangle {
property alias statusListItemIcon: iconOrImage
property alias statusListItemTitle: statusListItemTitle
property alias statusListItemTitleAside: statusListItemTitleAsideText
property alias statusListItemTitleIcons: titleIconsRow
property alias statusListItemTitleArea: statusListItemTitleArea
property alias statusListItemSubTitle: statusListItemSubTitle
property alias statusListItemTertiaryTitle: statusListItemTertiaryTitle
@@ -100,7 +79,7 @@ Rectangle {
implicitWidth: 448
implicitHeight: Math.max(64, statusListItemTitleArea.height + 16)
color: {
if (sensor.containsMouse) {
if (sensor.containsMouse || statusListItem.highlighted) {
switch(type) {
case StatusListItem.Type.Primary:
return Theme.palette.baseColor2
@@ -149,13 +128,22 @@ Rectangle {
!!statusListItem.icon.name ||
!!statusListItem.image.source.toString()
badge.border.color: statusListItem.color
ringSettings: statusListItem.ringSettings
}
Item {
id: statusListItemTitleArea
function getStatusListItemTitleAnchorsRight() {
let isIconsRowVisible = false
if(titleIconsRow.item) {
isIconsRowVisible = true//titleIconsRow.item.visible
}
return !statusListItem.titleAsideText && !isIconsRowVisible ? statusListItemTitleArea.right : undefined
}
anchors.left: iconOrImage.active ? iconOrImage.right : parent.left
anchors.right: statusListItemLabel.visible ?
statusListItemLabel.left : statusListItemComponentsSlot.left
anchors.right: statusListItemLabel.visible ? statusListItemLabel.left : statusListItemComponentsSlot.left
anchors.leftMargin: statusListItem.leftPadding
anchors.rightMargin: statusListItem.rightPadding
anchors.verticalCenter: parent.verticalCenter
@@ -168,8 +156,7 @@ Rectangle {
height: visible ? contentHeight : 0
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
anchors.left: parent.left
anchors.right: !statusListItem.titleAsideText && !statusListItem.titleIcon1Visible && !statusListItem.titleIcon2Visible
? parent.right : undefined
anchors.right: !statusListItem.titleAsideText && !titleIconsRow.sourceComponent ? parent.right : undefined
color: {
if (!statusListItem.enabled) {
return Theme.palette.baseColor1
@@ -207,37 +194,12 @@ Rectangle {
visible: !!statusListItem.titleAsideText
}
Row {
Loader {
id: titleIconsRow
spacing: 4
anchors.left: !statusListItem.titleAsideText ? statusListItemTitle.right : statusListItemTitleAsideText.right
anchors.verticalCenter: statusListItemTitle.verticalCenter
anchors.leftMargin: titleIconsRow.spacing
StatusRoundIcon {
visible: statusListItem.titleIcon1Visible
icon.name: statusListItem.titleIcon1.name
icon.width: statusListItem.titleIcon1.width
icon.height: statusListItem.titleIcon1.height
icon.rotation: statusListItem.titleIcon1.rotation
icon.color: statusListItem.titleIcon1.color
icon.background.color: statusListItem.titleIcon1.background.color
icon.background.width: statusListItem.titleIcon1.background.width
icon.background.height: statusListItem.titleIcon1.background.height
}
StatusRoundIcon {
visible: statusListItem.titleIcon2Visible
icon.name: statusListItem.titleIcon2.name
icon.width: statusListItem.titleIcon2.width
icon.height: statusListItem.titleIcon2.height
icon.rotation: statusListItem.titleIcon2.rotation
icon.color: statusListItem.titleIcon2.color
icon.background.color: statusListItem.titleIcon2.background.color
icon.background.width: statusListItem.titleIcon2.background.width
icon.background.height: statusListItem.titleIcon2.background.height
}
}
anchors.leftMargin: 4
}
StatusBaseText {
id: statusListItemSubTitle
@@ -283,7 +245,6 @@ Rectangle {
visible: !!statusListItem.label
}
Row {
id: statusListItemComponentsSlot
anchors.right: parent.right
@@ -10,15 +10,9 @@ StatusListItem {
property string userName: ""
property string chatKey: ""
property bool isMutualContact: false
property var trustIndicator: StatusMemberListItem.TrustedType.None
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
property bool isOnline: false
enum TrustedType {
None, //0
Verified, //1
Untrustworthy //2
}
// Subtitle composition:
function composeSubtitile() {
var compose = ""
@@ -42,8 +36,10 @@ StatusListItem {
// root object settings:
title: root.nickName
titleIcon1Visible: root.isMutualContact
titleIcon2Visible: root.trustIndicator !== StatusMemberListItem.TrustedType.None
statusListItemTitleIcons.sourceComponent: StatusContactVerificationIcons {
isMutualContact: root.isMutualContact
trustIndicator: root.trustIndicator
}
subTitle: composeSubtitile()
statusListItemSubTitle.font.pixelSize: 10
icon.isLetterIdenticon: !root.image.source.toString()
@@ -51,7 +47,7 @@ StatusListItem {
statusListItemIcon.badge.color: root.isOnline ? Theme.palette.successColor1 : Theme.palette.baseColor1
color: sensor.containsMouse ? Theme.palette.baseColor2 : Theme.palette.baseColor4
// Default sizes/positions by design
// Default sizes / positions by design
implicitWidth: 256
implicitHeight: Math.max(56, statusListItemTitleArea.height + leftPadding)
leftPadding: 8
@@ -64,13 +60,4 @@ StatusListItem {
statusListItemIcon.badge.border.width: 2
statusListItemIcon.badge.implicitHeight: 12 // 8 px + 2 px * 2 borders
statusListItemIcon.badge.implicitWidth: 12 // 8 px + 2 px * 2 borders
// Trusted type icons definition:
titleIcon1.name: "tiny/tiny-contact"
titleIcon1.color: Theme.palette.indirectColor1
titleIcon1.background.color: Theme.palette.primaryColor1
// None and Untrustworthy types, same aspect (Icon will not be visible in case of None type):
titleIcon2.name: trustIndicator === StatusMemberListItem.TrustedType.Verified ? "tiny/tiny-checkmark" : "tiny/subtract"
titleIcon2.color: Theme.palette.indirectColor1
titleIcon2.background.color: trustIndicator === StatusMemberListItem.TrustedType.Verified ? Theme.palette.primaryColor1 : Theme.palette.dangerColor1
}
+2 -13
View File
@@ -21,14 +21,6 @@ Rectangle {
Invitation = 7
}
enum ContactType {
STANDARD = 0,
RENAME = 1,
CONTACT = 2,
VERIFIED = 3,
UNTRUSTWORTHY = 4
}
property alias messageHeader: messageHeader
property alias quickActions:quickActionsPanel.quickActions
property alias statusChatInput: editComponent.inputComponent
@@ -108,11 +100,8 @@ Rectangle {
displayName: messageDetails.displayName
secondaryName: messageDetails.secondaryName
tertiaryDetail: messageDetails.chatID
icon1.name: messageDetails.contactType === StatusMessage.ContactType.CONTACT ? "tiny/tiny-contact" : ""
icon2.name: messageDetails.contactType === StatusMessage.ContactType.VERIFIED ? "tiny/tiny-checkmark" :
messageDetails.contactType === StatusMessage.ContactType.UNTRUSTWORTHY ? "tiny/subtract": ""
icon2.background.color: messageDetails.contactType === StatusMessage.ContactType.UNTRUSTWORTHY ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
icon2.color: Theme.palette.indirectColor1
isMutualContact: messageDetails.isMutualContact
trustIndicator: messageDetails.trustIndicator
resendText: statusMessage.resendText
showResendButton: messageDetails.hasExpired && messageDetails.amISender
onClicked: statusMessage.senderNameClicked()
@@ -17,12 +17,13 @@ QtObject {
property string messageText: ""
property int contentType: 0
property string messageContent: ""
property int contactType: 0
property bool isMutualContact: false
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
property bool hasMention: false
property bool isPinned: false
property string pinnedBy: ""
property bool hasExpired: false
property string timestamp: ""
property string timestamp: ""
}
@@ -1,11 +1,13 @@
import QtQuick 2.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
Loader {
id: statusSmartIdenticon
property string name: ""
property int dZ: 100
// Badge color properties must be set if badgeItem.visible = true
property alias badge: statusBadge
@@ -20,6 +22,12 @@ Loader {
height: 40
}
property StatusIdenticonRingSettings ringSettings: StatusIdenticonRingSettings {
totalRingUnits: 1
initalAngleRad: 0
ringPxSize: 1.5
}
sourceComponent: statusSmartIdenticon.icon.isLetterIdenticon ? letterIdenticon :
!!statusSmartIdenticon.image.source.toString() ? roundedImage :
!!statusSmartIdenticon.icon.name.toString() ? roundedIcon : letterIdenticon
@@ -79,6 +87,13 @@ Loader {
}
}
// Next components are painted above main sourceComponent
StatusIdenticonRing {
settings: statusSmartIdenticon.ringSettings
anchors.fill: parent
z: statusSmartIdenticon.dZ/2
}
// State component
StatusBadge {
id: statusBadge
@@ -88,6 +103,6 @@ Loader {
border.width: 3
implicitHeight: 15
implicitWidth: 15
z: 100
z: statusSmartIdenticon.dZ
}
}
@@ -0,0 +1,137 @@
import QtQuick 2.14
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
Item {
id: root
implicitWidth: 448
implicitHeight: 44
property alias textEdit: edit
property alias text: edit.text
property string warningText: ""
property string toLabelText: ""
property int nameCountLimit: 5
property ListModel namesModel: ListModel { }
function find(model, criteria) {
for (var i = 0; i < model.count; ++i) if (criteria(model.get(i))) return model.get(i);
return null;
}
function insertTag(name, id) {
if (!find(namesModel, function(item) { return item.publicId === id }) && namesModel.count < root.nameCountLimit) {
namesModel.insert(namesModel.count, {"name": name, "publicId": id});
addMember(id);
edit.clear();
}
}
signal addMember(string memberId)
signal removeMember(string memberId)
Rectangle {
anchors.fill: parent
radius: 8
color: Theme.palette.baseColor2
RowLayout {
anchors.fill: parent
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 8
StatusBaseText {
Layout.preferredWidth: 22
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
color: Theme.palette.baseColor1
text: root.toLabelText
}
ScrollView {
Layout.fillWidth: true
implicitHeight: 30
Layout.alignment: Qt.AlignVCenter
visible: (namesList.count > 0)
contentWidth: namesList.contentWidth
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
clip: true
ListView {
id: namesList
anchors.fill: parent
model: namesModel
orientation: ListView.Horizontal
spacing: 8
onContentWidthChanged: {
positionViewAtEnd();
}
delegate: Rectangle {
id: nameDelegate
width: (nameText.contentWidth + 34)
height: 30
color: mouseArea.containsMouse ? Theme.palette.miscColor1 : Theme.palette.primaryColor1
radius: 8
StatusBaseText {
id: nameText
anchors.left: parent.left
anchors.leftMargin: 8
anchors.verticalCenter: parent.verticalCenter
color: Theme.palette.indirectColor1
text: name
}
StatusIcon {
anchors.left: nameText.right
anchors.verticalCenter: parent.verticalCenter
color: Theme.palette.indirectColor1
icon: "close"
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
removeMember(publicId);
namesModel.remove(index, 1);
}
}
}
}
}
TextEdit {
id: edit
Layout.fillWidth: true
Layout.preferredHeight: 44
verticalAlignment: Text.AlignVCenter
visible: (namesModel.count < 5)
enabled: visible
focus: true
font.pixelSize: 15
font.family: Theme.palette.baseFont.name
color: Theme.palette.directColor1
Keys.onPressed: {
if ((event.key === Qt.Key_Backspace || event.key === Qt.Key_Escape)
&& getText(cursorPosition, (cursorPosition-1)) === "") {
removeMember(namesModel.get(namesList.count-1).publicId);
namesModel.remove((namesList.count-1), 1);
}
}
}
StatusBaseText {
id: warningTextLabel
visible: (namesModel.count === root.nameCountLimit)
Layout.preferredWidth: 120
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
font.pixelSize: 10
color: Theme.palette.dangerColor1
text: root.nameCountLimit + " " + root.warningText
}
}
}
}
@@ -0,0 +1,182 @@
import QtQuick 2.14
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.13
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
Control {
id: root
width: 343
height: !!secondaryText ? 68 : 48
anchors.right: parent.right
property bool open: false
property string primaryText: ""
property string secondaryText: ""
property bool loading: false
property string iconName: ""
property string linkUrl: ""
property StatusIconSettings icon: StatusIconSettings {
width: 23
height: 23
}
property int type: StatusToastMessage.Type.Default
enum Type {
Default,
Success
}
function open(title, subTitle, iconName, type, loading, url) {
root.primaryText = title;
root.secondaryText = subTitle;
root.icon.name = iconName;
root.type = type;
root.loading = loading;
root.linkUrl = url;
root.open = true;
}
signal close()
signal linkActivated(var link)
states: [
State {
name: "opened"
when: root.open
PropertyChanges {
target: root
anchors.rightMargin: 0
opacity: 1.0
}
},
State {
name: "closed"
when: !root.open
PropertyChanges {
target: root
anchors.rightMargin: -width
opacity: 0.0
}
StateChangeScript {
script: { root.close(); }
}
}
]
transitions: [
Transition {
to: "*"
NumberAnimation { properties: "anchors.rightMargin,opacity"; duration: 400 }
}
]
background: Rectangle {
id: background
anchors.fill: parent
color: Theme.palette.statusToastMessage.backgroundColor
radius: 8
border.color: Theme.palette.baseColor2
layer.enabled: true
layer.effect: DropShadow {
verticalOffset: 3
radius: 8
samples: 15
fast: true
cached: true
color: Theme.palette.dropShadow
}
}
contentItem: Item {
anchors.left: parent.left
anchors.leftMargin: 16
anchors.right: parent.right
anchors.rightMargin: 4
height: parent.height
MouseArea {
anchors.fill: parent
onMouseXChanged: {
root.open = (mouseX < (root.width/3));
}
}
RowLayout {
anchors.fill: parent
spacing: 16
Rectangle {
implicitWidth: 32
implicitHeight: 32
Layout.alignment: Qt.AlignVCenter
radius: (root.width/2)
color: (root.type === StatusToastMessage.Type.Success) ?
Theme.palette.successColor2 : Theme.palette.primaryColor3
Loader {
anchors.centerIn: parent
sourceComponent: root.loading ? loadingInd : statusIcon
Component {
id: loadingInd
StatusLoadingIndicator {
color: (root.type === StatusToastMessage.Type.Success) ?
Theme.palette.successColor1 : Theme.palette.primaryColor1
}
}
Component {
id: statusIcon
StatusIcon {
anchors.centerIn: parent
width: root.icon.width
height: root.icon.height
color: (root.type === StatusToastMessage.Type.Success) ?
Theme.palette.successColor1 : Theme.palette.primaryColor1
icon: root.icon.name
}
}
}
}
Column {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
StatusBaseText {
width: parent.width
font.pixelSize: 13
color: Theme.palette.directColor1
elide: Text.ElideRight
text: root.primaryText
}
StatusBaseText {
width: parent.width
visible: (!root.linkUrl && !!root.secondaryText)
height: visible ? contentHeight : 0
font.pixelSize: 13
color: Theme.palette.baseColor1
text: root.secondaryText
elide: Text.ElideRight
}
StatusSelectableText {
visible: (!!root.linkUrl)
height: visible ? implicitHeight : 0
font.pixelSize: 13
hoveredLinkColor: Theme.palette.primaryColor1
text: "<p><a style=\"text-decoration:none\" href=\'" + root.linkUrl + " \'>" + root.secondaryText + "</a></p>"
onLinkActivated: {
root.linkActivated(root.linkUrl);
}
}
}
StatusFlatRoundButton {
type: StatusFlatRoundButton.Type.Secondary
icon.name: "close"
icon.color: Theme.palette.directColor1
implicitWidth: 30
implicitHeight: 30
onClicked: {
root.open = false;
}
}
}
}
}
@@ -0,0 +1,78 @@
import QtQuick 2.14
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.14
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
Item {
id: wizardWrapper
width: parent.width
height: 56
property ListModel stepsModel: ListModel { }
ListView {
id: repeat
width: childrenRect.width
height: parent.height
anchors.horizontalCenter: parent.horizontalCenter
orientation: ListView.Horizontal
model: stepsModel
delegate: Item {
id: wrapperItem
width: (index === 0) ? descriptionLabel.contentWidth : (wizardWrapper.width / repeat.count)
height: 56
onXChanged: {
//as x changes while delegates are created, direct assignment doesn't work
x = (index === (repeat.count-1)) ? (width+32) : (label.width/2) + 8
}
StatusProgressBar {
id: barBorder
width: visible ? (parent.width - (label.width/2 + 24)) : 0
height: visible ? 8 : 0
visible: (index > 0)
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -12
from: 0
//TODO what is to: here?
to: 2000
value: loadingTime
backgroundColor: "transparent"
backgroundBorderColor: Theme.palette.primaryColor1
fillColor: Theme.palette.primaryColor1
}
Item {
id: label
width: descriptionLabel.contentWidth
height: 56
anchors.left: (index > 0) ? barBorder.right : parent.left
anchors.leftMargin: (index > 0) ? -((width/2) - 24) : 0
Rectangle {
width: 32
height: 32
anchors.horizontalCenter: parent.horizontalCenter
radius: width/2
color: stepCompleted ? Theme.palette.primaryColor1 : "transparent"
border.color: (stepCompleted && (barBorder.visible ? (barBorder.value === barBorder.to) : true))
? "transparent" : Theme.palette.primaryColor1
border.width: 2
StatusBaseText {
anchors.centerIn: parent
text: index+1
font.pixelSize: 17
color: (stepCompleted && (barBorder.visible ? (barBorder.value === barBorder.to) : true))
? Theme.palette.indirectColor1 : Theme.palette.primaryColor1
}
}
StatusBaseText {
id: descriptionLabel
anchors.bottom: parent.bottom
text: description
color: Theme.palette.directColor1
font.pixelSize: 13
}
}
}
}
}
@@ -19,38 +19,8 @@ Item {
property string tertiaryDetail: ""
property string resendText: ""
property bool showResendButton: false
property StatusIconSettings icon1: StatusIconSettings {
width: dummyImage.width
height: dummyImage.height
rotation: 0
color: Theme.palette.indirectColor1
background: StatusIconBackgroundSettings {
width: 10
height: 10
color: Theme.palette.primaryColor1
}
// only used to get implicit width and height from the actual image
property Image dummyImage: Image {
source: icon1.name ? "../../../../assets/img/icons/" + icon1.name + ".svg": ""
visible: false
}
}
property StatusIconSettings icon2: StatusIconSettings {
width: dummyImage.width
height: dummyImage.height
rotation: 0
color: Theme.palette.primaryColor1
background: StatusIconBackgroundSettings {
width: 10
height: 10
color: Theme.palette.indirectColor1
}
// only used to get implicit width and height from the actual image
property Image dummyImage: Image {
source: icon2.name ? "../../../../assets/img/icons/" + icon2.name + ".svg": ""
visible: false
}
}
property bool isMutualContact: false
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
signal clicked()
signal resendClicked()
@@ -83,28 +53,10 @@ Item {
}
}
Layout.alignment: Qt.AlignBottom
}
StatusRoundIcon {
icon.background.width: icon1.background.width
icon.background.height: icon1.background.height
icon.background.color: icon1.background.color
icon.width: icon1.width
icon.height: icon1.height
icon.name: icon1.name
icon.rotation: icon1.rotation
icon.color: icon1.color
visible: !!icon.name
}
StatusRoundIcon {
icon.background.width: icon2.background.width
icon.background.height: icon2.background.height
icon.background.color: icon2.background.color
icon.width: icon2.width
icon.height: icon2.height
icon.name: icon2.name
icon.rotation: icon2.rotation
icon.color: icon2.color
visible: !!icon.name
}
StatusContactVerificationIcons {
isMutualContact: statusMessageHeader.isMutualContact
trustIndicator: statusMessageHeader.trustIndicator
}
StatusBaseText {
id: secondaryDisplayName
+4
View File
@@ -10,6 +10,7 @@ StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml
StatusChatListAndCategories 0.1 StatusChatListAndCategories.qml
StatusChatToolBar 0.1 StatusChatToolBar.qml
StatusContactRequestsIndicatorListItem 0.1 StatusContactRequestsIndicatorListItem.qml
StatusContactVerificationIcons 0.1 StatusContactVerificationIcons.qml
StatusDescriptionListItem 0.1 StatusDescriptionListItem.qml
StatusLetterIdenticon 0.1 StatusLetterIdenticon.qml
StatusListItem 0.1 StatusListItem.qml
@@ -26,3 +27,6 @@ StatusExpandableItem 0.1 StatusExpandableItem.qml
StatusSmartIdenticon 0.1 StatusSmartIdenticon.qml
StatusMessage 0.1 StatusMessage.qml
StatusMessageDetails 0.1 StatusMessageDetails.qml
StatusTagSelector 0.1 StatusTagSelector.qml
StatusToastMessage 0.1 StatusToastMessage.qml
StatusWizardStepper 0.1 StatusWizardStepper.qml
@@ -0,0 +1,108 @@
import QtQuick 2.0
import QtQuick.Layouts 1.0
import StatusQ.Core 0.1
/*!
\qmltype StatusIdenticonRing
\inherits Item
\inqmlmodule StatusQ.Controls
\since StatusQ.Controls 0.1
\brief It provides lines wrapped into a ring around another component like avatars.
The \c StatusIdenticonRing item displays lines wrapped into a ring. The line is rendered clockwise.
N segments and M distinctive colors compose identicon lines.
Example of how the component looks like:
\image status_identicon_ring.png
Example of how to use it:
\qml
StatusIdenticonRing {
anchors.fill: parent
settings: StatusIdenticonRingSettings {
totalRingUnits: 25
initalAngleRad: 0
ringPxSize: 1.5
ringSpecModel: [ ListElement {colorId: 0; segmentLength: 1},
ListElement {colorId: 28; segmentLength: 1},
ListElement {colorId: 31; segmentLength: 1},
ListElement {colorId: 22; segmentLength: 4},
ListElement {colorId: 28; segmentLength: 3},
ListElement {colorId: 27; segmentLength: 5},
ListElement {colorId: 7; segmentLength: 5},
ListElement {colorId: 13; segmentLength: 1},
ListElement {colorId: 25; segmentLength: 4}]
distinctiveColors: ["#000000", "#726F6F", "#C4C4C4",
"#E7E7E7", "#FFFFFF", "#00FF00",
"#009800", "#B8FFBB", "#FFC413",
"#9F5947", "#FFFF00", "#A8AC00",
"#FFFFB0", "#FF5733", "#FF0000",
"#9A0000", "#FF9D9D", "#FF0099",
"#C80078", "#FF00FF", "#900090",
"#FFB0FF", "#9E00FF", "#0000FF",
"#000086", "#9B81FF", "#3FAEF9",
"#9A6600", "#00FFFF", "#008694",
"#C2FFFF", "#00F0B6"]
}
}
\endqml
For a list of components available see StatusQ.
*/
Item {
id: identiconRing
/*!
\qmlproperty StatusIdenticonRingSettings StatusIdenticonRing::settings
This property holds a set of settings for building the ring.
*/
property StatusIdenticonRingSettings settings: StatusIdenticonRingSettings {
totalRingUnits: 1
initalAngleRad: 0
ringPxSize: 1.5
}
/*!
\qmlproperty real StatusIdenticonRing::segmentRadLen
This property holds the total ring line length in radians. It depends on totalRingUnits value of settings object.
*/
readonly property real segmentRadLen: 2 * Math.PI / settings.totalRingUnits
visible: settings.ringSpecModel !== undefined
Canvas {
function printArcSegment(context, xPos, yPos, radius, color, startAngle, arcAngleLen, lineWidth) {
context.beginPath()
context.arc(xPos, yPos, radius, startAngle, startAngle + arcAngleLen, false/*anticlockwise*/)
context.strokeStyle = color
context.lineWidth = lineWidth
context.stroke()
}
anchors.fill: parent
onPaint: {
const context = getContext("2d")
const radius = (height - settings.ringPxSize) / 2
const xPos = width / 2
const yPos = height / 2
let arcPos = settings.initalAngleRad
context.reset()
if(settings.ringSpecModel) {
for (let i=0; i<settings.ringSpecModel.count; i++) {
const segment = settings.ringSpecModel.get(i)
printArcSegment(context,
xPos,
yPos,
radius,
settings.distinctiveColors[segment.colorId],
arcPos,
segment.segmentLength * identiconRing.segmentRadLen,
settings.ringPxSize)
arcPos += segment.segmentLength * identiconRing.segmentRadLen
}
}
}
}
}
+234
View File
@@ -0,0 +1,234 @@
import QtQuick 2.0
import StatusQ.Core.Theme 0.1
import StatusQ.Controls.Validators 0.1
/*!
\qmltype StatusPinInput
\inherits Item
\inqmlmodule StatusQ.Controls
\since StatusQ.Controls 0.1
\brief It allows entering an N pin length.
The \c StatusPinInput displays N visual circles corresponging with the pin length to introduce.
It runs a blinking animation when the control is focused and ready to introduce the pin, as well as, an hovering feedback when user is in the MouseArea where is able to click into the control.
This pin input control allows introducing validators.
Example of how the control looks like:
\image status_pin_input.png
Example of how to use it:
\qml
StatusPinInput {
id: regexPinInput
validator: StatusRegularExpressionValidator { regularExpression: /[0-9A-Za-z@]+/ }
circleDiameter: 22
circleSpacing: 22
pinLen: 7
}
\endqml
For a list of components available see StatusQ.
*/
Item {
id: root
/*!
\qmlproperty string StatusPinInput::pinInput
This property holds the introduced user pin.
*/
property alias pinInput: inputText.text
/*!
\qmlproperty Validator StatusPinInput::validator
This property allows you to set a validator on the StatusPinInput. When a validator is set the StatusPinInput will only accept
input which leaves the pinInput property in an acceptable state.
Currently supported validators are qml StatusIntValidator and StatusRegularExpressionValidator.
An example of using validators is shown below, which allows input of integers between 0 and 999999 into the pin input
\qml
StatusPinInput {
id: numbersPinInput
validator: StatusIntValidator{bottom: 0; top: 999999;}
}
\endqml
*/
property alias validator: d.statusValidator
/*!
\qmlproperty int StatusPinInput::pinLen
This property allows you to set a specific pin input length. The default value is 6.
*/
property int pinLen: 6
/*!
\qmlproperty int StatusPinInput::circleSpacing
This property allows you to customize spacing between pin circles. The default value is 16 pixels.
*/
property int circleSpacing: 16
/*!
\qmlproperty int StatusPinInput::circleDiameter
This property allows you to customize pin circle diameter. The default value is 16 pixels.
*/
property int circleDiameter: 16
QtObject {
id: d
property int currentPinIndex: 0
property StatusValidator statusValidator
function activateBlink () {
const currItem = repeater.itemAt(d.currentPinIndex)
if(currItem) {
if((currItem.innerState === "NEXT") && (!currItem.blinkingAnimation.running)) {
currItem.blinkingAnimation.start()
}
}
}
function deactivateBlink () {
const currItem = repeater.itemAt(d.currentPinIndex)
if(currItem) {
if((currItem.innerState === "NEXT") && (currItem.blinkingAnimation.running)) {
currItem.blinkingAnimation.stop()
// To ensure that the opacity does not remain in an intermediate state when forcing the animation to stop
currItem.innerOpacity = 1
}
}
}
}
/*
\qmlmethod StatusPinInput::statesInitialization()
Initializes pin input bringing it to its initial state.
It is directly called in Component.onCompleted slot and can be called whenever you need resetting it.
*/
function statesInitialization() {
d.currentPinIndex = 0
repeater.itemAt(d.currentPinIndex).innerState = "NEXT"
for (var i = 1; i < root.pinLen; i++) {
repeater.itemAt(i).innerState = "EMPTY"
}
}
width: (root.circleDiameter + root.circleSpacing) * root.pinLen
height: root.circleDiameter
Component.onCompleted: { statesInitialization() }
// Pin input data management object:
TextInput {
id: inputText
visible: false
focus: true
maximumLength: root.pinLen
validator: d.statusValidator.validatorObj
onTextChanged: {
// Modify state of current introduced character position:
if(text.length >= (d.currentPinIndex + 1)) {
repeater.itemAt(d.currentPinIndex).innerState = "FILLED"
// Update next:
d.currentPinIndex++
if(d.currentPinIndex < root.pinLen)
repeater.itemAt(d.currentPinIndex).innerState = "NEXT"
}
// Modify state of current removed character position:
else if (text.length <= (d.currentPinIndex + 1)) {
if(d.currentPinIndex < root.pinLen)
repeater.itemAt(d.currentPinIndex).innerState = "EMPTY"
d.currentPinIndex--
repeater.itemAt(d.currentPinIndex).innerState = "NEXT"
}
// Some component validations:
if(text.length !== d.currentPinIndex)
console.error("StatusPinInput input management error. Current pin length must be "+ text.length + "and is " + d.currentPinIndex)
}
onFocusChanged: { if(!focus) { d.deactivateBlink () } }
}
// Pin input visual objects:
Row {
spacing: root.circleSpacing
Repeater {
id: repeater
model: root.pinLen
Rectangle {
id: background
property string innerState: "EMPTY"
property alias blinkingAnimation: blinkingAnimation
property alias innerOpacity: inner.opacity
width: root.circleDiameter
height: width
color: Theme.palette.primaryColor2
radius: 0.5 * width
Rectangle {
id: inner
state: background.innerState
anchors.centerIn: parent
height: width
color: Theme.palette.primaryColor1
radius: 0.5 * width
states: [
State {
name: "NEXT"
StateChangeScript { script: { if(inputText.focus) blinkingAnimation.start() } }
PropertyChanges {target: inner; width: root.circleDiameter / 2}
},
State {
name: "FILLED"
StateChangeScript { script: if(blinkingAnimation.running) blinkingAnimation.stop() }
PropertyChanges {target: inner; width: root.circleDiameter}
PropertyChanges {target: inner; opacity: 1}
},
State {
name: "EMPTY"
StateChangeScript { script: if(blinkingAnimation.running) blinkingAnimation.stop() }
PropertyChanges {target: inner; width: 0}
PropertyChanges {target: inner; opacity: 1}
}
]
// Animation on transitions
Behavior on width { NumberAnimation { duration: 200 } }
// Animation on "cursor" blinking
SequentialAnimation {
id: blinkingAnimation
loops: Animation.Infinite
NumberAnimation { target: inner; property: "opacity"; to: 0; duration: 800 }
NumberAnimation { target: inner; property: "opacity"; to: 1; duration: 800 }
}
}
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
// MouseArea behavior:
onClicked: {
inputText.forceActiveFocus()
d.activateBlink ()
}
onContainsMouseChanged: { if(containsMouse) { cursorShape = Qt.PointingHandCursor } }
}
}
@@ -10,6 +10,7 @@ ProgressBar {
property string text
property color fillColor
property color backgroundColor: Theme.palette.directColor8
property color backgroundBorderColor: "transparent"
width: 416
height: 16
@@ -19,6 +20,7 @@ ProgressBar {
implicitWidth: parent.width
implicitHeight: parent.height
color: control.backgroundColor
border.color: control.backgroundBorderColor
radius: 5
}
contentItem: Item {
@@ -0,0 +1,57 @@
import QtQuick 2.14
import StatusQ.Controls 0.1
/*!
\qmltype StatusIntValidator
\inherits StatusValidator
\inqmlmodule StatusQ.Controls.Validators
\since StatusQ.Controls.Validators 0.1
\brief The StatusIntValidator type provides a validator for integer values.
The \c StatusIntValidator type provides a validator for integer values.
It is a wrapper of QML type \l{https://doc.qt.io/qt-5/qml-qtquick-intvalidator.html}{IntValidator}.
Example of how to use it:
\qml
StatusIntValidator {
bottom: 0
top: 125
errorMessage: qsTr("This is an invalid numeric value")
}
\endqml
For a list of components available see StatusQ.
*/
StatusValidator {
id: root
/*!
\qmlproperty string StatusIntValidator::bottom
This property holds the validator's lowest acceptable value. By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
*/
property int bottom
/*!
\qmlproperty string StatusIntValidator::locale
This property holds the name of the locale used to interpret the number.
*/
property string locale
/*!
\qmlproperty string StatusIntValidator::top
This property holds the validator's highest acceptable value. By default, this property's value is derived from the highest signed integer available (typically 2147483647).
*/
property int top
name: "intValidator"
errorMessage: "Please enter a valid numeric value."
validatorObj: IntValidator { bottom: root.bottom; locale: root.locale; top: root.top }
validate: function (t) {
// Basic validation management
return root.validatorObj.validate() === IntValidator.Acceptable
}
}
@@ -0,0 +1,60 @@
import QtQuick 2.14
import StatusQ.Controls 0.1
/*!
\qmltype StatusRegularExpressionValidator
\inherits StatusValidator
\inqmlmodule StatusQ.Controls.Validators
\since StatusQ.Controls.Validators 0.1
\brief The StatusRegularExpressionValidator type provides a validator for regular expressions.
The \c StatusRegularExpressionValidator type provides a validator, that counts as valid any string which matches a specified regular expression.
It is a wrapper of QML type \l{https://doc.qt.io/qt-5/qml-qtquick-regularexpressionvalidator.html}{RegularExpressionValidator}.
Example of how to use it:
\qml
StatusRegularExpressionValidator {
regularExpression: /[0-9A-Za-z@]+/
errorMessage: qsTr("Please enter a valid regular expression.")
}
\endqml
For a list of components available see StatusQ.
*/
StatusValidator {
id: root
/*!
\qmlproperty string StatusRegularExpressionValidator::regularExpression
This property holds the regular expression used for validation.
Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression matching "a".
By default, this property contains a regular expression with the pattern .* that matches any string.
Some more examples of regular expressions:
> A list of numbers with one to three positions separated by a comma:
\qml
/\d{1,3}(?:,\d{1,3})+$/
\endqml
> An amount consisting of up to 3 numbers before the decimal point, and 1 to 2 after the decimal point:
\qml
/(\d{1,3})([.,]\d{1,2})?$/
\endqml
*/
property var regularExpression
name: "regex"
errorMessage: "Please enter a valid regular expression."
validatorObj: RegularExpressionValidator { regularExpression: root.regularExpression }
validate: function (t) {
// Basic validation management
return root.validatorObj.validate() === RegularExpressionValidator.Acceptable
}
}
@@ -6,6 +6,7 @@ QtObject {
property string name: ""
property string errorMessage: "invalid input"
property var validatorObj
property var validate: function (value) {
return true
+2
View File
@@ -4,7 +4,9 @@ StatusAddressValidator 0.1 StatusAddressValidator.qml
StatusAddressOrEnsValidator 0.1 StatusAddressOrEnsValidator.qml
StatusAsyncValidator 0.1 StatusAsyncValidator.qml
StatusAsyncEnsValidator 0.1 StatusAsyncEnsValidator.qml
StatusIntValidator 0.1 StatusIntValidator.qml
StatusMinLengthValidator 0.1 StatusMinLengthValidator.qml
StatusMaxLengthValidator 0.1 StatusMaxLengthValidator.qml
StatusRegularExpressionValidator 0.1 StatusRegularExpressionValidator.qml
StatusUrlValidator 0.1 StatusUrlValidator.qml
StatusValidator 0.1 StatusValidator.qml
+2
View File
@@ -8,6 +8,7 @@ StatusChatInfoButton 0.1 StatusChatInfoButton.qml
StatusChatListCategoryItemButton 0.1 StatusChatListCategoryItemButton.qml
StatusColorSelector 0.1 StatusColorSelector.qml
StatusIconTabButton 0.1 StatusIconTabButton.qml
StatusIdenticonRing 0.1 StatusIdenticonRing.qml
StatusNavBarTabButton 0.1 StatusNavBarTabButton.qml
StatusTabBarIconButton 0.1 StatusTabBarIconButton.qml
StatusToolTip 0.1 StatusToolTip.qml
@@ -24,6 +25,7 @@ StatusSelect 0.1 StatusSelect.qml
StatusBaseInput 0.1 StatusBaseInput.qml
StatusInput 0.1 StatusInput.qml
StatusPickerButton 0.1 StatusPickerButton.qml
StatusPinInput 0.1 StatusPinInput.qml
StatusProgressBar 0.1 StatusProgressBar.qml
StatusPasswordStrengthIndicator 0.1 StatusPasswordStrengthIndicator.qml
StatusSwitchTabButton 0.1 StatusSwitchTabButton.qml
@@ -0,0 +1,46 @@
import QtQuick 2.13
import QtQml.Models 2.13
DelegateModel {
id: delegateModel
property var filterAcceptsItem: function(item) { return true; }
signal aboutToUpdateFilteredModel()
function update() {
delegateModel.aboutToUpdateFilteredModel()
if (items.count > 0) {
items.setGroups(0, items.count, "items");
}
var visible = [];
for (var i = 0; i < items.count; ++i) {
var item = items.get(i);
if (filterAcceptsItem(item.model)) {
visible.push(item);
}
}
for (i = 0; i < visible.length; ++i) {
item = visible[i];
item.inVisible = true;
if (item.visibleIndex !== i) {
visibleItems.move(item.visibleIndex, i, 1);
}
}
}
items.onChanged: update()
onFilterAcceptsItemChanged: update()
groups: DelegateModelGroup {
id: visibleItems
name: "visible"
includeByDefault: false
}
filterOnGroup: "visible"
}
+24
View File
@@ -1,6 +1,30 @@
import QtQuick 2.13
import StatusQ.Core.Theme 0.1
/*!
\qmltype StatusBaseText
\inherits Text
\inqmlmodule StatusQ.Core
\since StatusQ.Core 0.1
\brief Displays multiple lines of text. Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-text.html}{Text}.
The \c StatusBaseText item displays text.
For example:
\qml
StatusBaseText {
width: 240
text: "Hello World!"
font.pixelSize: 24
color: Theme.pallete.directColor1
}
\endqml
\image status_base_text.png
For a list of components available see StatusQ.
*/
Text {
font.family: Theme.palette.baseFont.name
}
@@ -0,0 +1,78 @@
import QtQuick 2.13
import StatusQ.Core 0.1
/*!
\qmltype StatusIdenticonRingSettings
\inherits QtObject
\inqmlmodule StatusQ.Core
\since StatusQ.Core 0.1
\brief It describes identicon ring settings.
The \c StatusIdenticonRingSettings object is not a graphical component just an object to encapsulate identicon ring settings.
Example of how to use it:
\qml
StatusIdenticonRingSettings {
totalRingUnits: 25
initalAngleRad: 0
ringPxSize: 1.5
ringSpecModel: [ ListElement {colorId: 0; segmentLength: 1},
ListElement {colorId: 28; segmentLength: 1},
ListElement {colorId: 31; segmentLength: 1},
ListElement {colorId: 22; segmentLength: 4},
ListElement {colorId: 28; segmentLength: 3},
ListElement {colorId: 27; segmentLength: 5},
ListElement {colorId: 7; segmentLength: 5},
ListElement {colorId: 13; segmentLength: 1},
ListElement {colorId: 25; segmentLength: 4}]
distinctiveColors: ["#000000", "#726F6F", "#C4C4C4",
"#E7E7E7", "#FFFFFF", "#00FF00",
"#009800", "#B8FFBB", "#FFC413",
"#9F5947", "#FFFF00", "#A8AC00",
"#FFFFB0", "#FF5733", "#FF0000",
"#9A0000", "#FF9D9D", "#FF0099",
"#C80078", "#FF00FF", "#900090",
"#FFB0FF", "#9E00FF", "#0000FF",
"#000086", "#9B81FF", "#3FAEF9",
"#9A6600", "#00FFFF", "#008694",
"#C2FFFF", "#00F0B6"]
}
\endqml
For a list of components available see StatusQ.
*/
QtObject {
id: statusIdenticonRingSettings
/*!
\qmlproperty ListModel StatusIdenticonRingSettings::ringSpecModel
This is a REQUIRED property that contains a ListModel object that describes each ring segment color and length.
Example of use: [ListElement {colorId: 0; segmentLength: 1}, ...]
*/
property ListModel ringSpecModel
/*!
\qmlproperty var StatusIdenticonRingSettings::distinctiveColors
This is a REQUIRED property that holds an string array of disctinctive segment colors.
*/
property var distinctiveColors
/*!
\qmlproperty real StatusIdenticonRingSettings::totalRingUnits
This property provides the total number of units the identicon ring is composed by.
*/
property real totalRingUnits
/*!
\qmlproperty real StatusIdenticonRingSettings::initalAngleRad
This property provides the initial angle, in radians, the identicon ring will start rendering the line.
*/
property real initalAngleRad
/*!
\qmlproperty real StatusIdenticonRingSettings::ringPxSize
This property provides the pixels size of the ring line.
*/
property real ringPxSize
}
@@ -158,6 +158,13 @@ ThemePalette {
getColor('brown3')
]
identiconRingColors: ["#000000", "#726F6F", "#C4C4C4", "#E7E7E7", "#FFFFFF", "#00FF00",
"#009800", "#B8FFBB", "#FFC413", "#9F5947", "#FFFF00", "#A8AC00",
"#FFFFB0", "#FF5733", "#FF0000", "#9A0000", "#FF9D9D", "#FF0099",
"#C80078", "#FF00FF", "#900090", "#FFB0FF", "#9E00FF", "#0000FF",
"#000086", "#9B81FF", "#3FAEF9", "#9A6600", "#00FFFF", "#008694",
"#C2FFFF", "#00F0B6"]
property QtObject statusAppLayout: QtObject {
property color backgroundColor: baseColor3
property color rightPanelBackgroundColor: baseColor3
@@ -167,6 +174,10 @@ ThemePalette {
property color backgroundColor: baseColor5
}
property QtObject statusToastMessage: QtObject {
property color backgroundColor: baseColor3
}
property QtObject statusListItem: QtObject {
property color backgroundColor: baseColor3
property color secondaryHoverBackgroundColor: primaryColor3
@@ -156,6 +156,13 @@ ThemePalette {
getColor('brown')
]
identiconRingColors: ["#000000", "#726F6F", "#C4C4C4", "#E7E7E7", "#FFFFFF", "#00FF00",
"#009800", "#B8FFBB", "#FFC413", "#9F5947", "#FFFF00", "#A8AC00",
"#FFFFB0", "#FF5733", "#FF0000", "#9A0000", "#FF9D9D", "#FF0099",
"#C80078", "#FF00FF", "#900090", "#FFB0FF", "#9E00FF", "#0000FF",
"#000086", "#9B81FF", "#3FAEF9", "#9A6600", "#00FFFF", "#008694",
"#C2FFFF", "#00F0B6"]
property QtObject statusAppLayout: QtObject {
property color backgroundColor: white
property color rightPanelBackgroundColor: white
@@ -165,6 +172,10 @@ ThemePalette {
property color backgroundColor: baseColor2
}
property QtObject statusToastMessage: QtObject {
property color backgroundColor: white
}
property QtObject statusListItem: QtObject {
property color backgroundColor: white
property color secondaryHoverBackgroundColor: getColor('blue6')
+6
View File
@@ -92,6 +92,8 @@ QtObject {
property var accountColors: []
property var identiconRingColors: []
property QtObject statusAppLayout: QtObject {
property color backgroundColor
property color rightPanelBackgroundColor
@@ -101,6 +103,10 @@ QtObject {
property color backgroundColor
}
property QtObject statusToastMessage: QtObject {
property color backgroundColor
}
property QtObject statusListItem: QtObject {
property color backgroundColor
property color secondaryHoverBackgroundColor
+2
View File
@@ -4,6 +4,8 @@ StatusBaseText 0.1 StatusBaseText.qml
StatusIcon 0.1 StatusIcon.qml
StatusIconSettings 0.1 StatusIconSettings.qml
StatusIconBackgroundSettings 0.1 StatusIconBackgroundSettings.qml
StatusIdenticonRingSettings 0.1 StatusIdenticonRingSettings.qml
StatusImageSettings 0.1 StatusImageSettings.qml
StatusModalHeaderSettings 0.1 StatusModalHeaderSettings.qml
StatusTooltipSettings 0.1 StatusTooltipSettings.qml
StatusAppNavBarFilterModel 0.1 StatusAppNavBarFilterModel.qml
+134 -116
View File
@@ -1,40 +1,35 @@
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 StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
Rectangle {
id: statusAppNavBar
property StatusNavBarTabButton navBarChatButton
property StatusNavBarTabButton navBarProfileButton
property list<StatusNavBarTabButton> navBarTabButtons
property alias navBarCommunityTabButtons: navBarCommunityTabButtons
property int navBarContentHeight: 0
property int navBarContentHeightWithoutCommunityButtons: 0
width: 78
implicitHeight: 600
color: Theme.palette.statusAppNavBar.backgroundColor
Component.onCompleted: {
navBarContentHeightWithoutCommunityButtons = (navBarChatButtonSlot.anchors.topMargin + navBarChatButtonSlot.height) +
(separator.anchors.topMargin + separator.height) +
(navBarTabButtonsSlot.height + navBarTabButtonsSlot.anchors.topMargin + navBarTabButtonsSlot.anchors.bottomMargin)
navBarContentHeight = navBarContentHeightWithoutCommunityButtons +
(navBarCommunityTabButtonsSlot.height + navBarScrollSection.anchors.topMargin)
}
property var sectionModel: []
property string communityTypeRole: ""
property int communityTypeValue: -1
property int navBarButtonSpacing: 12
onNavBarChatButtonChanged: {
if (!!navBarChatButton) {
navBarChatButton.parent = navBarChatButtonSlot
}
}
property StatusNavBarTabButton navBarProfileButton
property Component regularNavBarButton
property Component communityNavBarButton
property var filterRegularItem: function(item) { return true; }
property var filterCommunityItem: function(item) { return true; }
signal aboutToUpdateFilteredRegularModel()
signal aboutToUpdateFilteredCommunityModel()
onNavBarProfileButtonChanged: {
if (!!navBarProfileButton) {
@@ -42,115 +37,138 @@ Rectangle {
}
}
onNavBarTabButtonsChanged: {
if (navBarTabButtons.length) {
for (let idx in navBarTabButtons) {
navBarTabButtons[idx].parent = navBarTabButtonsSlot
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
}
}
ListView {
id: communityListView
anchors.left: parent.left
anchors.right: parent.right
anchors.top: separatorTop.visible? separatorTop.bottom : parent.top
anchors.bottom: separatorBottom.top
clip: true
spacing: navBarButtonSpacing
model: navBarCommunityModel
}
Item {
id: separatorBottom
width: parent.width
height: navBarButtonSpacing
anchors.bottom: parent.bottom
Rectangle {
height: 1
width: 30
color: Theme.palette.directColor7
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Item {
id: navBarChatButtonSlot
ListView {
id: navBarListView
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 48
anchors.horizontalCenter: parent.horizontalCenter
height: visible ? statusAppNavBar.navBarChatButton.height : 0
width: visible ? statusAppNavBar.navBarChatButton.width : 0
visible: !!statusAppNavBar.navBarChatButton
}
anchors.bottom: navBarProfileButtonSlot.top
anchors.bottomMargin: navBarButtonSpacing
Rectangle {
id: separatorTop
height: 1
width: 30
color: Theme.palette.directColor7
anchors.top: navBarChatButtonSlot.bottom
anchors.topMargin: 16
anchors.horizontalCenter: parent.horizontalCenter
visible: separator.anchors.topMargin === 0
}
spacing: navBarButtonSpacing
ScrollView {
id: navBarScrollSection
anchors.top: separatorTop.visible ? separatorTop.bottom : navBarChatButtonSlot.bottom
anchors.topMargin: separatorTop.visible ? 0 : 12
anchors.horizontalCenter: statusAppNavBar.horizontalCenter
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
clip: true
Component.onCompleted: {
if (navBarContentHeight > statusAppNavBar.height) {
height = statusAppNavBar.height -
statusAppNavBar.navBarContentHeightWithoutCommunityButtons -
(!!navBarTabButtonsSlot.anchors.bottom ? navBarTabButtonsSlot.anchors.bottomMargin : navBarTabButtonsSlot.anchors.topMargin) -
navBarProfileButtonSlot.height -
navBarProfileButtonSlot.anchors.bottomMargin
bottomPadding = 16
topPadding = 16
} else {
height = navBarCommunityTabButtons.count > 0 ? navBarCommunityTabButtonsSlot.implicitHeight : 0
}
}
Column {
id: navBarCommunityTabButtonsSlot
width: navBarScrollSection.width
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
spacing: 12
onImplicitHeightChanged: {
statusAppNavBar.Component.onCompleted()
navBarTabButtonsSlot.Component.onCompleted()
navBarScrollSection.Component.onCompleted()
}
Repeater {
id: navBarCommunityTabButtons
}
}
}
Rectangle {
id: separator
height: 1
width: 30
color: Theme.palette.directColor7
anchors.top: !!navBarCommunityTabButtons.model && navBarCommunityTabButtons.count > 0 ? navBarScrollSection.bottom : navBarChatButtonSlot.bottom
anchors.topMargin: navBarScrollSection.height < navBarCommunityTabButtonsSlot.implicitHeight ? 0 : 16
anchors.horizontalCenter: parent.horizontalCenter
visible: navBarChatButton !== null && navBarTabButtons.length > 0
}
Column {
id: navBarTabButtonsSlot
anchors.horizontalCenter: parent.horizontalCenter
spacing: 12
Component.onCompleted: {
if (navBarContentHeight > statusAppNavBar.height) {
anchors.top = undefined
anchors.topMargin = 0
anchors.bottom = navBarProfileButtonSlot.top
anchors.bottomMargin = 32
} else {
anchors.bottom = undefined
anchors.bottomMargin = 0
anchors.top = separator.visible ? separator.bottom : parent.top
anchors.topMargin = separator.visible ? 16 : navBarChatButtonSlot.anchors.topMargin
}
}
model: navBarModel
}
Item {
id: navBarProfileButtonSlot
anchors.horizontalCenter: parent.horizontalCenter
height: visible ? statusAppNavBar.navBarProfileButton.height : 0
width: visible ? statusAppNavBar.navBarProfileButton.width : 0
height: visible? statusAppNavBar.navBarProfileButton.height : 0
width: visible? statusAppNavBar.navBarProfileButton.width : 0
visible: !!statusAppNavBar.navBarProfileButton
anchors.bottom: parent.bottom
anchors.bottomMargin: visible ? 23 : 0
anchors.bottomMargin: visible ? 32 : 0
}
}
-2
View File
@@ -21,8 +21,6 @@ Menu {
property var closeHandler
dim: true
Overlay.modeless: MouseArea {}
signal menuItemClicked(int menuIndex)
+10
View File
@@ -276,6 +276,7 @@
<file>src/assets/img/icons/snt.svg</file>
<file>src/StatusQ/Popups/StatusSpellcheckingMenuItems.qml</file>
<file>src/StatusQ/Controls/StatusSelectableText.qml</file>
<file>src/StatusQ/Core/StatusAppNavBarFilterModel.qml</file>
<file>src/assets/img/icons/tiny/add.svg</file>
<file>src/assets/img/icons/tiny/arrow-down.svg</file>
<file>src/assets/img/icons/tiny/channel-white.svg</file>
@@ -319,5 +320,14 @@
<file>src/StatusQ/Controls/StatusProgressBar.qml</file>
<file>src/StatusQ/Controls/StatusPasswordStrengthIndicator.qml</file>
<file>src/StatusQ/Components/StatusMemberListItem.qml</file>
<file>src/StatusQ/Components/StatusTagSelector.qml</file>
<file>src/StatusQ/Components/StatusToastMessage.qml</file>
<file>src/StatusQ/Components/StatusWizardStepper.qml</file>
<file>src/StatusQ/Components/StatusContactVerificationIcons.qml</file>
<file>src/StatusQ/Controls/StatusIdenticonRing.qml</file>
<file>src/StatusQ/Core/StatusIdenticonRingSettings.qml</file>
<file>src/StatusQ/Controls/StatusPinInput.qml</file>
<file>src/StatusQ/Controls/Validators/StatusRegularExpressionValidator.qml</file>
<file>src/StatusQ/Controls/Validators/StatusIntValidator.qml</file>
</qresource>
</RCC>