Compare commits

..
77 Commits
Author SHA1 Message Date
Michał 17d82a7be0 chore(general): set info in readme before setting repo read-only (#917)
Further development will take place in the status-desktop repository.
2022-09-21 15:50:50 +02:00
Khushboo-dev-cpp a219e95a5c fix(StatusListItem): Adding padding in the inline tags (#915) 2022-09-21 15:46:32 +02:00
Alexandra Betouni 73d7e09536 (StatusSectionLayout): Added back button in StatusChatToolbar (#903)
To be used in header in all sections where it's needed

Needed for https://github.com/status-im/status-desktop/issues/7312
2022-09-21 16:31:47 +03:00
Michał 2c43dbb207 feat(StatusMessage): add 'hideMessage' property to allow hiding main message text (#916) 2022-09-21 10:30:21 +02:00
Lukáš Tinkl 3202294a11 fix(StatusChatInfoButton): fix vertical title alignment
do not display the subtitle when it's empty
2022-09-20 11:49:42 +02:00
Michał d892a84227 fix(StatusBaseButton): font family and weight fixed (#908) 2022-09-19 22:08:49 +02:00
MishkaRogachev ea5c83710b hotfix(StatusSectionLayout): fix notificationCount availability 2022-09-19 17:59:27 +03:00
Michal Iskierko a94d9338bf fix(StatusMessageSenderDetails): Simplify StatusMessageSenderDetails
StatusMessageSenderDetails contains only displayName and secondaryName.
Correct values are delivered by a model.

Issue #7241
2022-09-19 11:22:52 +02:00
Lukáš Tinkl 7d96b2d4c1 fix(StatusPinMessageDetails): correct spacing
Fixes status-im/status-desktop#7305
2022-09-16 11:40:08 +02:00
Patryk Osmaczko 9135b90ada fix(StatusBaseButton): align text to horizontal center 2022-09-16 09:44:53 +02:00
Lukáš Tinkl fa3ba834e2 fix(StatusListItem): unbreak vertical alignment 2022-09-16 09:40:58 +02:00
Lukáš Tinkl 27acdd959b hotfix: fix broken notification-muted icon 2022-09-15 14:54:57 +02:00
Alexandra Betouni f79cf81db2 fix(StatusChartPanel): updated left spacing (#907) 2022-09-14 18:43:42 +03:00
Alexandra Betouni 865fee22b8 fix(StatusChartPanel): fix #893 PR comments 2022-09-14 17:08:22 +02:00
Igor Sirotin d02fea1cd3 fix(StatusColorRadioButton): Fixed size as per design (#732) 2022-09-14 16:11:30 +03:00
Alexandra Betouni 524a86b0cc feat(StatusChart): Adding chart component (#893)
Needed for https://github.com/status-im/status-desktop/issues/6490
2022-09-14 14:21:59 +03:00
Sale Djenic 1dc5592636 feat(StatusPinInput): additional spacing for every N-th digit
Two new props exposed so we can sed an extra spacing for every N-th item.
- `additionalSpacingOnEveryNItems` - determines for which item to add an extra space
- `additionalSpacing` - determines the value of extra space which will be added
2022-09-14 13:13:14 +02:00
Michał ef5f8746d5 chore(StatusItemSelector): allow of using icons (#897) 2022-09-14 13:03:49 +02:00
Lukáš Tinkl 9a24d59ea8 fix(StatusChatInfoButton): pinned messages counter
- fix the "pinned messages" counter, add plural handling (Fixes #899)
- modernize using layouts (Fixes #898)
- add some more examples
2022-09-14 09:24:30 +02:00
PavelS e17088304b fix(StatusMessage): adjust text alignment (#901)
Fixes https://github.com/status-im/status-desktop/issues/7301
2022-09-13 16:33:32 +03:00
Lukáš Tinkl 1381b1bd15 hotfix: unbreak "pointing hand" cursor
turns out we can indeed have only one MouseArea to handle both the cursor
and intercepting the event in the "loading" state
2022-09-13 10:07:29 +02:00
Alexandra Betouni f89b0a8c6f feat(StatusBaseButton)!: Converting to QQC2 Button
Closes #782
2022-09-12 19:19:07 +02:00
Patryk Osmaczko b1025fabd7 feat(StatusChatListItem): add online badge 2022-09-12 10:17:45 +02:00
Igor Sirotin efc5be38bd fix(StatusMessageEmojiReactions): Fixed emoji reactions appearance (#889) 2022-09-10 11:22:12 +08:00
Khushboo-dev-cpp c3bbb396ec fix(StatusExpandableItem): Added new padding for Tertitary type expandable item, a flag to set separator to visible true or false (#896) 2022-09-09 19:29:05 +02:00
Pascal Precht 21f1c4ce52 feat(StatusMessage): add support for messageAttachments
Prior to this commit, a `StatusMessage` can hold only a single
`messageImage`.

There will be scenarios where messages can have multiple attachments.
This is the case when importing messages from discord.
Hence, this commit introduces a new `messageAttachments` property which
is a whitespace separated list of attachment URLs (very analogous to the
already existing `linkUrls` property).

For now, we can safely assume these URLs will resolve to image content.
In future versions however, we might want to support additional content
types to handle any byte stream.
We will then change `messageAttachments` from `string` to a list model
that holds `attachment`s where we also have access to its `contentType`.
This will allow us to decide at runtime which component should be used
to view/play the attachment.
2022-09-09 10:35:30 +02:00
Khushboo-dev-cpp 7108ac87cf feat(StatusListItem): Added new properties to handle inline tags needed in the wallet section (#879) 2022-09-09 00:03:28 +02:00
Lukáš Tinkl 384924ce58 fix: StatusDateGroupLabel doesn't support i18n and has no year
- fix evaluating "Today" and "Yesterday"; can't just compare the two Date
objects, the timestamp will always differ so need to compare
year/month/day only
- best attempt to have the month translated, and year added if they
differ (until Qt6 at least, left a TODO)

Closes #843
2022-09-08 13:21:01 +02:00
Sale Djenic 8c683bf83c feat(Controls): introduce StatusPasswordInput
`StatusPasswordInput` is a wrapper around  `TextField` with an option
to display signing phrase.
2022-09-08 13:03:04 +02:00
Michał f6424328d8 feat(StatusItemSelector): improved reusablity, addItem and popup handling removed (#887)
Additionally:
- minor positioning fixes in StatusListItem and StatusListItemTag
- StatusItemSelectorPage updated and added to main.qml
2022-09-08 11:06:25 +02:00
PavelS 60137c39b5 fix(StatusListItem): adjust placement of title icons (#888)
Needed for https://github.com/status-im/status-desktop/issues/6972
2022-09-07 19:28:52 +03:00
Pascal Precht 4d16ac17a8 fix(StatusBaseButton): fix wrong id usage 2022-09-07 15:15:05 +02:00
Pascal Precht 504053a6bf fix(StatusBaseButton): keep MouseArea enabled when in loading state
`StatusBaseButton` comes with a `MouseArea` that is disabled when the
button is set to being disabled. Prior to this commit it's *also* disabled
when the button is in `loading` state.

This makes sense because a button that is in `loading` state shouldn't
not emit any click signals or trigger hover indications.

There's a scenario though in which we want render a tooltip on top of
the button which is in `loading` state. For the tooltip to show, the
`MouseArea` of the button needs to be enabled.

Hence, this commit adjust `StatusBaseButton`'s behaviour to *not*
disable the `MouseArea` when it's `loading`. Mouse events are already
prevented via the `loading` flag. So the only thing left to do is to
ensure the button doesn't trigger any hover indication when in `loading`
state.
2022-09-07 13:49:18 +02:00
Pascal Precht fc10a0d43d feat(StatusMessageReply): introduce profileClickable property
This is analogue to `profileClickable` available on `StatusMessage`,
preventing users to activate a reply-to-message's profile avatar.

At the time of this commit, this is only the case for imported messages.
So we can derive that, if `StatusMessage.profileClickable` is false, then
`StatusMessageReply.profileClickable` is also false.

Hence, we don't need to expose this property to higher level APIs.
2022-09-06 11:24:19 +02:00
Stefan 3b6a6067af fix(StatusSelect): set implicitWidth to the content size 2022-09-05 12:14:56 +02:00
Patryk Osmaczko f1d7bdb069 fix(StatusTagSelector): forbid removing readonly tags 2022-09-05 12:06:28 +02:00
Lukáš Tinkl 32db0bb023 fix(StatusRadioButton): StatusRadioButton can't be fully clicked
- fix the control's width (don't have to be explicit, the QQC2 Control
takes care of calculating the implicitWidth/Height automatically based on
contents)
- while at it, fix the metrics to be able to support RTL
languages too (it was off for Arabic)
- some smaller cleanups too
2022-09-05 09:35:20 +02:00
Lukáš Tinkl 9688113d7f fix: remove duplicate entries 2022-09-05 09:35:20 +02:00
Alexandra Betouni 98d0d2163e feat(StatusQ): Merging Icon, Background and Image Settings (#788)
Closes #781
2022-09-02 18:40:30 +03:00
Alexandra Betouni e146ccaed4 fix(StatusScrollBar): Fixed visibilty when policy always on (#878)
Needed for https://github.com/status-im/status-desktop/issues/6262
2022-09-02 15:49:08 +03:00
PavelS 5e7a0d8251 fix(StatusSelectableText): add missing Utils import (#880) 2022-09-02 14:51:16 +03:00
Alexandra Betouni ecc44cfae0 feat(StatusQ/Layout)!: Cleaning up Layouts for consistency (#836)
- Created StatusMainLayout to be used as the apps' main
  layout
- Created StatusSectionLayout to be used for all sections as
  their base
  - Created StatusToolBar as part of StatusAppLayout with
    standard component the ActivityButton and posibility to
    add custom implementation components

Needed for https://github.com/status-im/status-desktop/issues/6635
2022-09-02 10:25:43 +03:00
Pascal Precht ad8bc322d1 feat(StatusMessage): introduce profileClickable property
This property allows for enabling/disabling whether or not the profile
picture and display name of a message is clickable and also dictates the
cursor type accordingly.

The reason this is being introduced is that, with imported messages from
other systems (e.g. discord, telegram etc), we don't want the user to
trigger the popup menu for more profile information because we don't
know any profile information of messages coming from such systems.

Such messages are signed by the community.

Closes https://github.com/status-im/status-desktop/issues/6680
2022-09-01 14:40:25 +02:00
PavelS 80a9cc9b3f feat(Icons): add quote icon (#876)
Needed for https://github.com/status-im/status-desktop/issues/6988
2022-08-31 17:43:12 +03:00
Michał 803a7637bf fix(StatusImageCropPanel): display SizeAllCursor cursor when over image (#864) 2022-08-31 15:36:23 +02:00
MishkaRogachev 4d9cec541f fix(StatusChatListCategory): Add alias to category item for squish tests 2022-08-31 14:29:35 +03:00
PavelS 4d73c25c7a feat(StatusScrollView): add ensureVisible function to Utils (#868)
Replace local ensureVisible with ensureVisible function from Utils

Required for https://github.com/status-im/status-desktop/issues/7093
2022-08-31 11:19:20 +03:00
Michał 8646daa401 chore(StatusAppNavBar): List views' bounds behavior refined (#866)
- outer list: not draggable
- communities list: not draggable when sufficient space,
  drag and overshot otherwise
2022-08-26 18:04:17 +02:00
Noelia db0f8e9fb5 feat(StatusItemPicker): Added radioButtonSize property
Added properties `namePixelSize` and `radioButtonSize`.
Some fixes when shortName is undefined.
2022-08-26 17:27:02 +02:00
Noelia 9d6cea7051 feat(StatusRadioButton): Added size variant Large and Small 2022-08-26 17:27:02 +02:00
Pascal Precht 780ade987d feat(StatusMessage): add messageOriginInfo property
This is a property that allows for adding information about the origin
of a message (e.g. "Imported from discord").

This will most likely be only useful for messages that have been
imported from any other platform.

Because importing from other platforms requires those message to be
signed by a Status Account, it's undesirable to render the public key of
the account that signed imported messages.

Hence, when there's a `messageOriginInfo`, we don't render the elided
public key.
2022-08-26 13:11:19 +02:00
Igor Sirotin fd6d735df8 test(StatusMessage): Added objectName to StatusTextMessage (#869) 2022-08-25 23:30:05 +03:00
Jonathan Rainville 4d63af303c test(StatusChatInfoButton): add objectName to pin text for tests 2022-08-24 10:08:17 -04:00
Jonathan Rainville 1e12636abd test(StatusTextMessage): add objectName for test 2022-08-22 13:48:24 -04:00
Michał 89049fd56b fix(StatusTabButton): display hand cursor on hover when enabled (#859)
Needed for https://github.com/status-im/status-desktop/issues/6787
2022-08-22 14:35:36 +02:00
Michal Iskierko be24401a50 fix(Theme): Adding additional green color
Issue #6279
2022-08-22 13:44:40 +02:00
Stefan 8214e64684 fix(StatusChatListCategory): Clicking on a category should toggle it
The culprit here is at the very bottom, in StatusListItem: the toplevel
item was a MouseArea handling the clicks and this causes problems as any
extra buttons placed on top of it get their mouseClick events delivered
in wrong order (after StatusListItem). Fix this by having a MouseArea
handling click events behind the actual toplevel item as a last resort,
catch all handler  plus the actual "sensor" being just a MouseArea that
handles merely the hover events

- drop unneeded onPressed/onReleased handlers in StatusChatListCategoryItem
- fix some warnings (typos, unreachable code, shadowed variables)

Fixes: #6733
2022-08-22 12:29:24 +02:00
Stefan 50299f8d83 test(Sandbox): extend sandbox test for StatusChatListCategoryItem
Scope was to validate why StatusChatListCategoryItem miss behaves when
used in StatusChatListCategory.

On its own all the events works fine, as it can be seen by monitoring
the click events for each item (title, item and buttons).
However, inside StatusChatListCategory the mouse events are overlapped and
button events trigger also for the item. Tried obvious fiexes like
disabling steal of mouse events from buttons but this break the hovering
effect.

Updates: #6733
2022-08-22 12:29:24 +02:00
PavelS 6e93b4ec41 fix(CreateChatView): adjust start chat page (#863)
Add fix from https://github.com/status-im/status-desktop/pull/7077 to
demoapp
2022-08-22 10:35:23 +03:00
Igor Sirotin 6c107b5760 fix(StatusMessage): Design update and minor improvements (#752) 2022-08-20 03:01:28 +03:00
Sale Djenic a9c0c88101 feat: added missing icons
The following icons added:
- `key_pair_prvate_key.svg`
- `key_pair_seed_phrase.svg`
2022-08-18 16:40:58 +02:00
Sale Djenic b59295d56b feat(StatusListItem): scroll feature added if list of tags exceeds component width 2022-08-18 16:40:58 +02:00
Jonathan Rainville b9882c6ff6 test(StatusSearchPopup): add object name for tests 2022-08-18 09:12:11 -04:00
Igor Sirotin 72750ef60c fix(StatusComboBox): Pointing hand cursor on hover (#862) 2022-08-18 15:07:16 +03:00
PavelS 9f6f9905e9 fix(StatusInput)!: trigger errors bindings (#858)
Change valid to false by default

Fixes https://github.com/status-im/status-desktop/issues/6825

BREAKING CHANGE: StatusInput now emits signal for errors change and is
invalid by default
2022-08-18 14:45:38 +03:00
Anthony Laibe a22d8252b1 feat(@StatusComboBox): expose inner objectName property (#850) 2022-08-18 10:55:09 +02:00
Jonathan Rainville 02bb67a266 test(StatusSearchPopup): add object names for tests 2022-08-16 09:35:19 -04:00
Stefan f15b0d4de4 fix(StatusChatListAndCategories): duplicate objectName
Due to repository automerge.
2022-08-16 11:47:47 +02:00
Stefan 8f06729c1a tests(StatusChatListAndCategories.qml) add object names for testing 2022-08-16 11:30:06 +02:00
MishkaRogachev c721a67c70 test(StatusChatListAndCategories): Add object names 2022-08-15 18:10:24 +04:00
PavelS b2e8a0e282 fix(StatusPopupMenu): update popup content to support big margins (#853)
Needed for https://github.com/status-im/status-desktop/issues/6822
2022-08-15 16:48:58 +03:00
PavelS 76cc5fda22 fix(StatusMenuItemDelegate): adjust menu item height (#852)
Needed for https://github.com/status-im/status-desktop/issues/6830
2022-08-15 12:53:44 +03:00
Sale Djenic e1d8d934b3 feat(StatusCheckbox): introduced new leftSide prop
- `leftSide` determines whether to display check box on the left or right
side, defaulted to left
2022-08-11 13:20:17 +02:00
Khushboo-dev-cpp 9fa6fb2324 fix(StatusColorSelectorGrid): Expose the Color Repeater for Squish testing (#847) 2022-08-11 12:58:09 +02:00
Patryk Osmaczko ce22d8759c fix(StatusIconTextButton): make icon invisible when no icon is loaded
Otherwise this button has invisible left padding when no icon is set
2022-08-10 14:43:28 +02:00
Patryk Osmaczko 91cafca41f fix(StatusToolTip): remove contentItem by id usage
Otherwise contentItem can't be safely overriden by the clients
2022-08-10 14:43:28 +02:00
Patryk Osmaczko 151097e466 feat: add social link icons 2022-08-10 14:43:28 +02:00
141 changed files with 26544 additions and 2469 deletions
+3
View File
@@ -2,6 +2,9 @@
> An emerging reusable QML UI component library for Status applications.
:bangbang: | This repository is set to read-only. `StatusQ` library is further developed in the [status-desktop](https://github.com/status-im/status-desktop) repository.
:---: | :---
## Usage
StatusQ introduces a module namespace that semantically groups components so they can be easily imported.
Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

+4 -4
View File
@@ -63,7 +63,7 @@ Rectangle {
visible: titleStyle === "windows"
}
StatusAppLayout {
StatusMainLayout {
id: statusAppLayout
anchors.top: windowsTitle.visible ? windowsTitle.bottom : demoApp.top
anchors.left: demoApp.left
@@ -73,7 +73,7 @@ Rectangle {
height: demoApp.height - demoApp.border.width * 2
width: demoApp.width - demoApp.border.width * 2
appNavBar: StatusAppNavBar {
leftPanel: StatusAppNavBar {
id: navBar
@@ -181,7 +181,7 @@ Rectangle {
}
}
appView: Loader {
rightPanel: Loader {
id: appView
anchors.fill: parent
sourceComponent: statusAppChatView
@@ -197,7 +197,7 @@ Rectangle {
id: statusAppCommunityView
StatusAppCommunityView {
communityDetailModalTitle: demoCommunityDetailModal.header.title
communityDetailModalImage: demoCommunityDetailModal.header.image.source
communityDetailModalImage: demoCommunityDetailModal.header.asset.name
onChatInfoButtonClicked: {
demoCommunityDetailModal.open();
}
+48 -2
View File
@@ -21,18 +21,37 @@ Column {
StatusButton {
text: "Button"
type: StatusBaseButton.Type.Primary
StatusToolTip {
visible: parent.hovered
text: "Look I'm a tooltip on a button!"
}
onClicked: console.warn("Primary button clicked")
onPressed: console.warn("Primary button pressed")
}
StatusButton {
text: "Button"
enabled: false
type: StatusBaseButton.Type.Primary
StatusToolTip {
visible: parent.hovered
text: "Tooltip on a disabled button, should not be visible!"
}
onClicked: console.warn("Primary disabled button clicked, this should not happen !!!")
}
StatusButton {
text: "Button"
loading: true
type: StatusBaseButton.Type.Primary
StatusToolTip {
visible: parent.hovered
text: "Look I'm a tooltip on a loading button!"
}
onClicked: console.warn("Primary loading button clicked, this should not happen !!!")
}
// Large
@@ -50,6 +69,25 @@ Column {
loading: true
}
// Large + Icon
StatusButton {
text: "Button"
icon.name: "info"
}
StatusButton {
text: "Button"
enabled: false
icon.name: "info"
}
StatusButton {
text: "Button"
loading: true
icon.name: "info"
}
// Danger
StatusButton {
text: "Button"
type: StatusBaseButton.Type.Danger
@@ -67,6 +105,7 @@ Column {
type: StatusBaseButton.Type.Danger
}
// Flat
StatusFlatButton {
text: "Button"
}
@@ -74,7 +113,6 @@ Column {
StatusFlatButton {
text: "Button"
enabled: false
}
StatusFlatButton {
@@ -82,6 +120,7 @@ Column {
loading: true
}
// Flat + Danger
StatusFlatButton {
text: "Button"
type: StatusBaseButton.Type.Danger
@@ -117,6 +156,7 @@ Column {
loading: true
}
// Small + danger
StatusButton {
text: "Button"
type: StatusBaseButton.Type.Danger
@@ -137,6 +177,7 @@ Column {
loading: true
}
// Flat + small
StatusFlatButton {
text: "Button"
size: StatusBaseButton.Size.Small
@@ -359,7 +400,12 @@ Column {
// Button with emoji
StatusButton {
text: "Button with Emoji"
icon.emoji: "🖼️"
asset.emoji: "🖼️"
}
StatusButton {
width: parent.width
text: "wide"
}
RowLayout {
+37 -12
View File
@@ -113,18 +113,33 @@ GridLayout {
StatusSwitch {
}
StatusSwitch {
text: "Switch with text"
}
StatusRadioButton {
text: "i'm radio!"
text: "Radio button 1"
checked: true
}
StatusRadioButton {
text: "Radio button 2 (clicking on this text will uncheck the above)"
}
StatusRadioButton {
LayoutMirroring.enabled : true
text: "Radio button 3 (forced right-to-left)"
}
StatusCheckBox {}
StatusCheckBox { checkState: Qt.Checked}
StatusCheckBox { text: "Check me on left side"}
StatusCheckBox { text: "Check me on right side"; leftSide: false}
StatusChatInfoButton {
title: "Iuri Matias"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
asset.color: Theme.palette.miscColor7
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
type: StatusChatInfoButton.Type.OneToOneChat
muted: true
pinnedMessagesCount: 1
@@ -135,12 +150,13 @@ GridLayout {
implicitHeight: 48
StatusChatInfoButton {
title: "Iuri Matias elided"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
subTitle: "Very long subtitle should elide as well"
asset.color: Theme.palette.miscColor7
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
type: StatusChatInfoButton.Type.OneToOneChat
muted: true
pinnedMessagesCount: 1
pinnedMessagesCount: 10
width: 100
}
}
@@ -151,8 +167,9 @@ GridLayout {
StatusChatInfoButton {
title: "Iuri Matias big not elided"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
asset.color: Theme.palette.miscColor7
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
type: StatusChatInfoButton.Type.OneToOneChat
muted: true
pinnedMessagesCount: 1
@@ -164,24 +181,32 @@ GridLayout {
title: "group"
subTitle: "Group Chat"
pinnedMessagesCount: 1
icon.color: Theme.palette.miscColor7
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.GroupChat
}
StatusChatInfoButton {
title: "public-chat"
subTitle: "Public Chat"
icon.color: Theme.palette.miscColor7
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.PublicChat
}
StatusChatInfoButton {
title: "community-channel"
subTitle: "Community Chat"
icon.color: Theme.palette.miscColor7
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.CommunityChat
}
StatusChatInfoButton {
title: "community-channel"
subTitle: "Some very long description text to see how the whole item wraps or elides"
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.CommunityChat
pinnedMessagesCount: 3
}
StatusSlider {
width: 360
from: 0
+67 -69
View File
@@ -12,93 +12,94 @@ import StatusQ.Popups 0.1
Column {
spacing: 10
StatusChatToolBar {
toolbarComponent: chatInfoButton1
StatusToolBar {
width: 518
Component {
id: chatInfoButton1
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
}
headerContent: StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
}
}
StatusChatToolBar {
toolbarComponent: chatInfoButton2
StatusToolBar {
width: 518
Component {
id: chatInfoButton2
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.PublicChat
pinnedMessagesCount: 1
muted: true
}
headerContent: StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Muted public chat"
subTitle: "Some subtitle"
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.PublicChat
pinnedMessagesCount: 1
muted: true
}
}
StatusChatToolBar {
StatusToolBar {
notificationCount: 1
toolbarComponent: chatInfoButton3
width: 518
Component {
id: chatInfoButton3
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Some contact"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
pinnedMessagesCount: 1
}
headerContent: StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Group chat"
subTitle: "Group chat subtitle"
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.GroupChat
pinnedMessagesCount: 1
}
}
StatusChatToolBar {
notificationCount: 1
toolbarComponent: tagSelector
StatusToolBar {
width: 518
Component {
id: tagSelector
headerContent: StatusChatInfoButton {
title: "Community chat"
subTitle: "Some very long description text to see how the whole item wraps or ellides"
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.CommunityChat
pinnedMessagesCount: 3
}
}
StatusTagSelector {
namesModel: ListModel {
ListElement {
publicId: "0x0"
name: "Maria"
icon: ""
isIdenticon: false
onlineStatus: 3
isReadonly: true
tagIcon: "crown"
}
ListElement {
publicId: "0x1"
name: "James"
icon: ""
isIdenticon: false
onlineStatus: 1
isReadonly: false
tagIcon: ""
}
StatusToolBar {
headerContent: StatusChatInfoButton {
title: "Very long chat name"
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.CommunityChat
pinnedMessagesCount: 1234567891
}
}
StatusToolBar {
notificationCount: 1
width: 518
StatusTagSelector {
namesModel: ListModel {
ListElement {
publicId: "0x0"
name: "Maria"
icon: ""
isIdenticon: false
onlineStatus: 3
isReadonly: true
tagIcon: "crown"
}
ListElement {
publicId: "0x1"
name: "James"
icon: ""
isIdenticon: false
onlineStatus: 1
isReadonly: false
tagIcon: ""
}
toLabelText: qsTr("To: ")
warningText: qsTr("USER LIMIT REACHED")
}
toLabelText: qsTr("To: ")
warningText: qsTr("USER LIMIT REACHED")
}
}
@@ -493,8 +494,5 @@ Column {
}
}
}
}
}
+202 -62
View File
@@ -1,4 +1,6 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQml.Models 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
@@ -6,10 +8,8 @@ import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Utils 0.1
GridLayout {
columns: 1
columnSpacing: 5
rowSpacing: 5
ColumnLayout {
spacing: 5
StatusNavigationListItem {
title: "Menu Item"
@@ -17,18 +17,18 @@ GridLayout {
StatusNavigationListItem {
title: "Menu Item"
icon.name: "info"
asset.name: "info"
}
StatusNavigationListItem {
title: "Menu Item"
icon.name: "info"
asset.name: "info"
badge.value: 1
}
StatusNavigationListItem {
title: "Menu Item (selected) with very long text"
selected: true
icon.name: "info"
asset.name: "info"
badge.value: 1
}
@@ -55,6 +55,59 @@ GridLayout {
opened: true
}
StatusChatListCategoryItem {
id: categoryItemInteractive
title: "Chat category interactive"
showActionButtons: true
onAddButtonClicked: testEventsList.eventTriggered("Add button clicked")
onMenuButtonClicked: testEventsList.eventTriggered("Menu button clicked")
onToggleButtonClicked: {
opened = !opened
testEventsList.eventTriggered("Toggle button clicked")
}
onTitleClicked: {
testEventsList.eventTriggered("Title clicked")
}
onClicked: {
opened = !opened
testEventsList.eventTriggered("Item clicked", itemId)
}
}
ListView {
id: testEventsList
Layout.fillWidth: true
Layout.preferredHeight: categoryItemInteractive.opened ? 20 * count : 0
clip: true
function eventTriggered(message) {
let obj = eventDelegateComponent.createObject()
obj.text = message
model.insert(0, obj)
}
Component {
id: eventDelegateComponent
ItemDelegate {
implicitHeight: 20
property int index: ObjectModel.index
Timer {
interval: 5000; running: true
onTriggered: testObjectModel.remove(index)
}
}
}
model: ObjectModel {
id: testObjectModel
}
}
StatusChatListItem {
name: "group-chat"
type: StatusChatListItem.Type.GroupChat
@@ -68,18 +121,20 @@ GridLayout {
StatusChatListItem {
name: "community-channel-emoji"
type: StatusChatListItem.Type.CommunityChat
icon.emoji: "😁"
asset.emoji: "😁"
}
StatusChatListItem {
name: "community-channel-with-image"
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
type: StatusChatListItem.Type.CommunityChat
}
StatusChatListItem {
name: "Weird Crazy Otter"
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
type: StatusChatListItem.Type.OneToOneChat
}
@@ -164,7 +219,7 @@ GridLayout {
title: "Title"
subTitle: "Super long description that causes a multiline paragraph and makes the size of the component grow. Let's see how it behaves."
tertiaryTitle: "Tertiary title"
icon.name: "info"
asset.name: "info"
statusListItemTitle.font.pixelSize: 17
statusListItemTitle.font.weight: Font.Bold
@@ -173,27 +228,29 @@ GridLayout {
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
image.isIdenticon: true
asset.isImage: true
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
asset.imgIsIdenticon: true
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
components: [StatusButton {
text: "Button"
size: StatusBaseButton.Size.Small
@@ -203,35 +260,35 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
components: [StatusSwitch {}]
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
components: [StatusRadioButton {}]
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
components: [StatusCheckBox {}]
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
label: "Text"
}
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
label: "Text"
components: [
StatusButton {
@@ -244,7 +301,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
label: "Text"
components: [StatusSwitch {}]
}
@@ -252,7 +309,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
label: "Text"
components: [
StatusRadioButton {}
@@ -262,7 +319,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
label: "Text"
components: [StatusCheckBox {}]
}
@@ -270,7 +327,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusListItem {
title: "Title"
subTitle: "Subtitle"
icon.name: "info"
asset.name: "info"
label: "Text"
components: [
StatusBadge {
@@ -287,14 +344,14 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusListItem {
title: "Title"
icon.name: "info"
asset.name: "info"
type: StatusListItem.Type.Secondary
}
StatusListItem {
title: "Title"
icon.isLetterIdenticon: true
icon.color: "orange"
asset.isLetterIdenticon: true
asset.color: "orange"
}
StatusListItem {
@@ -304,17 +361,19 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusListItem {
title: "Title"
icon.name: "delete"
asset.name: "delete"
type: StatusListItem.Type.Danger
}
StatusListItem {
title: "List Item with Badge"
subTitle: "Subtitle"
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
image.isIdenticon: true
badge.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
asset.isImage: true
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
asset.imgIsIdenticon: true
badge.asset.isImage: true
badge.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
badge.primaryText: "CryptoKitties"
badge.secondaryText: "#test"
}
@@ -322,36 +381,57 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusListItem {
title: "List Item with Badge 2"
subTitle: "Subtitle"
icon.isLetterIdenticon: true
asset.isLetterIdenticon: true
badge.primaryText: "CryptoKitties"
badge.secondaryText: "#test"
badge.icon.color: "orange"
badge.icon.isLetterIdenticon: true
badge.asset.color: "orange"
badge.asset.isLetterIdenticon: true
}
StatusListItem {
title: "List Item with Tags"
icon.isLetterIdenticon: true
asset.isLetterIdenticon: true
bottomModel: 3
bottomDelegate: StatusListItemTag {
title: "tag"
icon.isLetterIdenticon: true
asset.isLetterIdenticon: true
}
}
StatusListItem {
title: "List Item with Inline Tags"
icon.isLetterIdenticon: true
tagsModel : 2
asset.isLetterIdenticon: true
tagsModel: ListModel{
ListElement {
name: "helloworld.eth"
emoji: "😁"
}
ListElement {
name: "account1"
emoji: "😁"
}
ListElement {
name: "account2"
emoji: "😁"
}
ListElement {
name: "account3"
emoji: "😁"
}
ListElement {
name: "account4"
emoji: "😁"
}
}
tagsDelegate: StatusListItemTag {
color: "blue"
height: 24
radius: 6
closeButtonVisible: false
icon.emoji: "😁"
icon.emojiSize: Emoji.size.verySmall
icon.isLetterIdenticon: true
title: "helloworld.eth"
asset.emoji: model.emoji
asset.emojiSize: Emoji.size.verySmall
asset.isLetterIdenticon: true
title: model.name
titleText.font.pixelSize: 12
titleText.color: Theme.palette.indirectColor1
}
@@ -360,10 +440,10 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusListItem {
title: "List Item with Emoji"
subTitle: "Emoji"
icon.emoji: "😁"
icon.color: "yellow"
icon.letterSize: 14
icon.isLetterIdenticon: true
asset.emoji: "😁"
asset.color: "yellow"
asset.letterSize: 14
asset.isLetterIdenticon: true
}
StatusDescriptionListItem {
@@ -382,7 +462,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
title: "Title"
subTitle: "Subtitle"
tooltip.text: "Tooltip"
icon.name: "info"
asset.name: "info"
iconButton.onClicked: tooltip.visible = !tooltip.visible
}
@@ -397,9 +477,10 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
isVerified: true
isContact: true
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
asset.isImage: true
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
image.isIdenticon: true
asset.imgIsIdenticon: true
status: 1 // FIXME: use enum
ringSettings.ringSpecModel:
ListModel {
@@ -417,16 +498,27 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
StatusMemberListItem {
nickName: "carmen.eth"
isUntrustworthy: true
asset.isLetterIdenticon: true
}
StatusMemberListItem {
nickName: "very-long-annoying-nickname.eth"
isUntrustworthy: true
asset.isLetterIdenticon: true
}
StatusMemberListItem {
nickName: "untrusted-admin.eth"
asset.isLetterIdenticon: true
isUntrustworthy: true
isAdmin: true
isContact: true
}
StatusMemberListItem {
nickName: "This girl I know from work"
userName: "annabelle"
asset.isLetterIdenticon: true
status: 1 // FIXME: use enum
}
@@ -435,15 +527,21 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
userName: "annabelle"
pubKey: "0x043a7ed0e8752236a4688563652fd0296453cef00a5dcddbe252dc74f72cc1caa97a2b65e4a1a52d9c30a84c9966beaaaf6b333d659cbdd2e486b443ed1012cf04"
isContact: true
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
asset.isImage: true
asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
image.isIdenticon: true
asset.imgIsIdenticon: true
}
StatusMemberListItem {
nickName: "admin.guy"
userName: "adguy"
isAdmin: true
asset.isLetterIdenticon: true
isUntrustworthy: true
Component.onCompleted: {
print(asset.name, asset.isImage, asset.isLetterIdenticon)
}
}
StatusBaseText {
@@ -457,10 +555,12 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
title: "Nokia 3310"
subTitle: "Incoming device"
label: "loading: true"
icon.emoji: "😁"
icon.color: "hotpink"
icon.letterSize: 14
icon.isLetterIdenticon: true
asset.width: 40
asset.height: 40
asset.emoji: "😁"
asset.color: "hotpink"
asset.letterSize: 14
asset.isLetterIdenticon: true
loading: true
}
@@ -468,10 +568,50 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
title: "Nokia 3310"
subTitle: "Device"
label: "loadingFailed: true"
icon.emoji: "😁"
icon.color: "hotpink"
icon.letterSize: 14
icon.isLetterIdenticon: true
asset.width: 40
asset.height: 40
asset.emoji: "😁"
asset.color: "hotpink"
asset.letterSize: 14
asset.isLetterIdenticon: true
loadingFailed: true
}
StatusListItem {
implicitWidth: 600
title: "List Item with Tags"
subTitle: "03:32"
asset.isLetterIdenticon: true
inlineTagModel: 6
inlineTagDelegate: StatusListItemTag {
height: 24
title: "tag"
asset.isLetterIdenticon: true
}
components: [
ColumnLayout {
Row {
Layout.alignment: Qt.AlignRight
spacing: 4
StatusIcon {
color: Theme.palette.successColor1
icon: "arrow-up"
rotation: 135
height: 18
}
StatusBaseText {
text: "0.0000015 ETH"
font.pixelSize: 15
color: Theme.palette.directColor1
}
}
StatusBaseText {
Layout.alignment: Qt.AlignRight
text: "1201.10 USD"
font.pixelSize: 15
color: Theme.palette.baseColor1
}
}
]
}
}
+1 -1
View File
@@ -40,7 +40,7 @@ ColumnLayout {
}
StatusRoundIcon {
icon.name: "info"
asset.name: "info"
}
}
+24 -20
View File
@@ -109,7 +109,8 @@ Column {
anchors.centerIn: parent
header.title: "Some Title"
header.subTitle: "Subtitle"
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
header.asset.isImage: true
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
}
StatusModal {
@@ -117,7 +118,8 @@ Column {
anchors.centerIn: parent
header.title: "Some Title"
header.subTitle: "Subtitle"
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
header.asset.isImage: true
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
leftButtons: [
StatusBackButton { }
]
@@ -136,7 +138,8 @@ Column {
anchors.centerIn: parent
header.title: "Some Title"
header.subTitle: "Subtitle"
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
header.asset.isImage: true
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
headerActionButton: StatusFlatRoundButton {
type: StatusFlatRoundButton.Type.Secondary
@@ -164,7 +167,8 @@ Column {
StatusModal {
id: modalExample
anchors.centerIn: parent
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
header.asset.isImage: true
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
header.title: "Header"
header.subTitle: "SubTitle"
rightButtons: [
@@ -227,8 +231,8 @@ Column {
anchors.centerIn: parent
header.title: "Header"
header.subTitle: "SubTitle"
header.icon.isLetterIdenticon: true
header.icon.background.color: "red"
header.asset.isLetterIdenticon: true
header.asset.bgColor: "red"
contentItem: StatusBaseText {
anchors.centerIn: parent
@@ -252,9 +256,9 @@ Column {
anchors.centerIn: parent
header.title: "Header"
header.subTitle: "SubTitle"
header.image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.image.isIdenticon: true
header.asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.asset.imgIsIdenticon: true
contentItem: StatusBaseText {
anchors.centerIn: parent
@@ -279,9 +283,9 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
header.title: "Header"
header.subTitle: "SubTitle"
header.headerImageEditable: true
header.image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.image.isIdenticon: true
header.asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.asset.imgIsIdenticon: true
contentItem: StatusBaseText {
anchors.centerIn: parent
@@ -306,9 +310,9 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
header.title: "Some super long text here that exceeds the available space"
header.subTitle: "Some super long text here that exceeds the available space"
header.subTitleElide: Text.ElideMiddle
header.image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.image.isIdenticon: true
header.asset.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0BhCExPynn1gWf9bx498P7/
nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
header.asset.imgIsIdenticon: true
contentItem: StatusBaseText {
anchors.centerIn: parent
@@ -340,7 +344,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
sourceComponent: popupMenu.delegate
onLoaded: {
item.action.text = model.name
item.action.iconSettings.name = model.iconName
item.action.assetSettings.name = model.iconName
}
}
}
@@ -415,11 +419,11 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
topPadding: 8
bottomPadding: 0
implicitHeight: 32
defaultLeftPadding: 4
leftPadding: 4
text: name
icon.emoji: !!emoji ? emoji: ""
icon.emojiSize: Emoji.size.middle
icon.name: !emoji ? "filled-account": ""
asset.emoji: !!emoji ? emoji: ""
asset.emojiSize: Emoji.size.middle
asset.name: !emoji ? "filled-account": ""
normalColor: "transparent"
highlighted: index === floatingHeader.currentIndex
onClicked: {
+48 -22
View File
@@ -14,9 +14,10 @@ ListView {
anchors.fill: parent
anchors.margins: 15
clip: true
delegate: StatusMessage {
id: delegate
width: parent.width
width: ListView.view.width
audioMessageInfoText: "Audio Message"
cancelButtonText: "Cancel"
@@ -26,44 +27,69 @@ ListView {
resendText: "Resend"
pinnedMsgInfoText: "Pinned by"
timestamp: model.timestamp
isAReply: model.isReply
hasMention: model.hasMention
isPinned: model.isPinned
pinnedBy: model.pinnedBy
hasExpired: model.hasExpired
reactionsModel: model.reactions || []
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 {
sender.id: model.senderId
sender.displayName: model.senderDisplayName
sender.secondaryName: model.senderOptionalName
sender.isContact: model.isContact
sender.trustIndicator: model.trustIndicator
sender.profileImage: StatusProfileImageSettings {
width: 40
height: 40
source: model.profileImage
isIdenticon: model.isIdenticon
pubkey: model.senderId
name: model.profileImage || ""
colorId: 1
colorHash: 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 }
}
}
messageText: model.message
hasMention: model.hasMention
isContact: model.isContact
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 {
amISender: model.isReply && model.replyAmISender
sender.id: model.replySenderId || ""
sender.displayName: model.isReply ? model.replySenderName: ""
sender.secondaryName: model.isReply ? model.replySenderEnsName : ""
sender.profileImage: StatusProfileImageSettings {
width: 20
height: 20
source: model.isReply ? model.replyProfileImage: ""
isIdenticon: model.isReply ? model.replyIsIdenticon: ""
name: model.isReply ? model.replyProfileImage: ""
pubkey: model.replySenderId
colorId: 1
colorHash: 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 }
}
}
messageText: model.isReply ? model.replyMessageText: ""
contentType: model.replyContentType
messageContent: model.replyMessageContent
}
quickActions: [
StatusFlatRoundButton {
id: emojiBtn
+3 -4
View File
@@ -98,16 +98,15 @@ Page {
anchors.fill: parent
StatusBaseText {
anchors.left: parent.left
anchors.leftMargin: 252
anchors.right: parent.right
anchors.rightMargin: 252
width: Math.min(553, parent.width - 32)
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -(headerRow.height/2)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
visible: contactsModel.count === 0
wrapMode: Text.WordWrap
font.pixelSize: 15
color: Theme.palette.baseColor1
text: qsTr("You can only send direct messages to your Contacts.\n
Send a contact request to the person you would like to chat with, you will be able to chat with them once they have accepted your contact request.")
+8 -7
View File
@@ -13,7 +13,8 @@ StatusModal {
header.title: "Cryptokitties"
header.subTitle: "Public Community"
header.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
header.asset.isImage: true
header.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
contentItem: Column {
width: root.width
@@ -43,7 +44,7 @@ StatusModal {
title: "Share community"
subTitle: "https://join.status.im/u/0x04...45f19"
tooltip.text: "Copy to clipboard"
icon.name: "copy"
asset.name: "copy"
iconButton.onClicked: tooltip.visible = !tooltip.visible
width: parent.width
}
@@ -57,7 +58,7 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
statusListItemTitle.font.pixelSize: 17
title: "Members"
icon.name: "group-chat"
asset.name: "group-chat"
label: "184"
components: [
StatusIcon {
@@ -72,7 +73,7 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
statusListItemTitle.font.pixelSize: 17
title: "Notifications"
icon.name: "notification"
asset.name: "notification"
components: [
StatusSwitch {}
]
@@ -87,7 +88,7 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
statusListItemTitle.font.pixelSize: 17
title: "Edit community"
icon.name: "edit"
asset.name: "edit"
type: StatusListItem.Type.Secondary
}
@@ -95,7 +96,7 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
statusListItemTitle.font.pixelSize: 17
title: "Transfer ownership"
icon.name: "exchange"
asset.name: "exchange"
type: StatusListItem.Type.Secondary
}
@@ -103,7 +104,7 @@ StatusModal {
anchors.horizontalCenter: parent.horizontalCenter
statusListItemTitle.font.pixelSize: 17
title: "Leave community"
icon.name: "arrow-left"
asset.name: "arrow-left"
type: StatusListItem.Type.Secondary
}
}
+106 -55
View File
@@ -10,10 +10,113 @@ import StatusQ.Core.Theme 0.1
import "data" 1.0
StatusAppThreePanelLayout {
StatusSectionLayout {
id: root
property bool createChat: false
notificationCount: 1
onNotificationButtonClicked: { notificationCount = 0; }
showHeader: !root.createChat
headerContent: RowLayout {
id: chatHeader
signal chatInfoButtonClicked()
signal menuButtonClicked()
signal membersButtonClicked()
signal searchButtonClicked()
StatusChatInfoButton {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: padding
title: "Amazing Funny Squirrel"
subTitle: "Contact"
asset.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
pinnedMessagesCount: 1
}
RowLayout {
id: actionButtons
Layout.alignment: Qt.AlignRight
Layout.rightMargin: padding
spacing: 8
StatusFlatRoundButton {
id: menuButton
objectName: "chatToolbarMoreOptionsButton"
width: 32
height: 32
icon.name: "more"
type: StatusFlatRoundButton.Type.Secondary
// initializing the tooltip
tooltip.visible: !!tooltip.text && menuButton.hovered && !contextMenu.open
tooltip.text: qsTr("More")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
property bool showMoreMenu: false
onClicked: {
menuButton.highlighted = true
let originalOpenHandler = contextMenu.openHandler
let originalCloseHandler = contextMenu.closeHandler
contextMenu.openHandler = function () {
if (!!originalOpenHandler) {
originalOpenHandler()
}
}
contextMenu.closeHandler = function () {
menuButton.highlighted = false
if (!!originalCloseHandler) {
originalCloseHandler()
}
}
contextMenu.openHandler = originalOpenHandler
contextMenu.popup(-contextMenu.width + menuButton.width, menuButton.height + 4)
}
StatusPopupMenu {
id: contextMenu
StatusMenuItem {
text: "Mute Chat"
icon.name: "notification"
}
StatusMenuItem {
text: "Mark as Read"
icon.name: "checkmark-circle"
}
StatusMenuItem {
text: "Clear History"
icon.name: "close-circle"
}
StatusMenuSeparator {}
StatusMenuItem {
text: "Leave Chat"
icon.name: "arrow-left"
type: StatusMenuItem.Type.Danger
}
}
}
Rectangle {
width: 1
height: 24
color: Theme.palette.directColor7
Layout.alignment: Qt.AlignVCenter
visible: (notificationButton.visible && menuButton.visible)
}
}
}
leftPanel: Item {
anchors.fill: parent
anchors.margins: 16
@@ -76,7 +179,7 @@ StatusAppThreePanelLayout {
topPadding: 8
bottomPadding: 8
placeholderText: "Search"
input.icon.name: "search"
input.asset.name: "search"
}
Column {
@@ -91,7 +194,7 @@ StatusAppThreePanelLayout {
anchors.horizontalCenter: parent.horizontalCenter
title: "Contact requests"
requestsCount: 3
sensor.onClicked: demoContactRequestsModal.open()
onClicked: demoContactRequestsModal.open()
}
StatusChatList {
@@ -166,56 +269,4 @@ StatusAppThreePanelLayout {
}
}
}
rightPanel: Item {
anchors.fill: parent
StatusChatToolBar {
width: parent.width
toolbarComponent: statusChatInfoButton
searchButton.visible: false
membersButton.visible: false
notificationCount: 1
onNotificationButtonClicked: notificationCount = 0
popupMenu: StatusPopupMenu {
id: contextMenu
StatusMenuItem {
text: "Mute Chat"
icon.name: "notification"
}
StatusMenuItem {
text: "Mark as Read"
icon.name: "checkmark-circle"
}
StatusMenuItem {
text: "Clear History"
icon.name: "close-circle"
}
StatusMenuSeparator {}
StatusMenuItem {
text: "Leave Chat"
icon.name: "arrow-left"
type: StatusMenuItem.Type.Danger
}
}
Component {
id: statusChatInfoButton
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "Amazing Funny Squirrel"
subTitle: "Contact"
icon.color: Theme.palette.miscColor7
type: StatusChatInfoButton.Type.OneToOneChat
pinnedMessagesCount: 1
}
}
}
}
}
+112 -109
View File
@@ -5,12 +5,12 @@ import QtQuick.Layouts 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Layout 0.1
import StatusQ.Components 0.1
import "../demoapp/data" 1.0
StatusScrollView {
StatusSectionLayout {
id: root
QtObject {
@@ -31,124 +31,127 @@ StatusScrollView {
console.info("Clicked community ID: " + communityId)
}
}
centerPanel: Item {
anchors.fill: parent
clip: true
StatusScrollView {
anchors.fill: parent
contentHeight: column.height + d.layoutVMargin
contentWidth: column.width + d.layoutHMargin
contentHeight: column.height + d.layoutVMargin
contentWidth: column.width + d.layoutHMargin
clip: true
ColumnLayout {
id: column
spacing: 18
ColumnLayout {
id: column
spacing: 18
StatusBaseText {
Layout.topMargin: d.layoutVMargin
Layout.leftMargin: d.layoutHMargin
text: qsTr("Find community")
font.weight: Font.Bold
font.pixelSize: d.titlePixelSize
color: Theme.palette.directColor1
}
// Tags definition - Now hidden - Out of scope
// TODO: Replace by `StatusListItemTagRow`
Row {
visible: d.tagsModel.count > 0
Layout.leftMargin: d.layoutHMargin
Layout.rightMargin: d.layoutHMargin
width: 1234 // by design
spacing: d.stylePadding/2
Repeater {
model: d.tagsModel
delegate: StatusListItemTag {
border.color: Theme.palette.baseColor2
color: "transparent"
height: 32
radius: 36
closeButtonVisible: false
icon.emoji: model.emoji
icon.height: 32
icon.width: icon.height
icon.color: "transparent"
icon.isLetterIdenticon: true
title: model.name
titleText.font.pixelSize: 15
titleText.color: Theme.palette.primaryColor1
StatusBaseText {
text: qsTr("Find community")
font.weight: Font.Bold
font.pixelSize: d.titlePixelSize
color: Theme.palette.directColor1
}
}
}
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Featured")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
// Tags definition - Now hidden - Out of scope
// TODO: Replace by `StatusListItemTagRow`
Row {
visible: d.tagsModel.count > 0
Layout.leftMargin: d.layoutHMargin
Layout.rightMargin: d.layoutHMargin
width: 1234 // by design
spacing: d.stylePadding/2
GridLayout {
id: featuredGrid
Layout.leftMargin: d.layoutHMargin
columns: 3
columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
Repeater {
model: d.featuredCommunitiesModel
delegate: StatusCommunityCard {
locale: "es"
communityId: model.communityId
loaded: model.available
logo: model.logo
name: model.name
description: model.description
members: model.members
popularity: model.popularity
communityColor: model.communityColor
categories: ListModel {
ListElement { name: "sport"; emoji: "🎾"}
ListElement { name: "food"; emoji: "🥑"}
ListElement { name: "privacy"; emoji: "👻"}
Repeater {
model: d.tagsModel
delegate: StatusListItemTag {
border.color: Theme.palette.baseColor2
color: "transparent"
height: 32
radius: 36
closeButtonVisible: false
asset.emoji: model.emoji
asset.height: 32
asset.width: asset.height
asset.color: "transparent"
asset.isLetterIdenticon: true
title: model.name
titleText.font.pixelSize: 15
titleText.color: Theme.palette.primaryColor1
}
}
onClicked: { d.navigateToCommunity(communityId) }
}
}
}
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Popular")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Featured")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
GridLayout {
Layout.leftMargin: d.layoutHMargin
columns: 3
columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
GridLayout {
id: featuredGrid
Layout.leftMargin: d.layoutHMargin
columns: 3
columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
Repeater {
model: d.popularCommunitiesModel
delegate: StatusCommunityCard {
locale: "es"
communityId: model.communityId
loaded: model.available
logo: model.logo
name: model.name
description: model.description
members: model.members
activeUsers: model.activeUsers
popularity: model.popularity
tokenLogo: model.tokenLogo
isPrivate: model.isPrivate
banner: model.banner
Repeater {
model: d.featuredCommunitiesModel
delegate: StatusCommunityCard {
locale: "es"
communityId: model.communityId
loaded: model.available
logo: model.logo
name: model.name
description: model.description
members: model.members
popularity: model.popularity
communityColor: model.communityColor
categories: ListModel {
ListElement { name: "sport"; emoji: "🎾"}
ListElement { name: "food"; emoji: "🥑"}
ListElement { name: "privacy"; emoji: "👻"}
}
onClicked: { d.navigateToCommunity(communityId) }
onClicked: { d.navigateToCommunity(communityId) }
}
}
}
StatusBaseText {
Layout.leftMargin: d.layoutHMargin
Layout.topMargin: 20
text: qsTr("Popular")
font.weight: Font.Bold
font.pixelSize: d.subtitlePixelSize
color: Theme.palette.directColor1
}
GridLayout {
Layout.leftMargin: d.layoutHMargin
columns: 3
columnSpacing: d.stylePadding
rowSpacing: d.stylePadding
Repeater {
model: d.popularCommunitiesModel
delegate: StatusCommunityCard {
locale: "es"
communityId: model.communityId
loaded: model.available
logo: model.logo
name: model.name
description: model.description
members: model.members
activeUsers: model.activeUsers
popularity: model.popularity
tokenLogo: model.tokenLogo
isPrivate: model.isPrivate
banner: model.banner
onClicked: { d.navigateToCommunity(communityId) }
}
}
}
}
}
+109 -78
View File
@@ -1,5 +1,6 @@
import QtQuick 2.12
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.12
import StatusQ.Core 0.1
import StatusQ.Popups 0.1
@@ -10,7 +11,7 @@ import StatusQ.Core.Theme 0.1
import "data" 1.0
StatusAppThreePanelLayout {
StatusSectionLayout {
id: root
property string communityDetailModalTitle: ""
@@ -22,6 +23,101 @@ StatusAppThreePanelLayout {
color: SplitHandle.pressed ? Theme.palette.baseColor2
: (SplitHandle.hovered ? Qt.darker(Theme.palette.baseColor5, 1.1) : "transparent")
}
headerContent: RowLayout {
id: statusToolBar
StatusFlatRoundButton {
id: searchButton
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: padding
icon.name: "search"
type: StatusFlatRoundButton.Type.Secondary
// initializing the tooltip
tooltip.text: qsTr("Search")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
onClicked: {
searchButton.highlighted = !searchButton.highlighted;
searchPopup.setSearchSelection(communityDetailModalTitle,
"",
communityDetailModalImage);
searchPopup.open();
}
}
StatusChatInfoButton {
Layout.preferredWidth: Math.min(implicitWidth, parent.width)
Layout.fillHeight: true
title: "general"
subTitle: "Community Chat"
asset.color: Theme.palette.miscColor6
type: StatusChatInfoButton.Type.CommunityChat
}
Item {
Layout.fillWidth: true
}
StatusFlatRoundButton {
id: membersButton
icon.name: "group-chat"
type: StatusFlatRoundButton.Type.Secondary
// initializing the tooltip
tooltip.text: qsTr("Members")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
onClicked: {
membersButton.highlighted = !membersButton.highlighted;
root.showRightPanel = !root.showRightPanel;
}
}
StatusSearchPopup {
id: searchPopup
searchOptionsPopupMenu: searchPopupMenu
onAboutToHide: {
if (searchPopupMenu.visible) {
searchPopupMenu.close();
}
//clear menu
for (var i = 2; i < searchPopupMenu.count; i++) {
searchPopupMenu.removeItem(searchPopupMenu.takeItem(i));
}
}
onClosed: {
statusToolBar.searchButton.highlighted = false
searchPopupMenu.dismiss();
}
onSearchTextChanged: {
if (searchPopup.searchText !== "") {
searchPopup.loading = true;
searchModelSimTimer.start();
} else {
searchPopup.searchResults = [];
searchModelSimTimer.stop();
}
}
Timer {
id: searchModelSimTimer
interval: 500
onTriggered: {
if (searchPopup.searchText.startsWith("c")) {
searchPopup.searchResults = Models.searchResultsA;
} else {
searchPopup.searchResults = Models.searchResultsB;
}
searchPopup.loading = false;
}
}
}
StatusSearchLocationMenu {
id: searchPopupMenu
searchPopup: searchPopup
locationModel: Models.optionsModel
}
}
leftPanel: Item {
id: leftPanel
@@ -33,8 +129,9 @@ StatusAppThreePanelLayout {
chatInfoButton.title: "CryptoKitties"
chatInfoButton.subTitle: "128 Members"
chatInfoButton.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
chatInfoButton.icon.color: Theme.palette.miscColor6
chatInfoButton.asset.isImage: true
chatInfoButton.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
chatInfoButton.asset.color: Theme.palette.miscColor6
chatInfoButton.onClicked: { chatInfoButtonClicked(); }
popupMenu: StatusPopupMenu {
@@ -164,79 +261,11 @@ StatusAppThreePanelLayout {
}
centerPanel: Item {
StatusChatToolBar {
id: statusChatToolBar
width: parent.width
toolbarComponent: statusChatInfoButton
onSearchButtonClicked: {
searchButton.highlighted = !searchButton.highlighted;
searchPopup.setSearchSelection(communityDetailModalTitle,
"",
communityDetailModalImage);
searchPopup.open();
}
membersButton.onClicked: membersButton.highlighted = !membersButton.highlighted
onMembersButtonClicked: {
root.showRightPanel = !root.showRightPanel;
}
Component {
id: statusChatInfoButton
StatusChatInfoButton {
width: Math.min(implicitWidth, parent.width)
title: "general"
subTitle: "Community Chat"
icon.color: Theme.palette.miscColor6
type: StatusChatInfoButton.Type.CommunityChat
}
}
}
StatusSearchPopup {
id: searchPopup
searchOptionsPopupMenu: searchPopupMenu
onAboutToHide: {
if (searchPopupMenu.visible) {
searchPopupMenu.close();
}
//clear menu
for (var i = 2; i < searchPopupMenu.count; i++) {
searchPopupMenu.removeItem(searchPopupMenu.takeItem(i));
}
}
onClosed: {
statusChatToolBar.searchButton.highlighted = false
searchPopupMenu.dismiss();
}
onSearchTextChanged: {
if (searchPopup.searchText !== "") {
searchPopup.loading = true;
searchModelSimTimer.start();
} else {
searchPopup.searchResults = [];
searchModelSimTimer.stop();
}
}
Timer {
id: searchModelSimTimer
interval: 500
onTriggered: {
if (searchPopup.searchText.startsWith("c")) {
searchPopup.searchResults = Models.searchResultsA;
} else {
searchPopup.searchResults = Models.searchResultsB;
}
searchPopup.loading = false;
}
}
}
StatusSearchLocationMenu {
id: searchPopupMenu
searchPopup: searchPopup
locationModel: Models.optionsModel
anchors.fill: parent
StatusBaseText {
anchors.centerIn: parent
font.pixelSize: 15
text: qsTr("Community content here")
}
}
@@ -273,8 +302,10 @@ StatusAppThreePanelLayout {
isVerified: model.isVerified
isUntrustworthy: model.isUntrustworthy
isContact: model.isContact
image.source: model.icon
image.isIdenticon: false
asset.name: model.icon
asset.isImage: (asset.name !== "")
asset.isLetterIdenticon: (asset.name === "")
asset.imgIsIdenticon: false
status: model.onlineStatus
}
}
@@ -8,7 +8,7 @@ import StatusQ.Core.Theme 0.1
import "data" 1.0
StatusAppTwoPanelLayout {
StatusSectionLayout {
id: root
leftPanel: Item {
@@ -41,7 +41,7 @@ StatusAppTwoPanelLayout {
model: Models.demoProfileGeneralMenuItems
delegate: StatusNavigationListItem {
title: model.title
icon.name: model.icon
asset.name: model.icon
}
}
@@ -51,7 +51,7 @@ StatusAppTwoPanelLayout {
model: Models.demoProfileSettingsMenuItems
delegate: StatusNavigationListItem {
title: model.title
icon.name: model.icon
asset.name: model.icon
}
}
@@ -65,7 +65,7 @@ StatusAppTwoPanelLayout {
model: Models.demoProfileOtherMenuItems
delegate: StatusNavigationListItem {
title: model.title
icon.name: model.icon
asset.name: model.icon
}
}
}
File diff suppressed because one or more lines are too long
+4 -3
View File
@@ -35,7 +35,7 @@ ColumnLayout {
id: searchInput
Layout.fillWidth: true
input.icon.name: "search"
input.asset.name: "search"
placeholderText: "nickname.."
}
@@ -43,7 +43,7 @@ ColumnLayout {
id: contactBtn
icon.name: "tiny/tiny-contact"
identicon.icon.color: Theme.palette.primaryColor1
identicon.asset.color: Theme.palette.primaryColor1
onClicked: highlighted = !highlighted
}
@@ -51,7 +51,7 @@ ColumnLayout {
id: verifiedBtn
icon.name: "tiny/tiny-checkmark"
identicon.icon.color: Theme.palette.primaryColor1
identicon.asset.color: Theme.palette.primaryColor1
onClicked: highlighted = !highlighted
}
}
@@ -94,6 +94,7 @@ ColumnLayout {
nickName: model.nick
isVerified: model.isVerified
isContact: model.isContact
asset.isLetterIdenticon: true
}
}
+47 -29
View File
@@ -63,11 +63,11 @@ StatusWindow {
}
}
StatusAppLayout {
StatusMainLayout {
id: appLayout
anchors.fill: parent
appNavBar: StatusAppNavBar {
leftPanel: StatusAppNavBar {
height: rootWindow.height
communityTypeRole: "sectionType"
@@ -105,30 +105,34 @@ StatusWindow {
}
}
appView: StackView {
id: stackView
rightPanel: Item {
anchors.fill: parent
initialItem: libraryDocumentationCmp
}
ThemeSwitch {
anchors.top: parent.top
anchors.topMargin: 32
anchors.right: parent.right
anchors.rightMargin: 32
lightThemeEnabled: storeSettings.lightTheme
onLightThemeEnabledChanged: {
Theme.palette = lightThemeEnabled ? rootWindow.darkTheme : rootWindow.lightTheme
storeSettings.lightTheme = lightThemeEnabled
StackView {
id: stackView
anchors.fill: parent
initialItem: libraryDocumentationCmp
}
ThemeSwitch {
anchors.top: parent.top
anchors.topMargin: 32
anchors.right: parent.right
anchors.rightMargin: 32
lightThemeEnabled: storeSettings.lightTheme
onLightThemeEnabledChanged: {
Theme.palette = lightThemeEnabled ? rootWindow.darkTheme : rootWindow.lightTheme
storeSettings.lightTheme = lightThemeEnabled
}
}
}
}
Component {
id: libraryDocumentationCmp
StatusAppTwoPanelLayout {
StatusSectionLayout {
id: mainPageView
showHeader: false
function page(name, fillPage) {
storeSettings.fillPage = fillPage ? true : false
@@ -298,6 +302,16 @@ StatusWindow {
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title);
}
StatusNavigationListItem {
title: "StatusItemSelector"
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title, true);
}
StatusNavigationListItem {
title: "StatusChartPanel"
selected: viewLoader.source.toString().includes(title)
onClicked: mainPageView.page(title, true);
}
StatusListSectionHeadline { text: "StatusQ.Popup" }
StatusNavigationListItem {
title: "StatusPopupMenu"
@@ -343,8 +357,8 @@ StatusWindow {
}
}
rightPanel: Item {
id: rightPanel
centerPanel: Item {
id: centerPanel
anchors.fill: parent
StatusScrollView {
@@ -357,7 +371,7 @@ StatusWindow {
Item {
id: pageWrapper
width: rightPanel.width
width: centerPanel.width
anchors.top: parent.top
height: Math.max(rootWindow.height, viewLoader.height + 128)
scale: rootWindow.factor
@@ -415,8 +429,9 @@ StatusWindow {
Component {
id: examplesCmp
StatusAppTwoPanelLayout {
StatusSectionLayout {
id: examplesView
showHeader: false
function example(name) {
examplesLoader.source = Qt.resolvedUrl("./examples/" + name + ".qml")
@@ -444,16 +459,19 @@ StatusWindow {
}
}
rightPanel: StatusScrollView {
id: examplesRightPanel
centerPanel: Item {
anchors.fill: parent
anchors.margins: 64
anchors.topMargin: anchors.margins + 32
StatusScrollView {
id: examplesCenterPanel
anchors.fill: parent
anchors.margins: 64
anchors.topMargin: anchors.margins + 32
Loader {
id: examplesLoader
width: examplesRightPanel.availableWidth
source: storeSettings.selectedExample !== "" ? storeSettings.selectedExample : examplesView.defaultExampleSource
Loader {
id: examplesLoader
width: examplesCenterPanel.availableWidth
source: storeSettings.selectedExample !== "" ? storeSettings.selectedExample : examplesView.defaultExampleSource
}
}
}
}
+193
View File
@@ -0,0 +1,193 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import Sandbox 0.1
Item {
QtObject {
id: d
//dummy data
property real stepSize: 1000
property real minStep: 12000
property real maxStep: 22000
property var graphTabsModel: [{text: "Price", enabled: true}, {text: "Balance", enabled: false}]
property var timeRangeTabsModel: [{text: "1H", enabled: true},
{text: "1D", enabled: true},{text: "7D", enabled: true},
{text: "1M", enabled: true}, {text: "6M", enabled: true},
{text: "1Y", enabled: true}, {text: "ALL", enabled: true}]
property var simTimer: Timer {
running: true
interval: 3000
repeat: true
onTriggered: {
d.generateData();
}
}
function minutes(minutes = 0) {
var newMinute = new Date(new Date().getTime() - (minutes * 60 * 1000)).toString();
if (newMinute.slice(10,12) === "00") {
var dateToday = new Date(Date.now()).toString();
return dateToday.slice(4,7) + " " + dateToday.slice(8,10);
}
return newMinute.slice(10,16);
}
function hour(hours = 0) {
var newHour = new Date(new Date().getTime() - (hours * 60 * 60 * 1000)).toString();
if (newHour.slice(10,12) === "00") {
var dateToday = new Date(Date.now()).toString();
return dateToday.slice(4,7) + " " + dateToday.slice(8,10);
}
return newHour.slice(10,16);
}
function day(before = 0) {
var newDay = new Date(Date.now() - before * 24 * 60 * 60 * 1000).toString();
return newDay.slice(4,7) + " " + newDay.slice(8,10);
}
function month(before = 0) {
var newMonth = new Date(Date.now() - before * 24 * 60 * 60 * 1000).toString();
return newMonth.slice(4,7) + " '" + newMonth.slice(newMonth.indexOf("G")-3, newMonth.indexOf("G")-1);
}
property var timeRange: [
{'1H': [minutes(60), minutes(55), minutes(50), minutes(45), minutes(40), minutes(35), minutes(30), minutes(25), minutes(20), minutes(15), minutes(10), minutes(5), minutes()]},
{'1D': [hour(24), hour(23), hour(22), hour(21), hour(20), hour(19), hour(18), hour(17), hour(16), hour(15), hour(14), hour(13),
hour(12), hour(11), hour(10), hour(9), hour(8), hour(7), hour(6), hour(5), hour(4), hour(3), hour(2), hour(1), hour()]},
{'7D': [day(6), day(5), day(4), day(3), day(2), day(1), day()]},
{'1M': [day(30), day(28), day(26), day(24), day(22), day(20), day(18), day(16), day(14), day(12), day(10), day(8), day(6), day(4), day()]},
{'6M': [month(150), month(120), month(90), month(60), month(30), month()]},
{'1Y': [month(330), month(300), month(270), month(240), month(210), month(180), month(150), month(120), month(90), month(60), month(30), month()]},
{'ALL': ['2016', '2017', '2018', '2019', '2020', '2021', '2022']}
]
function generateData() {
var result = [];
for (var i = 0; i < timeRange[graphDetail.timeRangeTabBarIndex][graphDetail.selectedTimeRange].length; ++i) {
result[i] = Math.random() * (maxStep - minStep) + minStep;
}
graphDetail.chart.chartData.datasets[0].data = result;
graphDetail.chart.animateToNewData();
}
}
StatusChartPanel {
id: graphDetail
height: 290
anchors.left: parent.left
anchors.leftMargin: 24
anchors.right: parent.right
anchors.rightMargin: 24
anchors.verticalCenter: parent.verticalCenter
graphsModel: d.graphTabsModel
timeRangeModel: d.timeRangeTabsModel
onHeaderTabClicked: {
//TODO
//if time range tab
d.generateData();
//if graph bar
//switch graph
}
chart.chartType: 'line'
chart.chartData: {
return {
labels: d.timeRange[graphDetail.timeRangeTabBarIndex][graphDetail.selectedTimeRange],
datasets: [{
label: 'Price',
xAxisId: 'x-axis-1',
yAxisId: 'y-axis-1',
backgroundColor: (Theme.palette.name === "dark") ? 'rgba(136, 176, 255, 0.2)' : 'rgba(67, 96, 223, 0.2)',
borderColor: (Theme.palette.name === "dark") ? 'rgba(136, 176, 255, 1)' : 'rgba(67, 96, 223, 1)',
borderWidth: 3,
pointRadius: 0,
//data: d.generateData()
}]
}
}
chart.chartOptions: {
return {
maintainAspectRatio: false,
responsive: true,
legend: {
display: false
},
//TODO enable zoom
// zoom: {
// enabled: true,
// drag: true,
// speed: 0.1,
// threshold: 2
// },
// pan:{enabled:true,mode:'x'},
tooltips: {
intersect: false,
displayColors: false,
callbacks: {
footer: function(tooltipItem, data) { return 'Vol: $43,042,678,876'; },
label: function(tooltipItem, data) {
let label = data.datasets[tooltipItem.datasetIndex].label || '';
if (label) {
label += ': ';
}
label += tooltipItem.yLabel.toFixed(2);
return label.slice(0,label.indexOf(":")+1)+ " $"+label.slice(label.indexOf(":")+2, label.length);
}
}
},
scales: {
xAxes: [{
id: 'x-axis-1',
position: 'bottom',
gridLines: {
drawOnChartArea: false,
drawBorder: false,
drawTicks: false,
},
ticks: {
fontSize: 10,
fontColor: (Theme.palette.name === "dark") ? '#909090' : '#939BA1',
padding: 16
}
}],
yAxes: [{
position: 'left',
id: 'y-axis-1',
gridLines: {
borderDash: [8, 4],
drawBorder: false,
drawTicks: false,
color: (Theme.palette.name === "dark") ? '#909090' : '#939BA1'
},
beforeDataLimits: (axis) => {
axis.paddingTop = 25;
axis.paddingBottom = 0;
},
ticks: {
fontSize: 10,
fontColor: (Theme.palette.name === "dark") ? '#909090' : '#939BA1',
padding: 8,
min: d.minStep,
max: d.maxStep,
stepSize: d.stepSize,
callback: function(value, index, ticks) {
return '$' + value;
},
}
}]
}
}
}
}
}
+3 -2
View File
@@ -14,8 +14,9 @@ GridLayout {
StatusChatInfoToolBar {
chatInfoButton.title: "Cryptokitties"
chatInfoButton.subTitle: "128 Members"
chatInfoButton.image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
chatInfoButton.icon.color: Theme.palette.miscColor6
chatInfoButton.asset.isImage: true
chatInfoButton.asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
chatInfoButton.asset.color: Theme.palette.miscColor6
popupMenu: StatusPopupMenu {
+1 -1
View File
@@ -36,7 +36,7 @@ Item {
leftPadding: 0
rightPadding: 0
label: qsTr("Select tags that will fit your Community")
input.icon.name: "search"
input.asset.name: "search"
placeholderText: qsTr("Search tags")
Layout.fillWidth: true
}
@@ -26,7 +26,7 @@ Column {
anchors.horizontalCenter: parent.horizontalCenter
expandable: false
icon.name: "seed-phrase"
asset.name: "seed-phrase"
primaryText: "Back up seed phrase"
secondaryText: "Back up your seed phrase now to secure this account ajhaDH SDHSAHDLSADBSA,DLISAHDLASD ADASDHASLDHALSDHAS DAS,DASJDGLIASGD"
button.text: qsTr("Back up seed phrase")
@@ -36,7 +36,7 @@ Column {
anchors.horizontalCenter: parent.horizontalCenter
expandable: true
icon.name: "secret"
asset.name: "secret"
primaryText: "Account signing phrase"
secondaryText: "View your signing phrase and ensure that you never get scammed. View your signing phrase and ensure that you never get scammed."
expandableComponent: notImplemented
@@ -46,7 +46,7 @@ Column {
anchors.horizontalCenter: parent.horizontalCenter
expandable: true
icon.name: "seed-phrase"
asset.name: "seed-phrase"
primaryText: "View private key"
secondaryText: "Back up your seed phrase now to secure this account"
expandableComponent: notImplemented
@@ -74,7 +74,8 @@ Column {
type: StatusExpandableItem.Type.Secondary
expandable: true
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
primaryText: "CryptoKitties"
additionalText: "1456 USD"
expandableComponent: notImplemented
@@ -85,7 +86,8 @@ Column {
type: StatusExpandableItem.Type.Secondary
expandable: true
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
asset.isImage: true
asset.name: "qrc:/demoapp/data/profile-image-1.jpeg"
primaryText: "Adding Really long text to test scenario of having very long text along with tertiary text"
additionalText: "564.90 USD"
expandableComponent: notImplemented
+21 -13
View File
@@ -33,9 +33,8 @@ Column {
StatusInput {
label: "Label"
input.icon.name: "search"
placeholderText: "Input with icon"
input.asset.name: "search"
input.placeholderText: "Input with icon"
}
StatusInput {
@@ -57,6 +56,15 @@ Column {
input.clearable: true
}
StatusPasswordInput {
placeholderText: "Password"
}
StatusPasswordInput {
signingPhrase: "orange hello cygnet"
placeholderText: "Password"
}
Item {
implicitWidth: 480
implicitHeight: 82
@@ -112,9 +120,9 @@ Column {
StatusInput {
label: "StatusInput"
secondaryLabel: "with right icon"
input.icon.width: 15
input.icon.height: 11
input.icon.name: text !== "" ? "checkmark" : ""
input.asset.width: 15
input.asset.height: 11
input.asset.name: text !== "" ? "checkmark" : ""
input.leftIcon: false
}
@@ -192,9 +200,9 @@ Column {
StatusInput {
property bool toggled: true
label: "Input with emoji icon"
placeholderText: "Enter Name"
input.icon.emoji: toggled ? "😁" : "🧸"
input.icon.color: "blue"
input.placeholderText: "Enter Name"
input.asset.emoji: toggled ? "😁" : "🧸"
input.asset.color: "blue"
input.isIconSelectable: true
onIconClicked: {
toggled = !toggled
@@ -204,10 +212,10 @@ Column {
StatusInput {
property bool toggled: true
label: "Input with selectable icon which is not an emoji"
placeholderText: "Enter Name"
input.icon.emoji: ""
input.icon.name: toggled ? "filled-account" : "image"
input.icon.color: "blue"
input.placeholderText: "Enter Name"
input.asset.emoji: ""
input.asset.name: toggled ? "filled-account" : "image"
input.asset.color: "blue"
input.isIconSelectable: true
onIconClicked: {
toggled = !toggled
+22 -3
View File
@@ -1,4 +1,4 @@
import QtQuick 2.0
import QtQuick 2.14
import QtQuick.Layouts 1.14
import StatusQ.Components 0.1
@@ -15,25 +15,44 @@ ColumnLayout {
defaultItemText: "Example: Empty items"
andOperatorText: "and"
orOperatorText: "or"
popupItem: StatusDropdown {
itemsModel: ListModel {
id: model
}
StatusDropdown {
id: dropdown
parent: selector.addButton
width: 200
contentItem: ColumnLayout {
spacing: 10
StatusInput {
id: input
text: "Sample"
Layout.fillWidth: true
}
StatusButton {
Layout.alignment: Qt.AlignHCenter
text: "Add element"
onClicked: {
selector.addItem(input.text, "qrc:/images/SNT.png", selector.itemsModel.count > 0 ? Utils.Operators.Or : Utils.Operators.None)
model.append({
text: input.text,
imageSource: "qrc:/images/SNT.png",
operator: model.count > 0 ? Utils.Operators.Or : Utils.Operators.None
})
dropdown.close()
}
}
}
}
addButton.onClicked: {
dropdown.x = mouse.x
dropdown.y = mouse.y
dropdown.open()
}
}
StatusButton {
+69
View File
@@ -72,4 +72,73 @@ Column {
text: "Introduced PIN: " + regexPinInput.pinInput
font.pixelSize: 12
}
// PUK input that accepts only numbers
StatusBaseText {
topPadding: 100
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.palette.directColor1
text: "Enter Keycard PUK"
font.pixelSize: 30
font.bold: true
}
StatusPinInput {
id: numbersPukInput
anchors.horizontalCenter: parent.horizontalCenter
validator: StatusRegularExpressionValidator { regularExpression: /[0-9]+/ }
pinLen: 12
}
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 PUK: " + numbersPukInput.pinInput
font.pixelSize: 12
}
// PUK input that accepts only numbers
StatusBaseText {
topPadding: 100
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.palette.directColor1
text: "Enter Keycard PUK"
font.pixelSize: 30
font.bold: true
}
StatusPinInput {
id: numbersPukInputWithSpacing
anchors.horizontalCenter: parent.horizontalCenter
validator: StatusRegularExpressionValidator { regularExpression: /[0-9]+/ }
pinLen: 12
additionalSpacing: 32
additionalSpacingOnEveryNItems: 4
Component.onCompleted: {
numbersPukInputWithSpacing.statesInitialization()
numbersPukInputWithSpacing.forceFocus()
}
}
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 PUK: " + numbersPukInputWithSpacing.pinInput
font.pixelSize: 12
}
}
+31 -43
View File
@@ -22,8 +22,8 @@ GridLayout {
onClicked: complexMenu.popup()
}
StatusButton {
id: customPopupButton
text: "Menu with custom images and icons"
onClicked: customMenu.popup()
}
@@ -51,61 +51,51 @@ GridLayout {
StatusPopupMenu {
id: complexMenu
// subMenuItemIcons: [{ icon: 'info' }]
subMenuItemIcons: [{ icon: 'info' }]
StatusMenuItem {
text: "One"
iconSettings.name: "info"
assetSettings.name: "info"
}
StatusMenuSeparator {}
StatusMenuItem {
text: "Two"
iconSettings.name: "info"
assetSettings.name: "info"
}
StatusMenuItem {
text: "Three"
iconSettings.name: "info"
enabled: false
assetSettings.name: "info"
}
StatusPopupMenu {
title: "Four"
iconSettings.name: "info"
StatusMenuItem {
text: "One"
iconSettings.name: "info"
assetSettings.name: "info"
}
StatusMenuItem {
text: "Three"
iconSettings.name: "info"
assetSettings.name: "info"
}
}
}
StatusPopupMenu {
id: customMenu
width: customPopupButton.width
// subMenuItemIcons: [
// {
// icon: "chat"
// },
// {
// source: "qrc:/demoapp/data/profile-image-1.jpeg"
// },
// {
// isLetterIdenticon: true,
// color: "red"
// }
// ]
MenuItem {
text: "Default MenuItem, action: " + action
}
subMenuItemIcons: [
{ icon: "chat" },
{
source: "qrc:/demoapp/data/profile-image-1.jpeg"
},
{
isLetterIdenticon: true,
color: "red"
}
]
StatusMenuItem {
text: "Anywhere"
@@ -114,55 +104,53 @@ GridLayout {
StatusMenuSeparator {}
StatusPopupMenu {
title: "Chat"
iconSettings.name: "chat"
title: "Chat"
StatusMenuItem {
text: "vitalik.eth"
image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
assetSettings.isImage: true
assetSettings.name: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
image.isIdenticon: true
assetSettings.imgIsIdenticon: true
}
StatusMenuItem {
text: "Pascal"
image.source: "qrc:/demoapp/data/profile-image-1.jpeg"
assetSettings.isImage: true
assetSettings.name: "qrc:/demoapp/data/profile-image-1.jpeg"
}
}
StatusPopupMenu {
title: "Cryptokitties"
imageSettings.source: "qrc:/demoapp/data/profile-image-1.jpeg"
StatusMenuItem {
text: "welcome"
iconSettings.name: "channel"
iconSettings.color: Theme.palette.directColor1
assetSettings.name: "channel"
assetSettings.color: Theme.palette.directColor1
}
StatusMenuItem {
text: "support"
iconSettings.name: "channel"
iconSettings.color: Theme.palette.directColor1
assetSettings.name: "channel"
assetSettings.color: Theme.palette.directColor1
}
StatusMenuHeadline { text: "Public" }
StatusMenuItem {
text: "news"
iconSettings.name: "channel"
iconSettings.color: Theme.palette.directColor1
assetSettings.name: "channel"
assetSettings.color: Theme.palette.directColor1
}
}
StatusPopupMenu {
title: "Another community"
iconSettings.isLetterIdenticon: true
iconSettings.color: "red"
StatusMenuItem {
text: "welcome"
iconSettings.isLetterIdenticon: true
iconSettings.background.color: "red"
assetSettings.isLetterIdenticon: true
assetSettings.bgColor: "red"
}
}
}
+2 -1
View File
@@ -41,8 +41,9 @@ Column {
model: commmonModel
selectMenu.delegate: StatusMenuItemDelegate {
statusPopupMenu: select
action: StatusMenuItem {
iconSettings.name: "filled-account"
assetSettings.name: "filled-account"
text: name
onTriggered: {
selectedItem.text = name
-3
View File
@@ -75,11 +75,8 @@
<file>main.qml</file>
<file>ThemeSwitch.qml</file>
<file>examples/FilteringSorting.qml</file>
<file>images/RARI.png</file>
<file>images/SRToken.png</file>
<file>demoapp/data/profile-image-1.jpeg</file>
<file>demoapp/data/profile-image-2.jpeg</file>
<file>pages/StatusItemSelectorPage.qml</file>
<file>pages/StatusComboBoxPage.qml</file>
</qresource>
</RCC>
+5 -5
View File
@@ -239,7 +239,7 @@ Rectangle {
id: waitTimer
interval: lockTimeout
onTriggered: {
if(advancedInput.edit.text)
if(advancedInput.text)
advancedInput.locked = true
}
}
@@ -311,7 +311,7 @@ Rectangle {
}
PropertyChanges {
target: advancedInput
edit.color: Theme.palette.directColor1
input.color: Theme.palette.directColor1
}
PropertyChanges {
target: basicInput
@@ -370,7 +370,7 @@ Rectangle {
}
PropertyChanges {
target: advancedInput
edit.color: disabled ? Theme.palette.directColor5 : Theme.palette.dangerColor1
input.edit.color: disabled ? Theme.palette.directColor5 : Theme.palette.dangerColor1
}
PropertyChanges {
target: basicInput
@@ -429,7 +429,7 @@ Rectangle {
}
PropertyChanges {
target: advancedInput
edit.color: Theme.palette.directColor1
input.color: Theme.palette.directColor1
}
PropertyChanges {
target: basicInput
@@ -488,7 +488,7 @@ Rectangle {
}
PropertyChanges {
target: advancedInput
edit.color: Theme.palette.directColor1
input.color: Theme.palette.directColor1
}
PropertyChanges {
target: basicInput
+144
View File
@@ -0,0 +1,144 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import StatusQ.Controls 0.1
import "private/chart"
/*!
\qmltype StatusChartPanel
\inherits Page
\inqmlmodule StatusQ.Components
\since StatusQ.Components 0.1
\brief Displays a chart component together with an optional header in order to add a list of options.
Inherits \l{https://doc.qt.io/qt-5/qml-qtquick-controls2-page.html}{Page}.
The \c StatusChartPanel displays a customizable chart component. Additionally, options
can be added in the header in both right and left sides given graphTabsModel and timeRangeTabsModel
property are set respectively.
For example:
\qml
StatusChartPanel {
id: graphDetail
width: parent.width
height: 290
anchors.verticalCenter: parent.verticalCenter
graphsModel: d.graphTabsModel
timeRangeModel: d.timeRangeTabsModel
chart.chartType: 'line'
chart.chartData: {
return {
datasets: [{
data: d.data
}],
...
}
}
chart.chartOptions: {
return {
legend: {
display: false
},
...
}
}
}
\endqml
\image status_chart_panel.png
For a list of components available see StatusQ.
*/
Page {
id: root
/*!
\qmlproperty var StatusChartPanel::graphsModel
This property holds the graphs model options to be set on the left side tab bar of the header.
*/
property var graphsModel
/*!
\qmlproperty var StatusChartPanel::timeRangeModel
This property holds the time range options to be set on the right side tab bar of the header.
*/
property var timeRangeModel
/*!
\qmlproperty alias StatusChartPanel::graphComponent
This property holds holds a reference to the graph component.
*/
property alias chart: graphComponent
/*!
\qmlproperty alias StatusChartPanel::timeRangeTabBarIndex
This property holds holds a reference to the time range tab bar current index.
*/
property alias timeRangeTabBarIndex: timeRangeTabBar.currentIndex
/*!
\qmlproperty string StatusChartPanel::selectedTimeRange
This property holds holds the text of the current time range tab bar selected tab.
*/
property string selectedTimeRange: timeRangeTabBar.currentItem.text
/*!
\qmlsignal
This signal is emitted when a header tab bar is clicked.
*/
signal headerTabClicked(string text)
Component {
id: tabButton
StatusTabButton {
leftPadding: 0
width: implicitWidth
onClicked: {
root.headerTabClicked(text);
}
}
}
Component.onCompleted: {
if (!!timeRangeModel) {
for (var i = 0; i < timeRangeModel.length; i++) {
var timeTab = tabButton.createObject(root, { text: timeRangeModel[i].text,
enabled: timeRangeModel[i].enabled });
timeRangeTabBar.addItem(timeTab);
}
}
if (!!graphsModel) {
for (var j = 0; j < graphsModel.length; j++) {
var graphTab = tabButton.createObject(root, { text: graphsModel[j].text,
enabled: graphsModel[j].enabled });
graphsTabBar.addItem(graphTab);
}
}
}
background: null
header: Item {
height: childrenRect.height
RowLayout {
anchors.left: parent.left
anchors.leftMargin: 46
anchors.right: parent.right
StatusTabBar {
id: graphsTabBar
}
StatusTabBar {
id: timeRangeTabBar
Layout.alignment: Qt.AlignRight
}
}
}
contentItem: Item {
Chart {
id: graphComponent
anchors.fill: parent
}
}
}
+8 -8
View File
@@ -118,12 +118,12 @@ Column {
notificationsCount: model.notificationsCount
highlightWhenCreated: !!model.highlight
selected: (model.active && root.highlightItem)
icon.emoji: model.emoji
icon.color: !!model.color ? model.color : Theme.palette.userCustomizationColors[model.colorId]
image.isIdenticon: false
image.source: model.icon
asset.emoji: !!model.emoji ? model.emoji : ""
asset.color: !!model.color ? model.color : Theme.palette.userCustomizationColors[model.colorId]
asset.isImage: model.icon.includes("data")
asset.name: model.icon
ringSettings.ringSpecModel: model.colorHash
onlineStatus: model.onlineStatus
sensor.cursorShape: dragSensor.cursorShape
@@ -228,9 +228,9 @@ Column {
notificationsCount: model.notificationsCount
selected: draggable.chatListItem.selected
icon.color: draggable.chatListItem.icon.color
image.isIdenticon: draggable.chatListItem.image.isIdenticon
image.source: draggable.chatListItem.image.source
asset.color: draggable.chatListItem.asset.color
asset.imgIsIdenticon: draggable.chatListItem.asset.imgIsIdenticon
asset.name: draggable.chatListItem.asset.name
}
}
}
@@ -32,7 +32,7 @@ Item {
property bool draggableCategories: false
// Keeps track of expanded category state. Should only be modified
// internally at runtime.
property var openedCategoryState: new Object({})
property var openedCategoryState: ({})
property Component categoryPopupMenu
property Component chatListPopupMenu
@@ -71,6 +71,7 @@ Item {
spacing: 4
StatusChatList {
objectName: "statusChatListAndCategoriesChatList"
id: statusChatList
visible: statusChatList.model.count > 0
onChatItemSelected: root.chatItemSelected(categoryId, id)
@@ -113,6 +114,7 @@ Item {
delegate: Item {
id: draggable
objectName: model.name
width: statusChatListCategory.width
height: statusChatListCategory.height
property alias chatListCategory: statusChatListCategory
@@ -259,6 +261,7 @@ Item {
Repeater {
id: statusChatListCategories
objectName: "communityChatListCategories"
visible: !!model && model.count > 0
model: delegateModel
}
@@ -16,6 +16,7 @@ Column {
property bool opened: true
property bool dragged: false
property alias statusChatListCategoryItem: statusChatListCategoryItem
property alias showActionButtons: statusChatListCategoryItem.showActionButtons
property alias addButton: statusChatListCategoryItem.addButton
property alias menuButton: statusChatListCategoryItem.menuButton
@@ -37,20 +38,20 @@ Column {
title: statusChatListCategory.name
opened: statusChatListCategory.opened
sensor.pressAndHoldInterval: 150
propagateTitleClicks: true // title click is handled as a normal click (fallthru)
showMenuButton: showActionButtons && !!statusChatListCategory.popupMenu
highlighted: statusChatListCategory.dragged
sensor.onClicked: {
onClicked: {
if (sensor.enabled) {
if (mouse.button === Qt.RightButton && showActionButtons && !!statusChatListCategory.popupMenu) {
highlighted = true;
popupMenuSlot.item.popup(mouse.x + 4, mouse.y + 6);
return
} else if (mouse.button === Qt.LeftButton) {
statusChatListCategory.opened = !statusChatListCategory.opened
}
}
}
onTitleClicked: statusChatListCategory.opened = !opened
onToggleButtonClicked: statusChatListCategory.opened = !opened
onToggleButtonClicked: statusChatListCategory.opened = !statusChatListCategory.opened
onMenuButtonClicked: {
highlighted = true
menuButton.highlighted = true
@@ -60,15 +60,7 @@ StatusListItem {
icon.name: "chevron-down"
icon.width: 18
icon.rotation: statusChatListCategoryItem.opened ? 0 : 270
onPressed: {
sensor.enabled = false;
}
onClicked: {
statusChatListCategoryItem.toggleButtonClicked(mouse);
}
onReleased: {
sensor.enabled = true;
}
onClicked: statusChatListCategoryItem.toggleButtonClicked(mouse)
}
]
}
+23 -15
View File
@@ -21,11 +21,9 @@ Rectangle {
property bool hasUnreadMessages: false
property int notificationsCount: 0
property bool muted: false
property StatusImageSettings image: StatusImageSettings {
width: 24
height: 24
}
property StatusIconSettings icon: StatusIconSettings {
property int onlineStatus: StatusChatListItem.OnlineStatus.Inactive
property StatusAssetSettings asset: StatusAssetSettings {
width: 24
height: 24
color: Theme.palette.miscColor5
@@ -53,6 +51,11 @@ Rectangle {
CommunityChat // 6
}
enum OnlineStatus {
Inactive,
Online
}
implicitWidth: 288
implicitHeight: 40
@@ -85,9 +88,17 @@ Rectangle {
anchors.left: parent.left
anchors.leftMargin: 8
anchors.verticalCenter: parent.verticalCenter
image: root.image
icon: root.icon
asset: root.asset
name: root.name
badge {
visible: type === StatusChatListItem.Type.OneToOneChat
color: onlineStatus === StatusChatListItem.OnlineStatus.Online ? Theme.palette.successColor1 : Theme.palette.baseColor1
border.width: 1
border.color: root.color
implicitHeight: 9
implicitWidth: 9
}
}
StatusIcon {
@@ -112,17 +123,14 @@ Rectangle {
icon: {
switch (root.type) {
case StatusChatListItem.Type.PublicCat:
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
break;
case StatusChatListItem.Type.PublicChat:
return Theme.palette.name === "light" ? "tiny/public-chat" : "tiny/public-chat-white"
case StatusChatListItem.Type.GroupChat:
return Theme.palette.name == "light" ? "tiny/group" : "tiny/group-white"
break;
return Theme.palette.name === "light" ? "tiny/group" : "tiny/group-white"
case StatusChatListItem.Type.CommunityChat:
return Theme.palette.name == "light" ? "tiny/channel" : "tiny/channel-white"
break;
return Theme.palette.name === "light" ? "tiny/channel" : "tiny/channel-white"
default:
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
return Theme.palette.name === "light" ? "tiny/public-chat" : "tiny/public-chat-white"
}
}
}
@@ -1,149 +0,0 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
Item {
id: statusChatToolBar
property alias menuButton: menuButton
property alias notificationButton: notificationButton
property alias membersButton: membersButton
property alias searchButton: searchButton
property int padding: 8
property int notificationCount: 0
property Component popupMenu
property var toolbarComponent
signal chatInfoButtonClicked()
signal menuButtonClicked()
signal notificationButtonClicked()
signal membersButtonClicked()
signal searchButtonClicked()
implicitWidth: 518
implicitHeight: 60
onPopupMenuChanged: {
if (!!popupMenu) {
popupMenuSlot.sourceComponent = popupMenu
}
}
RowLayout {
width: parent.width
spacing: padding / 2
Loader {
id: loader
sourceComponent: statusChatToolBar.toolbarComponent
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
Layout.topMargin: padding
Layout.leftMargin: padding
}
RowLayout {
id: actionButtons
Layout.alignment: Qt.AlignTop | Qt.AlignRight
Layout.topMargin: padding
Layout.rightMargin: padding
spacing: 8
StatusFlatRoundButton {
id: searchButton
width: 32
height: 32
icon.name: "search"
type: StatusFlatRoundButton.Type.Secondary
onClicked: statusChatToolBar.searchButtonClicked()
// initializing the tooltip
tooltip.text: qsTr("Search")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
}
StatusFlatRoundButton {
id: membersButton
width: 32
height: 32
icon.name: "group-chat"
type: StatusFlatRoundButton.Type.Secondary
onClicked: statusChatToolBar.membersButtonClicked()
// initializing the tooltip
tooltip.text: qsTr("Members")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
}
StatusFlatRoundButton {
id: menuButton
objectName: "chatToolbarMoreOptionsButton"
width: 32
height: 32
icon.name: "more"
type: StatusFlatRoundButton.Type.Secondary
visible: !!statusChatToolBar.popupMenu
// initializing the tooltip
tooltip.visible: !!tooltip.text && menuButton.hovered && !popupMenuSlot.item.opened
tooltip.text: qsTr("More")
tooltip.orientation: StatusToolTip.Orientation.Bottom
tooltip.y: parent.height + 12
property bool showMoreMenu: false
onClicked: {
menuButton.highlighted = true
let originalOpenHandler = popupMenuSlot.item.openHandler
let originalCloseHandler = popupMenuSlot.item.closeHandler
popupMenuSlot.item.openHandler = function () {
if (!!originalOpenHandler) {
originalOpenHandler()
}
}
popupMenuSlot.item.closeHandler = function () {
menuButton.highlighted = false
if (!!originalCloseHandler) {
originalCloseHandler()
}
}
popupMenuSlot.item.openHandler = originalOpenHandler
popupMenuSlot.item.popup(-popupMenuSlot.item.width + menuButton.width, menuButton.height + 4)
statusChatToolBar.menuButtonClicked()
}
Loader {
id: popupMenuSlot
active: !!statusChatToolBar.popupMenu
}
}
Rectangle {
height: 24
width: 1
color: Theme.palette.directColor7
Layout.alignment: Qt.AlignVCenter
visible: notificationButton.visible &&
(menuButton.visible || membersButton.visible || searchButton.visible)
}
StatusActivityCenterButton {
id: notificationButton
width: 32
height: width
unreadNotificationsCount: statusChatToolBar.notificationCount
onClicked: statusChatToolBar.notificationButtonClicked()
}
}
}
}
@@ -360,11 +360,11 @@ Rectangle {
height: 24
radius: 20
closeButtonVisible: false
icon.emoji: model.emoji
icon.height: 24
icon.width: icon.height
icon.color: "transparent"
icon.isLetterIdenticon: true
asset.emoji: model.emoji
asset.width: 24
asset.height: 24
asset.color: "transparent"
asset.isLetterIdenticon: true
title: model.name
titleText.font.pixelSize: 13
titleText.color: d.fontColor
@@ -9,16 +9,14 @@ Row {
property bool isContact: false
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
property StatusIconSettings mutualConnectionIcon: StatusIconSettings {
property StatusAssetSettings mutualConnectionIcon: StatusAssetSettings {
name: "tiny/tiny-contact"
color: Theme.palette.indirectColor1
width: dummyImage.width
height: dummyImage.height
background: StatusIconBackgroundSettings {
width: 10
height: 10
color: Theme.palette.primaryColor1
}
bgWidth: 10
bgHeight: 10
bgColor: 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": ""
@@ -26,17 +24,15 @@ Row {
}
}
property StatusIconSettings trustContactIcon: StatusIconSettings {
property StatusAssetSettings trustContactIcon: StatusAssetSettings {
// 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
}
bgWidth: 10
bgHeight: 10
bgColor: 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": ""
@@ -55,25 +51,25 @@ Row {
StatusRoundIcon {
visible: root.isContact
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
asset.name: root.mutualConnectionIcon.name
asset.width: root.mutualConnectionIcon.width
asset.height: root.mutualConnectionIcon.height
asset.rotation: root.mutualConnectionIcon.rotation
asset.color: root.mutualConnectionIcon.color
asset.bgColor: root.mutualConnectionIcon.bgColor
asset.bgWidth: root.mutualConnectionIcon.bgWidth
asset.bgHeight: root.mutualConnectionIcon.bgHeight
}
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
asset.name: root.trustContactIcon.name
asset.width: root.trustContactIcon.width
asset.height: root.trustContactIcon.height
asset.rotation: root.trustContactIcon.rotation
asset.color: root.trustContactIcon.color
asset.bgColor: root.trustContactIcon.bgColor
asset.bgWidth: root.trustContactIcon.bgWidth
asset.bgHeight: root.trustContactIcon.bgHeight
}
}
@@ -0,0 +1,42 @@
import QtQuick 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
StatusBaseText {
id: root
property int previousMessageIndex: -1
property double previousMessageTimestamp
property double messageTimestamp
font.pixelSize: 13
color: Theme.palette.baseColor1
horizontalAlignment: Text.AlignHCenter
text: {
if (previousMessageIndex === -1)
return "";
const currentMsgDate = new Date(messageTimestamp);
const prevMsgDate = new Date(previousMessageTimestamp);
if (!!prevMsgDate && currentMsgDate.getDay() === prevMsgDate.getDay())
return "";
const now = new Date();
if (now.getFullYear() == currentMsgDate.getFullYear() && now.getMonth() == currentMsgDate.getMonth() && now.getDate() == currentMsgDate.getDate())
return qsTr("Today");
const yesterday = new Date();
yesterday.setDate(now.getDate()-1);
if (yesterday.getFullYear() == currentMsgDate.getFullYear() && yesterday.getMonth() == currentMsgDate.getMonth() && yesterday.getDate() == currentMsgDate.getDate())
return qsTr("Yesterday");
// FIXME Qt6: replace with Intl.DateTimeFormat
const monthName = Qt.locale().standaloneMonthName(currentMsgDate.getMonth(), Locale.LongFormat)
if (now.getFullYear() > currentMsgDate.getFullYear())
return "%1 %2, %3".arg(monthName).arg(currentMsgDate.getDate()).arg(currentMsgDate.getFullYear())
return "%1, %2".arg(monthName).arg(currentMsgDate.getDate())
}
}
@@ -10,7 +10,7 @@ Rectangle {
property string subTitle: ""
property alias subTitleComponent: statusDescriptionListItemSubTitle
property string value: ""
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings asset: StatusAssetSettings {
width: 23
height: 23
}
@@ -59,7 +59,7 @@ Rectangle {
StatusFlatRoundButton {
id: statusFlatRoundButton
visible: !!statusDescriptionListItem.icon.name
visible: !!statusDescriptionListItem.asset.name
anchors.verticalCenter: statusDescriptionListItemSubTitle.verticalCenter
anchors.left: statusDescriptionListItemSubTitle.right
anchors.leftMargin: 4
@@ -67,9 +67,9 @@ Rectangle {
width: 32
height: 32
icon.name: statusDescriptionListItem.icon.name
icon.width: statusDescriptionListItem.icon.width
icon.height: statusDescriptionListItem.icon.height
icon.name: statusDescriptionListItem.asset.name
icon.width: statusDescriptionListItem.asset.width
icon.height: statusDescriptionListItem.asset.height
StatusToolTip {
id: statusToolTip
+17 -23
View File
@@ -13,24 +13,19 @@ Rectangle {
property alias button: button
property alias expandableComponent: expandableRegion.sourceComponent
property alias expandableItem: expandableRegion.item
property bool separatorVisible: true
property int type: StatusExpandableItem.Type.Primary
property bool expandable: true
property bool expanded: false
property StatusIconSettings icon: StatusIconSettings {
width: !!statusExpandableItem.icon.name.toString() ? 24 : 40
height: !!statusExpandableItem.icon.name.toString() ? 24 : 40
property StatusAssetSettings asset: StatusAssetSettings {
width: !statusExpandableItem.asset.isImage ? 24 : 40
height: !statusExpandableItem.asset.isImage ? 24 : 40
color: Theme.palette.directColor1
background: StatusIconBackgroundSettings {
width: 32
height: 32
color: Theme.palette.primaryColor2
}
}
property StatusImageSettings image: StatusImageSettings {
width: 40
height: 40
bgWidth: 32
bgHeight: 32
bgColor: Theme.palette.primaryColor2
}
enum Type {
@@ -55,7 +50,7 @@ Rectangle {
height: 1
color: Theme.palette.baseColor2
visible: (statusExpandableItem.type === StatusExpandableItem.Type.Tertiary)
visible: (statusExpandableItem.type === StatusExpandableItem.Type.Tertiary) && separatorVisible
}
@@ -63,7 +58,7 @@ Rectangle {
id: header
anchors.top: parent.top
width: parent.width
height: 64
height: statusExpandableItem.type === StatusExpandableItem.Type.Tertiary ? 40 : 64
radius: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? 8 : 0
color: statusExpandableItem.type === StatusExpandableItem.Type.Secondary && sensor.containsMouse ? Theme.palette.baseColor2 : "transparent"
@@ -73,8 +68,7 @@ Rectangle {
anchors.topMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? 12.5 : 25
anchors.left: parent.left
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? 16 : 11
image: statusExpandableItem.image
icon: statusExpandableItem.icon
asset: statusExpandableItem.asset
name: primaryText.text
active: (statusExpandableItem.type !== StatusExpandableItem.Type.Tertiary)
}
@@ -85,14 +79,14 @@ Rectangle {
(statusExpandableItem.type === StatusExpandableItem.Type.Tertiary) ? parent.top : undefined
anchors.topMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Tertiary) ? 29 : 17
anchors.left: identicon.active ? identicon.right : parent.left
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 10 : 16
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 10 : !identicon.active ? 0 : 16
anchors.verticalCenter: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? identicon.verticalCenter : undefined
width: !!additionalText.text ? (button.visible ? parent.width - icon.background.width - button.width - additionalText.contentWidth - 110 :
parent.width - icon.background.width - additionalText.contentWidth - 110) :
(button.visible ? parent.width - icon.background.width - button.width - 70 :
parent.width - icon.background.width - 70)
width: !!additionalText.text ? (button.visible ? parent.width - asset.bgWidth - button.width - additionalText.contentWidth - 110 :
parent.width - asset.bgWidth - additionalText.contentWidth - 110) :
(button.visible ? parent.width - asset.bgWidth - button.width - 70 :
parent.width - asset.bgWidth - 70)
font.weight: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? Font.Medium : Font.Normal
font.pixelSize: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 15 : 17
@@ -181,7 +175,7 @@ Rectangle {
Loader {
id: expandableRegion
anchors.top: header.bottom
anchors.topMargin: 16
anchors.topMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Tertiary) ? 24 : 16
anchors.left: parent.left
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Primary) ? 48 : 0
anchors.right: parent.right
@@ -202,7 +196,7 @@ Rectangle {
State {
name: "EXPANDED"
PropertyChanges {target: expandImage; icon: "chevron-up"}
PropertyChanges {target: statusExpandableItem; height: 82 + expandableRegion.height + 22}
PropertyChanges {target: statusExpandableItem; height: 82 + expandableRegion.height}
PropertyChanges {target: expandableRegion; visible: true}
},
State {
@@ -216,6 +216,7 @@ Item {
anchors.fill: parent
enabled: root.interactive
cursorShape: Qt.SizeAllCursor
property var lastDragPoint: null
onReleased: lastDragPoint = null
+46 -34
View File
@@ -27,12 +27,15 @@ import StatusQ.Core.Utils 0.1
defaultItemText: qsTr("Example: 10 SNT")
andOperatorText: qsTr("and")
orOperatorText: qsTr("or")
popupItem: CustomPopup {
id: customPopup
onAddItem: {
tokensSelector.addItem(itemText, itemImage, operator)
customPopup.close()
}
CustomPopup {
id: popup
}
addButton.onClicked: {
popup.x = mouse.x
popup.y = mouse.y
popup.open()
}
}
\endqml
@@ -66,10 +69,10 @@ Rectangle {
*/
property url defaultItemImageSource: ""
/*!
\qmlproperty QC.Popup StatusItemSelector::popupItem
This property holds a custom popup item to be opened near the `add` button in order to select new items.
\qmlproperty StatusRoundButton StatusItemSelector::addButton
This property holds an alias to the `add` button.
*/
property QC.Popup popupItem
readonly property alias addButton: addItemButton
/*!
\qmlproperty ListModel StatusItemSelector::itemsModel
This property holds the data that will be populated in the items selector.
@@ -90,7 +93,13 @@ Rectangle {
}
\endqml
*/
property ListModel itemsModel: ListModel { }
property var itemsModel: ListModel { }
/*!
\qmlproperty bool StatusItemSelector::useIcons
This property determines if the imageSource role from the model will be handled as
an image or an icon.
*/
property bool useIcons: false
/*!
\qmlproperty string StatusItemSelector::andOperatorText
This property holds the string text representation for an `AND` logical operator.
@@ -101,27 +110,24 @@ Rectangle {
This property holds the string text representation for an `OR` logical operator.
*/
property string orOperatorText: qsTr("or")
/*
\qmlmethod StatusItemSelector::addItem()
It is used to add new items into the selector control. The expected arguments are:
string `text`, url `imageSource` and int `operator` (None = 0, And = 1 and Or = 2)
/*!
\qmlsignal StatusItemSelector::itemClicked
This signal is emitted when the item is clicked.
*/
function addItem(text, imageSource, operator) {
itemsModel.insert(itemsModel.count, { "text": text, "imageSource": imageSource.toString(), "operator": operator })
}
signal itemClicked(var item, int index, var mouse)
QtObject {
id: d
function operatorTextFormat(operator) {
switch(operator)
{
case Utils.Operators.And:
return root.andOperatorText
case Utils.Operators.Or:
return root.orOperatorText
case Utils.Operators.None:
return ""
switch(operator) {
case Utils.Operators.And:
return root.andOperatorText
case Utils.Operators.Or:
return root.orOperatorText
case Utils.Operators.None:
return ""
}
}
}
@@ -168,9 +174,10 @@ Rectangle {
Layout.fillWidth: true
spacing: 6
StatusListItemTag {
visible: itemsModel.count === 0
visible: !itemsModel || itemsModel.count === 0
title: root.defaultItemText
image.source: root.defaultItemImageSource
asset.name: root.defaultItemImageSource
asset.isImage: true
color: Theme.palette.baseColor2
closeButtonVisible: false
titleText.color: Theme.palette.baseColor1
@@ -178,8 +185,10 @@ Rectangle {
}
Repeater {
model: itemsModel
RowLayout {
spacing: flow.spacing
StatusBaseText {
visible: model.operator !== Utils.Operators.None
Layout.alignment: Qt.AlignVCenter
@@ -200,12 +209,20 @@ Rectangle {
}
StatusListItemTag {
title: model.text
image.source: model.imageSource
asset.name: model.imageSource
asset.isImage: !root.useIcons
asset.bgColor: "transparent"
color: Theme.palette.primaryColor3
closeButtonVisible: false
titleText.color: Theme.palette.primaryColor1
titleText.font.pixelSize: 15
//onClicked: // TODO: Open remove or edit dialog
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: root.itemClicked(parent, model.index, mouse)
}
}
}
}
@@ -216,11 +233,6 @@ Rectangle {
height: width
type: StatusRoundButton.Type.Secondary
icon.name: "add"
onClicked: {
root.popupItem.x = addItemButton.x + addItemButton.width + 4 * flow.spacing
root.popupItem.y = addItemButton.y + addItemButton.height
root.popupItem.open()
}
}
}
}
+107 -58
View File
@@ -23,46 +23,42 @@ Rectangle {
property string titleTextIcon: ""
property real leftPadding: 16
property real rightPadding: 16
property bool enabled: true
property bool highlighted: false
property bool propagateTitleClicks: true
property int type: StatusListItem.Type.Primary
property list<Item> components
property var bottomModel: []
property Component bottomDelegate
property var tagsModel: []
property alias tagsModel: tagsRepeater.model
property Component tagsDelegate
property var inlineTagModel: []
property Component inlineTagDelegate
property bool loading: false
property bool loadingFailed: false
property StatusIconSettings icon: StatusIconSettings {
height: isLetterIdenticon ? 40 : 20
width: isLetterIdenticon ? 40 : 20
property StatusAssetSettings asset: StatusAssetSettings {
height: isImage ? 40 : 20
width: isImage ? 40 : 20
rotation: 0
isLetterIdenticon: false
letterSize: 21
charactersLen: 1
color: isLetterIdenticon ? background.color : type === StatusListItem.Type.Danger ?
color: isLetterIdenticon ? bgColor : type === StatusListItem.Type.Danger ?
Theme.palette.dangerColor1 : Theme.palette.primaryColor1
background: StatusIconBackgroundSettings {
width: 40
height: 40
color: {
if (sensor.containsMouse) {
return type === StatusListItem.Type.Secondary ||
type === StatusListItem.Type.Danger ? "transparent" :
Theme.palette.primaryColor3
}
return type === StatusListItem.Type.Danger ?
Theme.palette.dangerColor3 : Theme.palette.primaryColor3
bgWidth: 40
bgHeight: 40
bgColor: {
if (sensor.containsMouse) {
return type === StatusListItem.Type.Secondary ||
type === StatusListItem.Type.Danger ? "transparent" :
Theme.palette.primaryColor3
}
return type === StatusListItem.Type.Danger ?
Theme.palette.dangerColor3 : Theme.palette.primaryColor3
}
imgIsIdenticon: false
}
property StatusImageSettings image: StatusImageSettings {
width: 40
height: 40
isIdenticon: false
}
property StatusIdenticonRingSettings ringSettings: StatusIdenticonRingSettings {
initalAngleRad: 0
ringPxSize: 1.5
@@ -122,33 +118,32 @@ Rectangle {
}
MouseArea {
id: sensor
enabled: statusListItem.enabled
anchors.fill: parent
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
preventStealing: true
onClicked: {
statusListItem.clicked(statusListItem.itemId, mouse)
}
}
MouseArea {
id: sensor
anchors.fill: parent
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: Qt.NoButton
hoverEnabled: true
StatusSmartIdenticon {
id: iconOrImage
anchors.left: parent.left
anchors.leftMargin: statusListItem.leftPadding
anchors.top: parent.top
anchors.topMargin: 12
anchors.verticalCenter: parent.verticalCenter
visible: !iconOrImageLoadingOverlay.visible
image: statusListItem.image
icon: statusListItem.icon
asset: statusListItem.asset
name: statusListItem.title
active: statusListItem.icon.isLetterIdenticon ||
!!statusListItem.icon.name ||
!!statusListItem.image.source.toString() ||
!!statusListItem.icon.emoji
active: statusListItem.asset.isLetterIdenticon ||
!!statusListItem.asset.name ||
!!statusListItem.asset.emoji
badge.border.color: statusListItem.color
ringSettings: statusListItem.ringSettings
}
@@ -181,7 +176,7 @@ Rectangle {
anchors.left: iconOrImage.active ? iconOrImage.right : parent.left
anchors.right: statusListItemLabel.visible ? statusListItemLabel.left : statusListItemComponentsSlot.left
anchors.leftMargin: iconOrImage.active ? 16 : statusListItem.leftPadding
anchors.rightMargin: statusListItem.rightPadding
anchors.rightMargin: Math.max(statusListItem.rightPadding, titleIconsRow.requiredWidth)
anchors.verticalCenter: bottomModel.length === 0 ? parent.verticalCenter : undefined
height: childrenRect.height
@@ -277,30 +272,76 @@ Rectangle {
Loader {
id: titleIconsRow
readonly property int requiredWidth: active ? width + anchors.leftMargin * 2 : 0
anchors.left: !statusListItem.titleAsideText ? statusListItemTitle.right : statusListItemTitleAsideText.right
anchors.verticalCenter: statusListItemTitle.verticalCenter
anchors.leftMargin: 4
}
StatusBaseText {
id: statusListItemSubTitle
objectName: "statusListItemSubTitle"
RowLayout {
id: statusListItemSubtitleTagsRow
anchors.top: statusListItemTitle.bottom
width: parent.width
text: statusListItem.subTitle
font.pixelSize: 15
color: statusListItem.loadingFailed ? Theme.palette.dangerColor1
: !statusListItem.enabled || !statusListItem.tertiaryTitle
? Theme.palette.baseColor1
: Theme.palette.directColor1
height: visible ? contentHeight : 0
visible: !!statusListItem.subTitle
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
spacing: 4
StatusBaseText {
id: statusListItemSubTitle
objectName: "statusListItemSubTitle"
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: inlineTagModelRepeater.count > 0 ? contentWidth : parent.width
text: statusListItem.subTitle
font.pixelSize: 15
color: statusListItem.loadingFailed ? Theme.palette.dangerColor1
: !statusListItem.enabled || !statusListItem.tertiaryTitle
? Theme.palette.baseColor1
: Theme.palette.directColor1
visible: !!statusListItem.subTitle
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
}
StatusBaseText {
id: dot
Layout.alignment: Qt.AlignVCenter
Layout.topMargin: -48
text: "."
font.pixelSize: 40
color: Theme.palette.baseColor1
lineHeightMode: Text.FixedHeight
lineHeight: 24
visible: inlineTagModelRepeater.count > 0
}
StatusScrollView {
id: inlineTagModelRepeaterRow
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
Layout.preferredHeight: row.height
contentHeight: row.height
contentWidth: row.width
padding: 0
clip: true
interactive: false
Row {
id: row
spacing: 4
Repeater {
id: inlineTagModelRepeater
model: inlineTagModel
delegate: inlineTagDelegate
}
}
}
}
StatusBaseText {
id: statusListItemTertiaryTitle
anchors.top: statusListItemSubTitle.bottom
anchors.top: statusListItemSubtitleTagsRow.bottom
width: parent.width
height: visible ? contentHeight : 0
text: statusListItem.tertiaryTitle
@@ -317,16 +358,24 @@ Rectangle {
implicitHeight: visible ? 22 : 0
}
Row {
id: statusListItemTagsSlotInline
ScrollView {
visible: tagsRepeater.count > 0
anchors.top: statusListItemTertiaryTitle.bottom
anchors.topMargin: visible? 8 : 0
width: parent.width
spacing: 10
height: visible? contentHeight + 12 : contentHeight
clip: true
Repeater {
model: tagsModel
delegate: tagsDelegate
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
Row {
id: statusListItemTagsSlotInline
spacing: 10
Repeater {
id: tagsRepeater
delegate: tagsDelegate
}
}
}
}
@@ -351,7 +400,7 @@ Rectangle {
id: statusListItemLabel
anchors.verticalCenter: bottomModel.length === 0 ? parent.verticalCenter : undefined
anchors.top: bottomModel.length === 0 ? undefined: parent.top
anchors.topMargin: bottomModel.length === 0 ? undefined : 16
anchors.topMargin: bottomModel.length === 0 ? 0 : 16
anchors.right: statusListItemComponentsSlot.left
anchors.rightMargin: statusListItemComponentsSlot.width > 0 ? 10 : 0
+13 -18
View File
@@ -13,17 +13,12 @@ Control {
property string primaryText: ""
property string secondaryText: ""
property StatusImageSettings image: StatusImageSettings {
height: 16
width: 16
isIdenticon: false
}
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings asset: StatusAssetSettings {
height: 16
width: 16
isLetterIdenticon: false
background: StatusIconBackgroundSettings {}
color: "transparent"
imgIsIdenticon: false
}
background: Rectangle {
@@ -43,22 +38,22 @@ Control {
anchors.horizontalCenterOffset: -spacing
spacing: 2
StatusRoundedImage {
implicitWidth: root.image.width
implicitHeight: root.image.height
visible: !root.icon.isLetterIdenticon
image.source: root.image.source
implicitWidth: root.asset.width
implicitHeight: root.asset.height
visible: !root.asset.isLetterIdenticon
image.source: root.asset.name
border.color: Theme.palette.baseColor1
border.width: root.image.isIdenticon ? 1 : 0
border.width: root.asset.imgIsIdenticon ? 1 : 0
}
StatusLetterIdenticon {
implicitWidth: root.icon.width
implicitHeight: root.icon.width
implicitWidth: root.asset.width
implicitHeight: root.asset.width
letterSize: 11
visible: root.icon.isLetterIdenticon
color: root.icon.color
visible: root.asset.isLetterIdenticon
color: root.asset.color
name: root.primaryText
emoji: root.icon.emoji
emojiSize: root.icon.emojiSize
emoji: root.asset.emoji
emojiSize: root.asset.emojiSize
}
StatusBaseText {
font.weight: Font.Medium
+12 -23
View File
@@ -6,8 +6,8 @@ import StatusQ.Core.Theme 0.1
Rectangle {
id: root
width: layout.width + layout.anchors.margins
height: 30
implicitWidth: layout.width + layout.anchors.margins
implicitHeight: 30
color: Theme.palette.primaryColor3
radius: 15
@@ -15,26 +15,19 @@ Rectangle {
property string title: ""
property bool closeButtonVisible: true
signal clicked()
signal clicked(var mouse)
property StatusImageSettings image: StatusImageSettings {
width: 20
height: 20
isIdenticon: false
}
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings asset: StatusAssetSettings {
height: 20
width: 20
rotation: 0
isLetterIdenticon: false
letterSize: 10
color: Theme.palette.primaryColor1
background: StatusIconBackgroundSettings {
width: 15
height: 15
color: Theme.palette.primaryColor3
}
bgWidth: 15
bgHeight: 15
bgColor: Theme.palette.primaryColor3
imgIsIdenticon: false
}
RowLayout {
@@ -45,12 +38,10 @@ Rectangle {
StatusSmartIdenticon {
id: iconOrImage
Layout.leftMargin: 4
image: root.image
icon: root.icon
asset: root.asset
name: root.title
active: root.icon.isLetterIdenticon ||
!!root.icon.name ||
!!root.image.source.toString()
active: root.asset.isLetterIdenticon ||
!!root.asset.name
}
StatusBaseText {
@@ -70,9 +61,7 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.clicked()
}
onClicked: root.clicked(mouse)
}
}
}
+4 -4
View File
@@ -294,7 +294,7 @@ Item {
bottomPadding: 0
placeholderText: root.placeholderSearchText
text: root.searchText
input.icon.name: "search"
input.asset.name: "search"
onTextChanged: root.searchText = text
}
@@ -303,11 +303,11 @@ Item {
width: content.itemWidth
height: content.itemHeight
color: mouseArea.containsMouse ? Theme.palette.baseColor4 : "transparent"
image: StatusImageSettings {
source: root.proxy.imageSource(model) ? root.proxy.imageSource(model) : ""
asset: StatusAssetSettings {
name: root.proxy.imageSource(model) ? root.proxy.imageSource(model) : ""
width: 15
height: 15
isIdenticon: false
imgIsIdenticon: false
}
name: root.proxy.name(model)
shortName: root.proxy.shortName(model)
@@ -120,7 +120,6 @@ StatusListItem {
}
subTitle: d.composeSubtitile()
statusListItemSubTitle.font.pixelSize: 10
icon.isLetterIdenticon: !root.image.source.toString()
statusListItemIcon.badge.visible: true
statusListItemIcon.badge.color: root.status === 1 ? Theme.palette.successColor1 : Theme.palette.baseColor1 // FIXME
color: sensor.containsMouse ? Theme.palette.baseColor2 : Theme.palette.baseColor4
@@ -129,10 +128,8 @@ StatusListItem {
implicitWidth: 256
implicitHeight: Math.max(56, statusListItemTitleArea.height + leftPadding)
leftPadding: 8
image.width: 32
image.height: 32
icon.width: 32
icon.height: 32
asset.width: 32
asset.height: 32
statusListItemIcon.anchors.verticalCenter: sensor.verticalCenter
statusListItemIcon.anchors.top: undefined
statusListItemIcon.badge.border.width: 2
+336 -85
View File
@@ -1,14 +1,16 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import QtQuick.Controls 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Controls 0.1
import "./private/statusMessage"
Rectangle {
id: statusMessage
id: root
enum ContentType {
Unknown = 0,
@@ -21,12 +23,12 @@ Rectangle {
Invitation = 7
}
property alias messageHeader: messageHeader
property alias quickActions:quickActionsPanel.quickActions
property alias quickActions: quickActionsPanel.items
property alias statusChatInput: editComponent.inputComponent
property alias linksComponent: linksLoader.sourceComponent
property alias footerComponent: footer.sourceComponent
property alias timestamp: messageHeader.timestamp
property alias transcationComponent: transactionBubbleLoader.sourceComponent
property alias invitationComponent: invitationBubbleLoader.sourceComponent
property alias mouseArea: mouseArea
property string resendText: ""
property string cancelButtonText: ""
@@ -35,155 +37,397 @@ Rectangle {
property string errorLoadingImageText: ""
property string audioMessageInfoText: ""
property string pinnedMsgInfoText: ""
property string messageAttachments: ""
property var reactionIcons: [
Emoji.iconSource("❤"),
Emoji.iconSource("👍"),
Emoji.iconSource("👎"),
Emoji.iconSource("🤣"),
Emoji.iconSource("😥"),
Emoji.iconSource("😠")
]
property string messageId: ""
property bool isAppWindowActive: false
property bool editMode: false
property bool isAReply: false
property bool isEdited: false
property bool isChatBlocked: false
property bool hasMention: false
property bool isPinned: false
property string pinnedBy: ""
property bool hasExpired: false
property double timestamp: 0
property var reactionsModel: []
readonly property bool dateGroupVisible: dateGroupLabel.visible
property bool showHeader: true
property bool isActiveMessage: false
property bool disableHover: false
property bool hideQuickActions: false
property color overrideBackgroundColor: "transparent"
property bool overrideBackground: false
property bool profileClickable: true
property bool hideMessage: false
property alias previousMessageIndex: dateGroupLabel.previousMessageIndex
property alias previousMessageTimestamp: dateGroupLabel.previousMessageTimestamp
property StatusMessageDetails messageDetails: StatusMessageDetails {}
property StatusMessageDetails replyDetails: StatusMessageDetails {}
signal profilePictureClicked()
signal senderNameClicked()
signal editCompleted(var newMsgText)
signal replyProfileClicked()
signal stickerLoaded()
signal imageClicked(var imageSource)
property string timestampString: Qt.formatTime(new Date(timestamp), "hh:mm");
property string timestampTooltipString: Qt.formatTime(new Date(timestamp), "dddd, MMMM d, yyyy hh:mm:ss t");
signal clicked(var sender, var mouse)
signal profilePictureClicked(var sender, var mouse)
signal senderNameClicked(var sender, var mouse)
signal replyProfileClicked(var sender, var mouse)
signal addReactionClicked(var sender, var mouse)
signal toggleReactionClicked(int emojiId)
signal imageClicked(var image, var mouse, var imageSource)
signal stickerClicked()
signal resendClicked()
height: childrenRect.height
color: hoverHandler.hovered ? (messageDetails.hasMention ? Theme.palette.mentionColor3 : messageDetails.isPinned ? Theme.palette.pinColor2 : Theme.palette.baseColor2) : messageDetails.hasMention ? Theme.palette.mentionColor4 : messageDetails.isPinned ? Theme.palette.pinColor3 : "transparent"
signal editCompleted(var newMsgText)
signal editCancelled()
signal stickerLoaded()
signal linkActivated(string link)
signal hoverChanged(string messageId, bool hovered)
signal activeChanged(string messageId, bool active)
function startMessageFoundAnimation() {
messageFoundAnimation.start();
}
onMessageAttachmentsChanged: {
root.prepareAttachmentsModel()
}
function prepareAttachmentsModel() {
attachmentsModel.clear()
if (!root.messageAttachments) {
return
}
root.messageAttachments.split(" ").forEach(source => {
attachmentsModel.append({source})
})
}
implicitWidth: messageLayout.implicitWidth
+ messageLayout.anchors.leftMargin
+ messageLayout.anchors.rightMargin
implicitHeight: messageLayout.implicitHeight
+ messageLayout.anchors.topMargin
+ messageLayout.anchors.bottomMargin
color: {
if (root.overrideBackground)
return root.overrideBackgroundColor;
if (root.editMode)
return Theme.palette.baseColor2;
if (hoverHandler.hovered || root.isActiveMessage) {
if (root.hasMention)
return Theme.palette.mentionColor3;
if (root.isPinned)
return Theme.palette.pinColor2;
return Theme.palette.baseColor2;
}
if (root.hasMention)
return Theme.palette.mentionColor4;
if (root.isPinned)
return Theme.palette.pinColor3;
return "transparent";
}
Rectangle {
anchors {
top: parent.top
bottom: parent.bottom
left: parent.left
}
width: 2
visible: root.isPinned
color: Theme.palette.pinColor1
}
Rectangle {
anchors {
top: parent.top
bottom: parent.bottom
left: parent.left
}
width: 2
visible: root.hasMention
color: Theme.palette.mentionColor1
}
SequentialAnimation {
id: messageFoundAnimation
PauseAnimation {
duration: 600
}
NumberAnimation {
target: highlightRect
property: "opacity"
to: 1.0
duration: 1500
}
PauseAnimation {
duration: 1000
}
NumberAnimation {
target: highlightRect
property: "opacity"
to: 0.0
duration: 1500
}
}
Rectangle {
id: highlightRect
anchors.fill: parent
opacity: 0
visible: opacity > 0.001
color: Theme.palette.baseColor2
}
MouseArea {
id: mouseArea
anchors.fill: parent
}
HoverHandler {
id: hoverHandler
enabled: !root.isActiveMessage && !root.disableHover
}
ColumnLayout {
id: messageLayout
width: parent.width
StatusMessageReply {
anchors.fill: parent
anchors.topMargin: 8
anchors.bottomMargin: 8
StatusDateGroupLabel {
id: dateGroupLabel
Layout.fillWidth: true
visible: isAReply
replyDetails: statusMessage.replyDetails
onReplyProfileClicked: statusMessage.replyProfileClicked()
audioMessageInfoText: statusMessage.audioMessageInfoText
Layout.topMargin: 20
messageTimestamp: root.timestamp
visible: text !== ""
}
RowLayout {
spacing: 8
Loader {
Layout.fillWidth: true
StatusSmartIdenticon {
id: profileImage
active: isAReply
visible: active
sourceComponent: StatusMessageReply {
replyDetails: root.replyDetails
profileClickable: root.profileClickable
onReplyProfileClicked: root.replyProfileClicked(sender, mouse)
audioMessageInfoText: root.audioMessageInfoText
}
}
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
spacing: 8
Item {
implicitWidth: root.messageDetails.sender.profileImage.assetSettings.width
implicitHeight: profileImage.visible ? profileImage.height : 0
Layout.alignment: Qt.AlignTop
Layout.topMargin: 10
Layout.leftMargin: 16
image: messageDetails.profileImage
name: messageHeader.displayName
MouseArea {
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
onClicked: statusMessage.profilePictureClicked()
StatusSmartIdenticon {
id: profileImage
active: root.showHeader
visible: active
name: root.messageDetails.sender.displayName
asset: root.messageDetails.sender.profileImage.assetSettings
ringSettings: root.messageDetails.sender.profileImage.ringSettings
MouseArea {
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
enabled: root.profileClickable
onClicked: root.profilePictureClicked(this, mouse)
}
}
}
Column {
ColumnLayout {
spacing: 4
Layout.alignment: Qt.AlignTop
Layout.topMargin: 10
Layout.fillWidth: true
StatusPinMessageDetails {
visible: messageDetails.isPinned && !editMode
pinnedMsgInfoText: statusMessage.pinnedMsgInfoText
pinnedBy: messageDetails.pinnedBy
Loader {
active: root.isPinned && !editMode
visible: active
sourceComponent: StatusPinMessageDetails {
pinnedMsgInfoText: root.pinnedMsgInfoText
pinnedBy: root.pinnedBy
}
}
StatusMessageHeader {
id: messageHeader
width: parent.width
displayName: messageDetails.displayName
secondaryName: messageDetails.secondaryName
tertiaryDetail: messageDetails.chatID
isContact: messageDetails.isContact
trustIndicator: messageDetails.trustIndicator
resendText: statusMessage.resendText
showResendButton: messageDetails.hasExpired && messageDetails.amISender
onClicked: statusMessage.senderNameClicked()
onResendClicked: statusMessage.resendClicked()
visible: !editMode
Layout.fillWidth: true
sender: root.messageDetails.sender
amISender: root.messageDetails.amISender
messageOriginInfo: root.messageDetails.messageOriginInfo
resendText: root.resendText
showResendButton: root.hasExpired && root.messageDetails.amISender
onClicked: root.senderNameClicked(sender, mouse)
onResendClicked: root.resendClicked()
visible: root.showHeader && !editMode
timestamp.text: root.timestampString
timestamp.tooltip.text: root.timestampTooltipString
displayNameClickable: root.profileClickable
}
Loader {
active: !editMode && !!messageDetails.messageText
width: parent.width
Layout.fillWidth: true
active: !root.editMode && !!root.messageDetails.messageText && !root.hideMessage
visible: active
sourceComponent: StatusTextMessage {
width: parent.width
textField.text: messageDetails.messageText
objectName: "StatusMessage_textMessage"
textField.text: {
if (root.messageDetails.contentType === StatusMessage.ContentType.Sticker)
return "";
const formattedMessage = Utils.linkifyAndXSS(root.messageDetails.messageText);
if (root.messageDetails.contentType === StatusMessage.ContentType.Emoji)
return Emoji.parse(formattedMessage, Emoji.size.middle, Emoji.format.png);
if (root.isEdited) {
const index = formattedMessage.endsWith("code>") ? formattedMessage.length : formattedMessage.length - 4;
const editedMessage = formattedMessage.slice(0, index)
+ ` <span class="isEdited">` + qsTr("(edited)") + `</span>`
+ formattedMessage.slice(index);
return Utils.getMessageWithStyle(Emoji.parse(editedMessage), textField.hoveredLink)
}
return Utils.getMessageWithStyle(Emoji.parse(formattedMessage), textField.hoveredLink)
}
onLinkActivated: {
root.linkActivated(link);
}
}
}
Loader {
active: messageDetails.contentType === StatusMessage.ContentType.Image && !editMode
active: root.messageDetails.contentType === StatusMessage.ContentType.Image && !editMode
visible: active
sourceComponent: StatusImageMessage {
source: messageDetails.contentType === StatusMessage.ContentType.Image ? messageDetails.messageContent : ""
onClicked: statusMessage.imageClicked()
shapeType: messageDetails.amISender ? StatusImageMessage.ShapeType.RIGHT_ROUNDED : StatusImageMessage.ShapeType.LEFT_ROUNDED
source: root.messageDetails.contentType === StatusMessage.ContentType.Image ? root.messageDetails.messageContent : ""
onClicked: root.imageClicked(image, mouse, imageSource)
shapeType: root.messageDetails.amISender ? StatusImageMessage.ShapeType.RIGHT_ROUNDED : StatusImageMessage.ShapeType.LEFT_ROUNDED
}
}
StatusSticker {
visible: messageDetails.contentType === StatusMessage.ContentType.Sticker && !editMode
image.source: messageDetails.messageContent
onLoaded: statusMessage.stickerLoaded()
Loader {
active: !!root.messageAttachments && !editMode
visible: active
sourceComponent: Column {
spacing: 4
Layout.fillWidth: true
Repeater {
model: attachmentsModel
delegate: StatusImageMessage {
source: model.source
onClicked: root.imageClicked(image, mouse, imageSource)
shapeType: root.messageDetails.amISender ? StatusImageMessage.ShapeType.RIGHT_ROUNDED : StatusImageMessage.ShapeType.LEFT_ROUNDED
}
}
}
}
Loader {
active: root.messageDetails.contentType === StatusMessage.ContentType.Sticker && !editMode
visible: active
sourceComponent: StatusSticker {
asset.isImage: true
asset.name: root.messageDetails.messageContent
onLoaded: root.stickerLoaded()
onClicked: {
root.stickerClicked()
}
}
}
Loader {
active: messageDetails.contentType === StatusMessage.ContentType.Audio && !editMode
active: root.messageDetails.contentType === StatusMessage.ContentType.Audio && !editMode
visible: active
sourceComponent: StatusAudioMessage {
audioSource: messageDetails.messageContent
audioSource: root.messageDetails.messageContent
hovered: hoverHandler.hovered
audioMessageInfoText: statusMessage.audioMessageInfoText
audioMessageInfoText: root.audioMessageInfoText
}
}
Loader {
id: linksLoader
active: !!linksLoader.sourceComponent
active: !root.editMode
visible: active
}
Loader {
id: transactionBubbleLoader
active: messageDetails.contentType === StatusMessage.ContentType.Transaction && !editMode
active: root.messageDetails.contentType === StatusMessage.ContentType.Transaction && !editMode
visible: active
}
Loader {
id: invitationBubbleLoader
active: messageDetails.contentType === StatusMessage.ContentType.Invitation && !editMode
active: root.messageDetails.contentType === StatusMessage.ContentType.Invitation && !editMode
visible: active
}
StatusEditMessage {
id: editComponent
width: parent.width
msgText: messageDetails.messageText
visible: editMode
saveButtonText: statusMessage.saveButtonText
cancelButtonText: statusMessage.cancelButtonText
onCancelEditClicked: editMode = false
onEditCompleted: {
editMode = false
statusMessage.editCompleted(newMsgText)
}
Layout.fillWidth: true
Layout.rightMargin: 16
active: root.editMode
visible: active
msgText: root.messageDetails.messageText
saveButtonText: root.saveButtonText
cancelButtonText: root.cancelButtonText
onEditCancelled: root.editCancelled()
onEditCompleted: root.editCompleted(newMsgText)
}
StatusBaseText {
id: retryLbl
color: Theme.palette.dangerColor1
text: statusMessage.resendText
text: root.resendText
font.pixelSize: 12
visible: messageDetails.hasExpired && messageDetails.amISender && !messageDetails.timestamp && !editMode
visible: root.hasExpired && root.messageDetails.amISender && !root.timestamp && !editMode
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: statusMessage.resendClicked()
onClicked: root.resendClicked()
}
}
Loader {
id: footer
active: sourceComponent && !editMode
active: root.reactionsModel.count > 0
visible: active
sourceComponent: StatusMessageEmojiReactions {
id: emojiReactionsPanel
emojiReactionsModel: root.reactionsModel
store: root.messageStore
icons: root.reactionIcons
onHoverChanged: {
root.hoverChanged(messageId, hovered)
}
isCurrentUser: root.messageDetails.amISender
onAddEmojiClicked: root.addReactionClicked(sender, mouse)
onToggleReaction: root.toggleReactionClicked(emojiID)
}
}
}
}
@@ -195,6 +439,13 @@ Rectangle {
anchors.rightMargin: 20
anchors.top: parent.top
anchors.topMargin: -8
visible: hoverHandler.hovered && !editMode
visible: hoverHandler.hovered && !root.hideQuickActions
}
ListModel {
id: attachmentsModel
Component.onCompleted: {
root.prepareAttachmentsModel()
}
}
}
@@ -6,24 +6,10 @@ QtObject {
id: msgDetails
property bool amISender: false
property string displayName: ""
property string secondaryName: ""
property string chatID: ""
property StatusImageSettings profileImage: StatusImageSettings {
width: 40
height: 40
}
property StatusMessageSenderDetails sender: StatusMessageSenderDetails { }
property bool isEdited: false
property string messageText: ""
property int contentType: 0
property string messageText: ""
property string messageContent: ""
property bool isContact: 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 messageOriginInfo: ""
}
@@ -0,0 +1,21 @@
import QtQuick 2.0
import StatusQ.Core 0.1
QtObject {
id: root
property string id: ""
property string displayName: ""
property string secondaryName: ""
property bool isEnsVerified: false
property bool isContact: false
property int trustIndicator: StatusContactVerificationIcons.TrustedType.None
property StatusProfileImageSettings profileImage: StatusProfileImageSettings {
pubkey: root.id
showRing: !root.isEnsVerified
width: 40
height: 40
}
}
@@ -12,9 +12,9 @@ StatusListItem {
implicitWidth: 286
implicitHeight: 48
icon.background.width: 20
icon.background.height: 20
icon.background.color: "transparent"
asset.bgWidth: 20
asset.bgHeight: 20
asset.bgColor: "transparent"
statusListItemIcon.anchors.topMargin: 14
+13 -15
View File
@@ -5,33 +5,31 @@ import StatusQ.Core.Theme 0.1
Rectangle {
id: statusRoundedIcon
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings asset: StatusAssetSettings {
width: 24
height: 24
rotation: 0
color: Theme.palette.primaryColor1
background: StatusIconBackgroundSettings {
width: 40
height: 40
color: Theme.palette.primaryColor3
}
bgWidth: 40
bgHeight: 40
bgColor: Theme.palette.primaryColor3
}
color: icon.background.color
implicitWidth: icon.background.width
implicitHeight: icon.background.height
radius: icon.background.width / 2
color: asset.bgColor
implicitWidth: asset.bgWidth
implicitHeight: asset.bgHeight
radius: asset.bgWidth / 2
StatusIcon {
id: statusIcon
anchors.centerIn: parent
width: statusRoundedIcon.icon.width
height: statusRoundedIcon.icon.height
width: statusRoundedIcon.asset.width
height: statusRoundedIcon.asset.height
color: statusRoundedIcon.icon.color
icon: statusRoundedIcon.icon.name
rotation: statusRoundedIcon.icon.rotation
color: statusRoundedIcon.asset.color
icon: statusRoundedIcon.asset.name
rotation: statusRoundedIcon.asset.rotation
}
}
+37 -40
View File
@@ -4,7 +4,7 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
Loader {
id: statusSmartIdenticon
id: root
property string name: ""
property int dZ: 100
@@ -12,51 +12,46 @@ Loader {
// Badge color properties must be set if badgeItem.visible = true
property alias badge: statusBadge
property StatusIconSettings icon: StatusIconSettings {
width: 40
height: 40
}
property StatusImageSettings image: StatusImageSettings {
property StatusAssetSettings asset: StatusAssetSettings {
width: 40
height: 40
}
property StatusIdenticonRingSettings ringSettings: StatusIdenticonRingSettings {
initalAngleRad: 0
ringPxSize: Math.max(1.5, statusSmartIdenticon.image.width / 24.0)
ringPxSize: Math.max(1.5, root.asset.width/ 24.0)
distinctiveColors: Theme.palette.identiconRingColors
}
sourceComponent: statusSmartIdenticon.icon.isLetterIdenticon ? letterIdenticon :
!!statusSmartIdenticon.image.source.toString() ? roundedImage :
!!statusSmartIdenticon.icon.name.toString() ? roundedIcon : letterIdenticon
sourceComponent: (root.asset.isLetterIdenticon || root.asset.name === "") ? letterIdenticon :
!root.asset.isImage ? roundedIcon : roundedImage
Component {
id: roundedImage
Item {
width: statusSmartIdenticon.image.width
height: statusSmartIdenticon.image.height
width: root.asset.width
height: root.asset.height
StatusRoundedImage {
id: statusRoundImage
width: parent.width
height: parent.height
image.source: statusSmartIdenticon.image.source
image.source: root.asset.name
showLoadingIndicator: true
border.width: statusSmartIdenticon.image.isIdenticon ? 1 : 0
border.width: root.asset.imgIsIdenticon ? 1 : 0
border.color: Theme.palette.directColor7
color: statusSmartIdenticon.image.isIdenticon ?
color: root.asset.imgIsIdenticon ?
Theme.palette.statusRoundedImage.backgroundColor :
"transparent"
}
Loader {
anchors.centerIn: parent
active: statusRoundImage.image.status === Image.Error
active: root.asset.imgStatus === Image.Error ||
statusRoundImage.image.status === Image.Error
sourceComponent: letterIdenticon
onLoaded: {
item.color = Theme.palette.miscColor5
item.width = statusSmartIdenticon.image.width
item.height = statusSmartIdenticon.image.height
item.width = root.asset.width
item.height = root.asset.height
}
}
}
@@ -65,14 +60,14 @@ Loader {
Component {
id: roundedIcon
StatusRoundIcon {
icon.background.width: statusSmartIdenticon.icon.background.width
icon.background.height: statusSmartIdenticon.icon.background.height
icon.background.color: statusSmartIdenticon.icon.background.color
icon.width: statusSmartIdenticon.icon.width
icon.height: statusSmartIdenticon.icon.height
icon.name: statusSmartIdenticon.icon.name
icon.rotation: statusSmartIdenticon.icon.rotation
icon.color: statusSmartIdenticon.icon.color
asset.bgWidth: root.asset.bgWidth
asset.bgHeight: root.asset.bgHeight
asset.bgColor: root.asset.bgColor
asset.width: root.asset.width
asset.height: root.asset.height
asset.name: root.asset.name
asset.rotation: root.asset.rotation
asset.color: root.asset.color
}
}
@@ -80,33 +75,35 @@ Loader {
id: letterIdenticon
StatusLetterIdenticon {
objectName: "statusSmartIdenticonLetter"
width: statusSmartIdenticon.icon.width
height: statusSmartIdenticon.icon.height
color: statusSmartIdenticon.icon.color
name: statusSmartIdenticon.name
emoji: statusSmartIdenticon.icon.emoji
emojiSize: statusSmartIdenticon.icon.emojiSize
letterSize: statusSmartIdenticon.icon.letterSize
charactersLen: statusSmartIdenticon.icon.charactersLen
width: root.asset.width
height: root.asset.height
color: root.asset.color
name: root.name
emoji: root.asset.emoji
emojiSize: root.asset.emojiSize
letterSize: root.asset.letterSize
charactersLen: root.asset.charactersLen
}
}
// Next components are painted above main sourceComponent
StatusIdenticonRing {
settings: statusSmartIdenticon.ringSettings
settings: root.ringSettings
anchors.fill: parent
z: statusSmartIdenticon.dZ/2
z: root.dZ/2
}
// State component
StatusBadge {
id: statusBadge
visible: false
anchors.bottom: statusSmartIdenticon.bottom
anchors.right: statusSmartIdenticon.right
anchors.bottom: root.bottom
anchors.right: root.right
anchors.rightMargin: -border.width
anchors.bottomMargin: -border.width
border.width: 3
implicitHeight: 15
implicitWidth: 15
z: statusSmartIdenticon.dZ
z: root.dZ
}
}
+10 -5
View File
@@ -180,6 +180,7 @@ Item {
"isContact": entry.isContact,
"ringSpecModel": entry.ringSpecModel,
"icon": entry.icon,
"isImage": entry.isImage,
"onlineStatus": entry.onlineStatus,
"tagIcon": entry.tagIcon ? entry.tagIcon : "",
"isReadonly": !!entry.isReadonly});
@@ -305,8 +306,11 @@ Item {
if ((event.key === Qt.Key_Backspace || event.key === Qt.Key_Escape)
&& getText(cursorPosition, (cursorPosition-1)) === ""
&& (namesList.count-1) >= 0) {
removeMember(namesModel.get(namesList.count-1).pubKey);
namesModel.remove((namesList.count-1), 1);
const item = namesModel.get(namesList.count-1)
if (!item.isReadonly) {
removeMember(item.pubKey);
namesModel.remove((namesList.count-1), 1);
}
}
if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && (sortedList.count > 0)) {
root.insertTag(sortedList.get(userListView.currentIndex).name,
@@ -412,9 +416,10 @@ Item {
isVerified: model.isVerified
isUntrustworthy: model.isUntrustworthy
isContact: model.isContact
image.source: model.icon
image.isIdenticon: false
icon.color: Theme.palette.userCustomizationColors[root.colorIdForPubkeyGetter(model.pubKey)]
asset.name: model.icon
asset.color: Theme.palette.userCustomizationColors[root.colorIdForPubkeyGetter(model.pubKey)]
asset.isImage: (asset.name !== "")
asset.isLetterIdenticon: (asset.name === "")
status: model.onlineStatus
statusListItemIcon.badge.border.color: sensor.containsMouse ? Theme.palette.baseColor2 : Theme.palette.baseColor4
ringSettings.ringSpecModel: root.ringSpecModelGetter(model.pubKey)
@@ -75,10 +75,10 @@ Control {
property int duration: 0
/*!
\qmlproperty StatusIconSettings StatusToastMessage::icon
\qmlproperty StatusAssetSettings StatusToastMessage::icon
This property holds a set of settings for the icon of the ToastMessage.
*/
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings icon: StatusAssetSettings {
width: 23
height: 23
}
+58
View File
@@ -0,0 +1,58 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
ToolBar {
id: root
property string backButtonName: ""
property int notificationCount: 0
property Item headerContent
property alias notificationButton: notificationButton
signal backButtonClicked()
signal notificationButtonClicked()
implicitWidth: visible ? 518 : 0
implicitHeight: visible ? 60 : 0
padding: 8
background: null
RowLayout {
anchors.fill: parent
spacing: 0
StatusFlatButton {
icon.name: "arrow-left"
icon.width: 20
icon.height: 20
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.leftMargin: 12
visible: !!root.backButtonName
text: root.backButtonName
size: StatusBaseButton.Size.Large
onClicked: { root.backButtonClicked(); }
}
Control {
id: headerContentItem
Layout.fillWidth: !!headerContent
Layout.fillHeight: !!headerContent
background: null
contentItem: (!!headerContent) ? headerContent : null
}
Item {
Layout.fillWidth: !headerContent
}
StatusActivityCenterButton {
id: notificationButton
unreadNotificationsCount: root.notificationCount
onClicked: root.notificationButtonClicked()
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,139 @@
/*!
* Elypson's Chart.qml adaptor to Chart.js
* (c) 2020 ChartJs2QML contributors (starting with Elypson, Michael A. Voelkel, https://github.com/Elypson)
* Released under the MIT License
*/
import QtQuick 2.13
import "Chart.js" as Chart
Canvas {
id: root
property var jsChart: undefined
property string chartType
property var chartData
property var chartOptions
property double chartAnimationProgress: 0.1
property var animationEasingType: Easing.InOutExpo
property double animationDuration: 500
property var memorizedContext
property var memorizedData
property var memorizedOptions
property alias animationRunning: chartAnimator.running
signal animationFinished()
function animateToNewData()
{
chartAnimationProgress = 0.1;
jsChart.update();
chartAnimator.restart();
}
MouseArea {
id: event
anchors.fill: root
hoverEnabled: true
enabled: true
property var handler: undefined
property QtObject mouseEvent: QtObject {
property int left: 0
property int top: 0
property int x: 0
property int y: 0
property int clientX: 0
property int clientY: 0
property string type: ""
property var target
}
function submitEvent(mouse, type) {
mouseEvent.type = type
mouseEvent.clientX = mouse ? mouse.x : 0;
mouseEvent.clientY = mouse ? mouse.y : 0;
mouseEvent.x = mouse ? mouse.x : 0;
mouseEvent.y = mouse ? mouse.y : 0;
mouseEvent.left = 0;
mouseEvent.top = 0;
mouseEvent.target = root;
if(handler) {
handler(mouseEvent);
}
root.requestPaint();
}
onClicked: {
submitEvent(mouse, "click");
}
onPositionChanged: {
submitEvent(mouse, "mousemove");
}
onExited: {
submitEvent(undefined, "mouseout");
}
onEntered: {
submitEvent(undefined, "mouseenter");
}
onPressed: {
submitEvent(mouse, "mousedown");
}
onReleased: {
submitEvent(mouse, "mouseup");
}
}
PropertyAnimation {
id: chartAnimator
target: root
property: "chartAnimationProgress"
alwaysRunToEnd: true
to: 1
duration: root.animationDuration
easing.type: root.animationEasingType
onFinished: {
root.animationFinished();
}
}
onChartAnimationProgressChanged: {
root.requestPaint();
}
onPaint: {
if(root.getContext('2d') != null && memorizedContext != root.getContext('2d') || memorizedData != root.chartData || memorizedOptions != root.chartOptions) {
var ctx = root.getContext('2d');
jsChart = new Chart.build(ctx, {
type: root.chartType,
data: root.chartData,
options: root.chartOptions
});
memorizedData = root.chartData ;
memorizedContext = root.getContext('2d');
memorizedOptions = root.chartOptions;
root.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
chartAnimator.start();
}
jsChart.draw(chartAnimationProgress);
}
onWidthChanged: {
if(jsChart) {
jsChart.resize();
}
}
onHeightChanged: {
if(jsChart) {
jsChart.resize();
}
}
}
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 ChartJs2QML contributors (starting with Elypson, Michael A. Voelkel, https://github.com/Elypson)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -6,45 +6,63 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
Item {
id: editText
id: root
property alias inputComponent: chatInputLoader.sourceComponent
property alias active: chatInputLoader.active
property string cancelButtonText: ""
property string saveButtonText: ""
property string msgText: ""
signal cancelEditClicked()
signal editCancelled()
signal editCompleted(var newMsgText)
height: childrenRect.height
implicitHeight: layout.implicitHeight
implicitWidth: layout.implicitWidth
ColumnLayout {
id: layout
anchors.fill: parent
spacing: 4
Loader {
id: chatInputLoader
// To-Do: Move to StatusChatInput once its moved to StatusQ
Layout.fillWidth: true
/*
NOTE: sourceComponent must have `messageText` property
TODO: Replace with StatusChatInput once its moved to StatusQ.
*/
sourceComponent: StatusInput {
width: editText.width
placeholderText: ""
readonly property string messageText: input.text
width: parent.width
input.placeholderText: ""
input.text: msgText
maximumHeight: 40
}
}
RowLayout {
spacing: 4
StatusFlatButton {
id: cancelBtn
text: cancelButtonText
size: StatusBaseButton.Size.Small
onClicked: cancelEditClicked()
onClicked: {
editCancelled()
}
}
StatusButton {
id: saveBtn
text: saveButtonText
size: StatusBaseButton.Size.Small
enabled: chatInputLoader.item.input.text.trim().length > 0
onClicked: editCompleted(chatInputLoader.item.input.text)
enabled: !!chatInputLoader.item && chatInputLoader.item.messageText.trim().length > 0
onClicked: {
editCompleted(!chatInputLoader.item ? "" : chatInputLoader.item.messageText)
}
}
}
}
@@ -25,10 +25,10 @@ Item {
property string loadingImageText: ""
property string errorLoadingImageText: ""
signal clicked(var image, var mouse)
signal clicked(var image, var mouse, var imageSource)
width: loadingImage.visible ? loadingImage.width : imageMessage.width
height: loadingImage.visible ? loadingImage.height : imageMessage.paintedHeight
implicitWidth: loadingImage.visible ? loadingImage.width : imageMessage.width
implicitHeight: loadingImage.visible ? loadingImage.height : imageMessage.paintedHeight
QtObject {
id: _internal
@@ -87,7 +87,7 @@ Item {
_internal.pausePlaying = ! _internal.pausePlaying
return
}
imageContainer.clicked(imageMessage, mouse)
imageContainer.clicked(imageMessage, mouse, imageMessage.source)
}
}
}
@@ -0,0 +1,191 @@
import QtQuick 2.3
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.14
import QtGraphicalEffects 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
Item {
id: root
implicitHeight: 22
implicitWidth: childrenRect.width
property int imageMargin: 4
signal addEmojiClicked(var sender, var mouse)
signal hoverChanged(bool hovered)
signal toggleReaction(int emojiID)
property var store
property bool isCurrentUser
property var emojiReactionsModel
property var icons: []
QtObject {
id: d
function lastTwoItems(nodes) {
return nodes.join(qsTr(" and "));
}
function showReactionAuthors(jsonArrayOfUsersReactedWithThisEmoji, emojiId) {
const listOfUsers = JSON.parse(jsonArrayOfUsersReactedWithThisEmoji)
if (listOfUsers.error) {
console.error("error parsing users who reacted to a message, error: ", obj.error)
return
}
let author;
if (listOfUsers.length === 1) {
author = listOfUsers[0]
} else if (listOfUsers.length === 2) {
author = lastTwoItems(listOfUsers);
} else {
var leftNode = [];
var rightNode = [];
const maxReactions = 12
let maximum = Math.min(maxReactions, listOfUsers.length)
if (listOfUsers.length > maxReactions) {
leftNode = listOfUsers.slice(0, maxReactions);
rightNode = listOfUsers.slice(maxReactions, listOfUsers.length);
return (rightNode.length === 1) ?
lastTwoItems([leftNode.join(", "), rightNode[0]]) :
lastTwoItems([leftNode.join(", "), qsTr("%1 more").arg(rightNode.length)]);
}
leftNode = listOfUsers.slice(0, maximum - 1);
rightNode = listOfUsers.slice(maximum - 1, listOfUsers.length);
author = lastTwoItems([leftNode.join(", "), rightNode[0]])
}
return qsTr("%1 reacted with %2")
.arg(author)
.arg(Emoji.getEmojiFromId(emojiId));
}
}
Row {
spacing: root.imageMargin
Repeater {
id: reactionRepeater
width: childrenRect.width
model: root.emojiReactionsModel
Control {
id: reactionDelegate
topPadding: 2
bottomPadding: 2
leftPadding: 2
rightPadding: 6
background: Rectangle {
radius: 10
color: model.didIReactWithThisEmoji
? (reactionDelegate.hovered ? Theme.palette.statusMessage.emojiReactionActiveBackgroundHovered
: Theme.palette.statusMessage.emojiReactionActiveBackground)
: (reactionDelegate.hovered ? Theme.palette.statusMessage.emojiReactionBackgroundHovered
: Theme.palette.statusMessage.emojiReactionBackground)
// Rounded corner to cover one corner
Rectangle {
anchors.top: parent.top
anchors.left: parent.left
width: 10
height: 10
radius: 2
color: parent.color
}
}
contentItem: Row {
spacing: 4
StatusEmoji {
anchors.verticalCenter: parent.verticalCenter
width: 15
height: 15
source: {
if (model.emojiId >= 1 && model.emojiId <= root.icons.length)
return root.icons[model.emojiId - 1];
return "";
}
}
StatusBaseText {
anchors.verticalCenter: parent.verticalCenter
text: model.numberOfReactions
font.pixelSize: 12
color: model.didIReactWithThisEmoji ? Theme.palette.indirectColor1 : Theme.palette.directColor1
}
}
StatusToolTip {
visible: reactionDelegate.hovered
maxWidth: 400
text: d.showReactionAuthors(model.jsonArrayOfUsersReactedWithThisEmoji, model.emojiId)
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: {
root.hoverChanged(true)
}
onExited: {
root.hoverChanged(false)
}
onClicked: {
root.toggleReaction(model.emojiId)
}
}
}
}
Item {
width: addEmojiButton.width + addEmojiButton.anchors.leftMargin // there is more margin between the button and the emojis than between each emoji
height: addEmojiButton.height
StatusIcon {
id: addEmojiButton
readonly property bool isHovered: addEmojiButtonMouseArea.containsMouse
anchors.left: parent.left
anchors.leftMargin: 2.5
icon: "reaction-b"
width: 16.5
height: 16.5
color: addEmojiButton.isHovered ? Theme.palette.primaryColor1 : Theme.palette.baseColor1
}
MouseArea {
id: addEmojiButtonMouseArea
anchors.fill: addEmojiButton
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
root.addEmojiClicked(this, mouse);
}
}
StatusToolTip {
visible: addEmojiButton.isHovered
text: qsTr("Add reaction")
}
}
}
}
@@ -3,36 +3,41 @@ import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
Item {
id: statusMessageHeader
id: root
property StatusMessageSenderDetails sender: StatusMessageSenderDetails { }
property alias displayNameLabel: primaryDisplayName
property alias secondaryNameLabel: secondaryDisplayName
property alias tertiaryDetailsLabel: tertiaryDetailText
property alias timestamp: timestampText
property string displayName: ""
property string secondaryName: ""
property string tertiaryDetail: ""
property string tertiaryDetail: sender.id
property string resendText: ""
property bool showResendButton: false
property bool isContact: false
property var trustIndicator: StatusContactVerificationIcons.TrustedType.None
property bool isContact: sender.isContact
property int trustIndicator: sender.trustIndicator
property bool amISender: false
property bool displayNameClickable: true
property string messageOriginInfo: ""
signal clicked()
signal clicked(var sender, var mouse)
signal resendClicked()
height: childrenRect.height
width: primaryDisplayName.width + (secondaryDisplayName.visible ? secondaryDisplayName.width + header.spacing : 0)
implicitHeight: layout.implicitHeight
implicitWidth: layout.implicitWidth
RowLayout {
id: header
id: layout
spacing: 4
TextEdit {
id: primaryDisplayName
Layout.alignment: Qt.AlignBottom
font.family: Theme.palette.baseFont.name
font.weight: Font.Medium
font.pixelSize: 15
@@ -41,55 +46,62 @@ Item {
wrapMode: Text.WordWrap
selectByMouse: true
color: Theme.palette.primaryColor1
text: displayName
text: root.amISender ? qsTr("You") : root.sender.displayName
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
enabled: root.displayNameClickable
hoverEnabled: true
onClicked: {
statusMessageHeader.clicked()
root.clicked(this, mouse)
}
}
Layout.alignment: Qt.AlignBottom
}
StatusBaseText {
id: messageOriginInfo
Layout.alignment: Qt.AlignVCenter
visible: root.messageOriginInfo !== ""
color: Theme.palette.baseColor1
font.pixelSize: 10
text: root.messageOriginInfo
}
StatusContactVerificationIcons {
isContact: statusMessageHeader.isContact
trustIndicator: statusMessageHeader.trustIndicator
visible: !root.amISender
isContact: root.isContact
trustIndicator: root.trustIndicator
}
StatusBaseText {
id: secondaryDisplayName
Layout.alignment: Qt.AlignVCenter
visible: !root.amISender && !!root.sender.secondaryName
color: Theme.palette.baseColor1
font.pixelSize: 10
text: secondaryName
visible: !!text
text: `(${root.sender.secondaryName})`
}
StatusBaseText {
id: dotSeparator1
Layout.fillHeight: true
Layout.alignment: Qt.AlignVCenter
visible: secondaryDisplayName.visible
font.pixelSize: 10
color: Theme.palette.baseColor1
text: "."
visible: secondaryDisplayName.visible
text: ""
}
StatusBaseText {
id: tertiaryDetailText
visible: !root.amISender && root.messageOriginInfo === ""
Layout.alignment: Qt.AlignVCenter
Layout.maximumWidth: 58
font.pixelSize: 10
elide: Text.ElideMiddle
color: Theme.palette.baseColor1
text: tertiaryDetail
text: Utils.elideText(tertiaryDetail, 5, 3)
}
StatusBaseText {
id: dotSeparator2
Layout.fillHeight: true
Layout.alignment: Qt.AlignVCenter
visible: tertiaryDetailText.visible
font.pixelSize: 10
color: Theme.palette.baseColor1
text: "."
visible: tertiaryDetailText.visible
text: ""
}
StatusTimeStampLabel {
id: timestampText
@@ -98,12 +110,12 @@ Item {
Layout.alignment: Qt.AlignVCenter
color: Theme.palette.dangerColor1
font.pixelSize: 12
text: statusMessageHeader.resendText
text: root.resendText
visible: showResendButton && !!timestampText.text
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: statusMessageHeader.resendClicked()
onClicked: root.resendClicked()
}
}
}
@@ -6,29 +6,29 @@ import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
Rectangle {
id: buttonsContainer
id: root
property list<Item> quickActions
property list<Item> items
QtObject {
id: _internal
readonly property int containerMargin: 2
}
width: buttonRow.width + _internal.containerMargin * 2
height: 36
implicitWidth: buttonRow.width + _internal.containerMargin * 2
implicitHeight: 36
radius: 8
color: Theme.palette.statusSelect.menuItemBackgroundColor
layer.enabled: true
layer.effect: DropShadow {
width: buttonsContainer.width
height: buttonsContainer.height
x: buttonsContainer.x
y: buttonsContainer.y + 10
width: root.width
height: root.height
x: root.x
y: root.y + 10
horizontalOffset: 0
verticalOffset: 2
source: buttonsContainer
source: root
radius: 10
samples: 15
color: Theme.palette.dropShadow
@@ -39,13 +39,13 @@ Rectangle {
spacing: _internal.containerMargin
anchors.left: parent.left
anchors.leftMargin: _internal.containerMargin
anchors.verticalCenter: buttonsContainer.verticalCenter
anchors.verticalCenter: root.verticalCenter
height: parent.height - 2 * _internal.containerMargin
}
onQuickActionsChanged: {
for (let idx in quickActions) {
quickActions[idx].parent = buttonRow
onItemsChanged: {
for (let idx in items) {
items[idx].parent = buttonRow
}
}
}
@@ -7,18 +7,20 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
Loader {
id: chatReply
Item {
id: root
property StatusMessageDetails replyDetails
property string audioMessageInfoText: ""
property bool profileClickable: true
signal replyProfileClicked()
signal replyProfileClicked(var sender, var mouse)
active: visible
implicitHeight: layout.implicitHeight
implicitWidth: layout.implicitWidth
sourceComponent: RowLayout {
id: replyLayout
RowLayout {
id: layout
spacing: 8
Shape {
id: replyCorner
@@ -56,13 +58,15 @@ Loader {
StatusSmartIdenticon {
id: profileImage
Layout.alignment: Qt.AlignTop
image: replyDetails.profileImage
name: replyDetails.displayName
name: replyDetails.sender.displayName
asset: replyDetails.sender.profileImage.assetSettings
ringSettings: replyDetails.sender.profileImage.ringSettings
MouseArea {
cursorShape: Qt.PointingHandCursor
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
onClicked: replyProfileClicked()
enabled: root.profileClickable
onClicked: replyProfileClicked(this, mouse)
}
}
TextEdit {
@@ -74,7 +78,7 @@ Loader {
font.weight: Font.Medium
selectByMouse: true
readOnly: true
text: replyDetails.displayName
text: replyDetails.amISender ? qsTr("You") : replyDetails.sender.displayName
}
}
StatusTextMessage {
@@ -85,13 +89,14 @@ Loader {
textField.height: 18
clip: true
visible: !!replyDetails.messageText
allowShowMore: false
}
StatusImageMessage {
Layout.fillWidth: true
Layout.preferredHeight: imageAlias.paintedHeight
imageWidth: 56
source: replyDetails.contentType === StatusMessage.ContentType.Image ? replyDetails.messageContent : ""
visible: replyDetails.contentType === StatusMessage.ContentType.Image
// visible: replyDetails.contentType === StatusMessage.ContentType.Image
shapeType: StatusImageMessage.ShapeType.ROUNDED
}
Item {
@@ -100,9 +105,10 @@ Loader {
Layout.alignment: Qt.AlignLeft
visible: replyDetails.contentType === StatusMessage.ContentType.Sticker
StatusSticker {
image.width: 48
image.height: 48
image.source: replyDetails.messageContent
asset.width: 48
asset.height: 48
asset.name: replyDetails.messageContent
asset.isImage: true
}
}
Item {
@@ -116,7 +122,7 @@ Loader {
height: 22
isPreview: true
audioSource: replyDetails.messageContent
audioMessageInfoText: chatReply.audioMessageInfoText
audioMessageInfoText: root.audioMessageInfoText
}
}
}
@@ -1,4 +1,5 @@
import QtQuick 2.13
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtGraphicalEffects 1.13
@@ -11,14 +12,35 @@ Loader {
active: visible
sourceComponent: Rectangle {
height: 24
width: layout.width + 16
color: Theme.palette.pinColor2
radius: 12
RowLayout {
id: layout
anchors.centerIn: parent
sourceComponent: Control {
verticalPadding: 3
leftPadding: 2
rightPadding: 6
background: Rectangle {
readonly property color translucentColor: Theme.palette.pinColor2
implicitWidth: 24
implicitHeight: 24
color: Qt.rgba(translucentColor.r,
translucentColor.g,
translucentColor.b, 1)
opacity: translucentColor.a
layer.enabled: true
radius: 12
Rectangle {
anchors.bottom: parent.bottom
anchors.left: parent.left
width: parent.width / 2
height: parent.height / 2
color: parent.color
radius: 4
}
}
contentItem: RowLayout {
spacing: 4
StatusIcon {
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: 16
@@ -35,7 +57,6 @@ Loader {
}
StatusBaseText {
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: -4
color: Theme.palette.directColor1
font.pixelSize: 13
font.weight: Font.Medium
@@ -10,7 +10,7 @@ Loader {
property bool noHover: false
property bool noMouseArea: false
property StatusImageSettings image: StatusImageSettings {
property StatusAssetSettings asset: StatusAssetSettings {
width: 140
height: 140
}
@@ -26,8 +26,8 @@ Loader {
color: Theme.palette.baseColor2
radius: 16
width: image.width
height: image.height
width: asset.width
height: asset.height
function reload() {
// From the documentation (https://doc.qt.io/qt-5/qml-qtquick-image.html#sourceSize-prop)
@@ -53,7 +53,7 @@ Loader {
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
cache: true
source: image.source
source: asset.name
onStatusChanged: {
if (status === Image.Ready) {
@@ -6,24 +6,34 @@ import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
Item {
id: textMessage
id: root
property int contentType: 0
property alias textField: chatText
property bool allowShowMore: true
signal linkActivated(url link)
signal linkActivated(string link)
implicitHeight: showMoreLoader.active ? childrenRect.height : chatText.height
implicitWidth: chatText.implicitWidth
implicitHeight: chatText.effectiveHeight + d.showMoreHeight
QtObject {
id: _internal
id: d
property bool readMore: false
property bool veryLongChatText: chatText.length > 1000
readonly property bool veryLongChatText: chatText.length > 1000
readonly property int showMoreHeight: showMoreLoader.visible ? showMoreLoader.height : 0
}
TextEdit {
id: chatText
visible: !showMoreLoader.active || _internal.readMore
objectName: "StatusTextMessage_chatText"
readonly property int effectiveHeight: d.veryLongChatText && !d.readMore ? Math.min(chatText.implicitHeight, 200)
: chatText.implicitHeight
width: parent.width
height: effectiveHeight + d.showMoreHeight / 2
visible: !opMask.active
clip: true
selectedTextColor: Theme.palette.directColor1
selectionColor: Theme.palette.primaryColor3
color: Theme.palette.directColor1
@@ -33,12 +43,12 @@ Item {
wrapMode: Text.Wrap
readOnly: true
selectByMouse: true
height: _internal.veryLongChatText && !_internal.readMore ? Math.min(implicitHeight, 200) : implicitHeight
width: parent.width
clip: height < implicitHeight
onLinkActivated: textMessage.linkActivated(link)
onLinkActivated: {
root.linkActivated(link);
}
onLinkHovered: {
cursorShape: Qt.PointingHandCursor
// Strange thing. Without this empty stub the cursorShape
// is not changed to pointingHandCursor.
}
}
@@ -60,7 +70,7 @@ Item {
Loader {
id: opMask
active: showMoreLoader.active && !_internal.readMore
active: showMoreLoader.active && !d.readMore
anchors.fill: chatText
sourceComponent: OpacityMask {
source: chatText
@@ -70,17 +80,17 @@ Item {
Loader {
id: showMoreLoader
active: _internal.veryLongChatText
anchors.top: chatText.bottom
anchors.topMargin: -10
active: root.allowShowMore && d.veryLongChatText
visible: active
anchors.verticalCenter: chatText.bottom
anchors.horizontalCenter: parent.horizontalCenter
sourceComponent: StatusRoundButton {
implicitWidth: 24
implicitHeight: 24
type: StatusRoundButton.Type.Secondary
icon.name: _internal.readMore ? "chevron-up": "chevron-down"
icon.name: d.readMore ? "chevron-up": "chevron-down"
onClicked: {
_internal.readMore = !_internal.readMore
d.readMore = !d.readMore
}
}
}
+5 -1
View File
@@ -9,10 +9,11 @@ StatusChatListItem 0.1 StatusChatListItem.qml
StatusChatListCategory 0.1 StatusChatListCategory.qml
StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml
StatusChatListAndCategories 0.1 StatusChatListAndCategories.qml
StatusChatToolBar 0.1 StatusChatToolBar.qml
StatusToolBar 0.1 StatusToolBar.qml
StatusContactRequestsIndicatorListItem 0.1 StatusContactRequestsIndicatorListItem.qml
StatusEmoji 0.1 StatusEmoji.qml
StatusContactVerificationIcons 0.1 StatusContactVerificationIcons.qml
StatusDateGroupLabel 0.1 StatusDateGroupLabel.qml
StatusDescriptionListItem 0.1 StatusDescriptionListItem.qml
StatusLetterIdenticon 0.1 StatusLetterIdenticon.qml
StatusListItem 0.1 StatusListItem.qml
@@ -31,6 +32,7 @@ StatusExpandableItem 0.1 StatusExpandableItem.qml
StatusSmartIdenticon 0.1 StatusSmartIdenticon.qml
StatusMessage 0.1 StatusMessage.qml
StatusMessageDetails 0.1 StatusMessageDetails.qml
StatusMessageSenderDetails 0.1 StatusMessageSenderDetails.qml
StatusTagSelector 0.1 StatusTagSelector.qml
StatusToastMessage 0.1 StatusToastMessage.qml
StatusWizardStepper 0.1 StatusWizardStepper.qml
@@ -41,3 +43,5 @@ StatusCommunityTags 0.1 StatusCommunityTags.qml
StatusItemSelector 0.1 StatusItemSelector.qml
StatusCard 0.1 StatusCard.qml
StatusDatePicker 0.1 StatusDatePicker.qml
StatusChart 0.1 StatusChart.qml
StatusChartPanel 0.1 StatusChartPanel.qml
+95 -144
View File
@@ -1,11 +1,14 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import QtQuick.Controls 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Utils 0.1
Rectangle {
id: statusBaseButton
Button {
id: root
enum Size {
Tiny,
@@ -19,158 +22,106 @@ Rectangle {
Primary
}
property StatusIconSettings icon: StatusIconSettings {
width: 24
height: 24
}
property StatusAssetSettings asset: StatusAssetSettings { }
property bool loading: false
property bool loading
property alias hovered: sensor.containsMouse
property color normalColor
property color hoverColor
property color disabledColor
property color textColor
property color disabledTextColor
property color borderColor: "transparent"
property int size: StatusBaseButton.Size.Large
property int type: StatusBaseButton.Type.Normal
property alias text: label.text
property alias font: label.font
property real defaultLeftPadding: size === StatusBaseButton.Size.Large ? 24 : 12
property real defaultRightPadding: size === StatusBaseButton.Size.Large ? 24 : 12
property real defaultTopPadding: {
switch (size) {
case StatusBaseButton.Size.Tiny:
return 5
case StatusBaseButton.Size.Small:
return 10
case StatusBaseButton.Size.Large:
default:
return 11
}
}
property real defaultBottomPadding: {
switch (size) {
case StatusBaseButton.Size.Tiny:
return 5
case StatusBaseButton.Size.Small:
return 10
case StatusBaseButton.Size.Large:
default:
return 11
}
}
property real leftPadding: defaultLeftPadding
property real rightPadding: defaultRightPadding
property real topPadding: defaultTopPadding
property real bottomPadding: defaultBottomPadding
property color normalColor
property color hoverColor
property color disaledColor
property color textColor
property color disabledTextColor
signal pressed(var mouse)
signal released(var mouse)
signal clicked(var mouse)
signal pressAndHold(var mouse)
property bool highlighted: false
/// Implementation
implicitWidth: layout.width + statusBaseButton.leftPadding + statusBaseButton.rightPadding
implicitHeight: layout.height + statusBaseButton.topPadding + statusBaseButton.bottomPadding
radius: size !== StatusBaseButton.Size.Tiny ? 8 : 6
color: {
if (statusBaseButton.enabled)
return sensor.containsMouse || highlighted ? hoverColor
: normalColor;
return disaledColor
}
QtObject {
id: d
readonly property color textColor: statusBaseButton.enabled ? statusBaseButton.textColor : statusBaseButton.disabledTextColor
readonly property color textColor: root.enabled || root.loading ? root.textColor : root.disabledTextColor
}
font.family: Theme.palette.baseFont.name
font.weight: Font.Medium
font.pixelSize: size === StatusBaseButton.Size.Large ? 15 : 13
horizontalPadding: {
if (root.icon.name) {
return size === StatusBaseButton.Size.Large ? 18 : 16
}
return size === StatusBaseButton.Size.Large ? 24 : 12
}
verticalPadding: {
switch (size) {
case StatusBaseButton.Size.Tiny:
return 5
case StatusBaseButton.Size.Small:
return 10
case StatusBaseButton.Size.Large:
default:
return 11
}
}
spacing: root.size === StatusBaseButton.Size.Large ? 6 : 4
icon.height: 24
icon.width: 24
background: Rectangle {
radius: root.size === StatusBaseButton.Size.Tiny ? 6 : 8
border.color: root.borderColor
color: {
if (root.enabled)
return !root.loading && (root.hovered || root.highlighted) ? hoverColor : normalColor;
return disabledColor;
}
}
contentItem: RowLayout {
spacing: root.spacing
StatusIcon {
Layout.preferredWidth: visible ? root.icon.width : 0
Layout.preferredHeight: visible ? root.icon.height : 0
icon: root.icon.name
rotation: root.asset.rotation
opacity: !loading && root.icon.name !== ""
visible: root.icon.name !== ""
color: d.textColor
}
StatusEmoji {
Layout.preferredWidth: visible ? root.icon.width : 0
Layout.preferredHeight: visible ? root.icon.height : 0
visible: root.asset.emoji
emojiId: Emoji.iconId(root.asset.emoji, root.asset.emojiSize) || ""
}
StatusBaseText {
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
opacity: !loading
font: root.font
text: root.text
color: d.textColor
verticalAlignment: Text.AlignVCenter
}
}
Loader {
anchors.centerIn: parent
active: root.loading
sourceComponent: StatusLoadingIndicator {
color: d.textColor
}
}
// stop the mouse clicks in the "loading" state w/o disabling the whole button
// as this would make it impossible to have hover events or a tooltip
MouseArea {
id: sensor
anchors.fill: parent
cursorShape: loading ? Qt.ArrowCursor
: Qt.PointingHandCursor
hoverEnabled: true
enabled: !loading && statusBaseButton.enabled
Loader {
anchors.centerIn: parent
active: loading
sourceComponent: StatusLoadingIndicator {
color: d.textColor
} // Indicator
} // Loader
Row {
id: layout
anchors.centerIn: parent
spacing: 4
StatusIcon {
id: statusIcon
width: statusBaseButton.icon.width
height: statusBaseButton.icon.height
icon: statusBaseButton.icon.name
rotation: statusBaseButton.icon.rotation
anchors.verticalCenter: parent.verticalCenter
opacity: !loading && statusBaseButton.icon.name !== ""
visible: statusBaseButton.icon.name !== ""
color: d.textColor
} // Icon
StatusEmoji {
width: statusBaseButton.icon.width
height: statusBaseButton.icon.height
anchors.verticalCenter: parent.verticalCenter
visible: statusBaseButton.icon.emoji
emojiId: Emoji.iconId(statusBaseButton.icon.emoji, statusBaseButton.icon.emojiSize) || ""
} // Emoji
StatusBaseText {
id: label
opacity: !loading
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: size === StatusBaseButton.Size.Large ? 15 : 13 // by design
color: d.textColor
} // Text
} // Row
onPressed: {
if (!loading) {
statusBaseButton.pressed(mouse)
}
}
onReleased: {
if (!loading) {
statusBaseButton.released(mouse)
}
}
onClicked: {
if (!loading) {
statusBaseButton.clicked(mouse)
}
}
onPressAndHold: {
if (!loading) {
statusBaseButton.pressAndHold(mouse)
}
}
} // Sensor
acceptedButtons: Qt.AllButtons
enabled: root.loading
onPressed: mouse.accepted = true
onWheel: wheel.accepted = true
cursorShape: !root.loading ? Qt.PointingHandCursor: undefined // always works; 'undefined' resets to default cursor
}
}
+27 -37
View File
@@ -7,6 +7,7 @@ import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
/*!
\qmltype StatusBaseInput
@@ -182,9 +183,9 @@ Item {
/*!
\qmlproperty bool StatusBaseInput::valid
This property sets the valid state. Default value is true.
This property sets the valid state. Default value is false.
*/
property bool valid: true
property bool valid: false
/*!
\qmlproperty bool StatusBaseInput::pristine
This property sets the pristine. Default value is true.
@@ -217,21 +218,19 @@ Item {
property bool showBackground: true
/*!
\qmlproperty StatusIconSettings StatusBaseInput::icon
\qmlproperty StatusAssetSettings StatusBaseInput::icon
This property holds a set of settings for the icon of the StatusBaseInput.
*/
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings asset: StatusAssetSettings {
width: 24
height: 24
name: ""
color: Theme.palette.baseColor1
emoji: ""
letterSize: emoji ? 11 : 14
background: StatusIconBackgroundSettings {
width: 30
height: 30
color: Theme.palette.indirectColor1
}
bgWidth: 30
bgHeight: 30
bgColor: Theme.palette.indirectColor1
}
/*!
@@ -317,8 +316,8 @@ Item {
sourceComponent: {
if (root.leftComponent) return root.leftComponent
if (!root.leftIcon) return undefined
if (root.icon.emoji || root.icon.isLetterIdenticon) return identiconComponent
if (root.icon.name) return isIconSelectable ? identiconComponent : iconComponent
if (root.asset.emoji || root.asset.isLetterIdenticon) return identiconComponent
if (root.asset.name) return isIconSelectable ? identiconComponent : iconComponent
return undefined
}
}
@@ -339,17 +338,6 @@ Item {
}
clip: true
function ensureVisible(r) {
if (contentX >= r.x)
contentX = r.x
else if (contentX + width <= r.x + r.width)
contentX = r.x + r.width - width
if (contentY >= r.y)
contentY = r.y
else if (contentY + height <= r.y + r.height)
contentY = r.y + r.height - height
}
TextEdit {
id: edit
property string previousText: text
@@ -374,7 +362,7 @@ Item {
edit.keyEvent = event.key
root.keyPressed(event);
}
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
onCursorRectangleChanged: Utils.ensureVisible(flick, cursorRectangle)
onActiveFocusChanged: if (root.pristine) root.pristine = false
onTextChanged: {
if (previousText === text) {
@@ -430,8 +418,8 @@ Item {
if (root.rightComponent) return root.rightComponent
if (root.clearable) return clearButton
if (root.leftIcon) return undefined
if (root.icon.emoji) return identiconComponent
if (root.icon.name) return isIconSelectable ? identiconComponent : iconComponent
if (root.asset.emoji) return identiconComponent
if (root.asset.name) return isIconSelectable ? identiconComponent : iconComponent
return undefined
}
}
@@ -465,14 +453,16 @@ Item {
StatusSmartIdenticon {
id: identicon
icon.width: 24
icon.height: 24
icon.background: root.icon.background
icon.color: root.icon.color
icon.letterSize: root.icon.letterSize
icon.emoji: root.icon.emoji
icon.name: !root.icon.emoji ? root.icon.name : ""
icon.isLetterIdenticon: root.icon.isLetterIdenticon
asset.width: 24
asset.height: 24
asset.bgWidth: root.asset.bgWidth
asset.bgHeight: root.asset.bgHeight
asset.bgColor: root.asset.bgColor
asset.color: root.asset.color
asset.letterSize: root.asset.letterSize
asset.emoji: root.asset.emoji
asset.name: !root.asset.emoji ? root.asset.name : ""
asset.isLetterIdenticon: root.asset.isLetterIdenticon
name: root.letterIconName
MouseArea {
@@ -492,10 +482,10 @@ Item {
StatusIcon {
id: statusIcon
icon: root.icon.name
width: root.icon.width
height: root.icon.height
color: root.icon.color
icon: root.asset.name
width: root.asset.width
height: root.asset.height
color: root.asset.color
}
}
}
+1 -3
View File
@@ -11,12 +11,10 @@ StatusBaseButton {
hoverColor: type === StatusBaseButton.Type.Primary ? Theme.palette.hoverColor(normalColor) :
type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor2
: Theme.palette.dangerColor2
disaledColor: Theme.palette.baseColor2
disabledColor: Theme.palette.baseColor2
textColor: type === StatusBaseButton.Type.Primary ? Theme.palette.white :
type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor1
: Theme.palette.dangerColor1
disabledTextColor: Theme.palette.baseColor1
font.weight: type === StatusBaseButton.Type.Primary ? Font.Medium : Font.Normal
}
@@ -16,10 +16,9 @@ Rectangle {
signal clicked(var mouse)
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings icon: StatusAssetSettings {
width: 24
height: 24
background: StatusIconBackgroundSettings {}
}
color: {
@@ -41,14 +40,14 @@ Rectangle {
}
StatusRoundIcon {
icon.name: root.icon.name
icon.width: root.icon.width
icon.height: root.icon.height
icon.rotation: root.icon.rotation
icon.color: Theme.palette.white
icon.background.width: 40
icon.background.height: 40
icon.background.color: root.icon.color
asset.name: root.icon.name
asset.width: root.icon.width
asset.height: root.icon.height
asset.rotation: root.icon.rotation
asset.color: Theme.palette.white
asset.bgWidth: 40
asset.bgHeight: 40
asset.bgColor: root.icon.color
anchors.top: parent.top
anchors.topMargin: 8
anchors.left: parent.left
+145 -183
View File
@@ -1,29 +1,22 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
Rectangle {
id: statusChatInfoButton
Button {
id: root
objectName: "chatInfoButton"
implicitWidth: identicon.width +
Math.max(
statusChatInfoButtonTitle.anchors.leftMargin + statusChatInfoButtonTitle.implicitWidth,
statusChatInfoButtonTitle.anchors.leftMargin + statusChatInfoButtonSubTitle.implicitWidth
) + 8
implicitHeight: 48
property string title: text
property string subTitle
property bool muted
property int pinnedMessagesCount
property string title: ""
property string subTitle: ""
property bool muted: false
property int pinnedMessagesCount: 0
property StatusImageSettings image: StatusImageSettings {
width: 36
height: 36
}
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings asset: StatusAssetSettings {
width: 36
height: 36
charactersLen: 2
@@ -32,9 +25,7 @@ Rectangle {
property int type: StatusChatInfoButton.Type.PublicChat
property alias tooltip: statusToolTip
property alias sensor: sensor
signal clicked(var mouse)
signal pinnedMessagesCountClicked(var mouse)
signal unmute()
signal linkActivated(string link)
@@ -49,192 +40,163 @@ Rectangle {
CommunityChat // 6
}
radius: 8
color: sensor.enabled && sensor.containsMouse ? Theme.palette.baseColor2 : "transparent"
horizontalPadding: 4
verticalPadding: 2
spacing: 4
MouseArea {
id: sensor
anchors.fill: parent
hoverEnabled: true
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
background: Rectangle {
radius: 8
color: root.enabled && root.hovered ? Theme.palette.baseColor2 : "transparent"
onClicked: statusChatInfoButton.clicked(mouse)
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: root.hovered ? Qt.PointingHandCursor : undefined
}
}
contentItem: RowLayout {
spacing: root.spacing
// identicon
StatusSmartIdenticon {
id: identicon
anchors.left: parent.left
anchors.leftMargin: 4
anchors.verticalCenter: parent.verticalCenter
image: statusChatInfoButton.image
icon: statusChatInfoButton.icon
name: statusChatInfoButton.title
asset: root.asset
name: root.title
}
Item {
id: statusChatInfoButtonTitle
anchors.top: identicon.top
anchors.topMargin: statusChatInfoButtonSubTitle.visible ? 0 : 8
anchors.left: identicon.right
anchors.leftMargin: 8
// text
ColumnLayout {
Layout.fillWidth: true
spacing: 2
width: Math.min(parent.width - anchors.leftMargin
- identicon.width - identicon.anchors.leftMargin,
implicitWidth)
height: chatName.height
// title
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeading | Qt.AlignBottom
spacing: root.spacing
implicitWidth: statusIcon.width + chatName.anchors.leftMargin + chatName.implicitWidth
+ mutedDelta
StatusIcon {
visible: root.type !== StatusChatInfoButton.Type.OneToOneChat
Layout.preferredWidth: 14
Layout.preferredHeight: 14
color: root.muted ? Theme.palette.baseColor1 : Theme.palette.directColor1
icon: {
switch (root.type) {
case StatusChatInfoButton.Type.PublicCat:
return "tiny/public-chat"
case StatusChatInfoButton.Type.GroupChat:
return "tiny/group"
case StatusChatInfoButton.Type.CommunityChat:
return "tiny/channel"
default:
return "tiny/public-chat"
}
}
}
property real mutedDelta: mutedIcon.visible ? mutedIcon.width + 8 : 0
StatusBaseText {
objectName: "statusChatInfoButtonNameText"
Layout.fillWidth: true
elide: Text.ElideRight
text: root.type === StatusChatInfoButton.Type.PublicChat && !root.title.startsWith("#") ?
"#" + root.title
: root.title
color: root.muted ? Theme.palette.directColor5 : Theme.palette.directColor1
font.weight: Font.Medium
}
StatusIcon {
id: statusIcon
anchors.top: parent.top
anchors.topMargin: -2
anchors.left: parent.left
StatusIcon {
objectName: "mutedIcon"
Layout.preferredWidth: 13
Layout.preferredHeight: 13
icon: "tiny/muted"
color: mutedIconSensor.containsMouse ? Theme.palette.directColor1 : Theme.palette.baseColor1
visible: root.muted
visible: statusChatInfoButton.type !== StatusChatInfoButton.Type.OneToOneChat
width: visible ? 14 : 0
color: statusChatInfoButton.muted ? Theme.palette.baseColor1 : Theme.palette.directColor1
icon: {
switch (statusChatInfoButton.type) {
case StatusChatInfoButton.Type.PublicCat:
return "tiny/public-chat"
break;
case StatusChatInfoButton.Type.GroupChat:
return "tiny/group"
break;
case StatusChatInfoButton.Type.CommunityChat:
return "tiny/channel"
break;
default:
return "tiny/public-chat"
MouseArea {
id: mutedIconSensor
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: root.unmute()
}
StatusToolTip {
id: statusToolTip
text: qsTr("Unmute")
visible: mutedIconSensor.containsMouse
orientation: StatusToolTip.Orientation.Bottom
y: parent.height + 12
}
}
}
StatusBaseText {
id: chatName
objectName: "statusChatInfoButtonNameText"
// subtitle
RowLayout {
id: subtitleRow
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeading | Qt.AlignTop
Layout.rightMargin: 4
spacing: 0
anchors.left: statusIcon.visible ? statusIcon.right : parent.left
anchors.leftMargin: statusIcon.visible ? 1 : 0
anchors.top: parent.top
elide: Text.ElideRight
width: Math.min(implicitWidth, parent.width
- statusIcon.width
- statusChatInfoButtonTitle.mutedDelta)
text: statusChatInfoButton.type === StatusChatInfoButton.Type.PublicChat &&
!statusChatInfoButton.title.startsWith("#") ?
"#" + statusChatInfoButton.title :
statusChatInfoButton.title
color: statusChatInfoButton.muted ? Theme.palette.directColor5 : Theme.palette.directColor1
font.pixelSize: 15
font.weight: Font.Medium
}
StatusIcon {
objectName: "mutedIcon"
id: mutedIcon
anchors.left: chatName.right
anchors.leftMargin: 4
anchors.top: chatName.top
anchors.topMargin: -2
width: 13
icon: "tiny/muted"
color: mutedIconSensor.containsMouse ? Theme.palette.directColor1 : Theme.palette.baseColor1
visible: statusChatInfoButton.muted
MouseArea {
id: mutedIconSensor
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: statusChatInfoButton.unmute()
StatusSelectableText {
Layout.fillWidth: implicitWidth + separator.width + pinIcon.width + pinText.width > subtitleRow.width
text: root.subTitle
visible: root.subTitle
color: Theme.palette.baseColor1
font.pixelSize: 12
onLinkActivated: root.linkActivated(link)
}
StatusToolTip {
id: statusToolTip
text: "Unmute"
visible: mutedIconSensor.containsMouse
orientation: StatusToolTip.Orientation.Bottom
y: parent.height + 12
Rectangle {
id: separator
Layout.preferredHeight: 12
Layout.preferredWidth: 1
Layout.leftMargin: 4
Layout.rightMargin: 2
color: Theme.palette.directColor7
visible: root.subTitle && root.pinnedMessagesCount
}
}
}
Item {
id: statusChatInfoButtonSubTitle
anchors.left: statusChatInfoButtonTitle.left
anchors.top: statusChatInfoButtonTitle.bottom
visible: !!statusChatInfoButton.subTitle || statusChatInfoButton.pinnedMessagesCount > 0
height: visible ? chatType.height : 0
width: Math.min(parent.width - statusChatInfoButtonTitle.anchors.leftMargin
- identicon.width - identicon.anchors.leftMargin - 8,
implicitWidth)
implicitWidth: chatType.implicitWidth + pinIconDelta + 8
property real pinIconDelta: pinIcon.visible ? pinIcon.width + pinIcon.anchors.leftMargin
+ divider.width + divider.anchors.leftMargin
: 0
StatusSelectableText {
id: chatType
text: statusChatInfoButton.subTitle
color: Theme.palette.baseColor1
font.pixelSize: 12
width: Math.min(parent.width - (pinIcon.visible ? divider.width + divider.anchors.leftMargin + pinIcon.width + pinIcon.anchors.leftMargin : 0),
implicitWidth)
onLinkActivated: statusChatInfoButton.linkActivated(link)
}
Rectangle {
id: divider
height: 12
width: 1
color: Theme.palette.directColor7
anchors.left: chatType.right
anchors.leftMargin: 4
anchors.verticalCenter: chatType.verticalCenter
visible: !!chatType.text && pinIcon.visible
}
StatusIcon {
id: pinIcon
anchors.left: divider.visible ? divider.right : parent.left
anchors.leftMargin: -2
anchors.verticalCenter: chatType.verticalCenter
height: 14
visible: statusChatInfoButton.pinnedMessagesCount > 0
icon: "pin"
color: Theme.palette.baseColor1
}
StatusBaseText {
anchors.left: pinIcon.right
anchors.leftMargin: -6
anchors.verticalCenter: pinIcon.verticalCenter
width: 14
text: statusChatInfoButton.pinnedMessagesCount
font.pixelSize: 12
font.underline: pinCountSensor.containsMouse
visible: pinIcon.visible
color: pinCountSensor.containsMouse ? Theme.palette.directColor1 : Theme.palette.baseColor1
MouseArea {
objectName: "pinMessagesCounterSensor"
id: pinCountSensor
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: statusChatInfoButton.pinnedMessagesCountClicked(mouse)
StatusIcon {
id: pinIcon
Layout.preferredHeight: 14
Layout.preferredWidth: 14
visible: root.pinnedMessagesCount > 0
icon: "pin"
color: Theme.palette.baseColor1
}
StatusBaseText {
id: pinText
TextMetrics {
id: tm
font: pinText.font
elide: Text.ElideRight
elideWidth: pinText.width
text: qsTr("%Ln pinned message(s)", "", root.pinnedMessagesCount)
}
objectName: "StatusChatInfo_pinText"
Layout.fillWidth: true
text: tm.elidedText !== tm.text ? root.pinnedMessagesCount : tm.text
font.pixelSize: 12
font.underline: pinCountSensor.containsMouse
visible: root.pinnedMessagesCount
color: pinCountSensor.containsMouse ? Theme.palette.directColor1 : Theme.palette.baseColor1
MouseArea {
objectName: "pinMessagesCounterSensor"
id: pinCountSensor
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.pinnedMessagesCountClicked(mouse)
}
}
Item { Layout.fillWidth: true }
}
}
}
+15 -9
View File
@@ -8,16 +8,20 @@ import StatusQ.Components 0.1
CheckBox {
id: statusCheckBox
id: root
property bool leftSide: true
indicator: Rectangle {
anchors.left: root.leftSide? parent.left : undefined
anchors.right: !root.leftSide? parent.right : undefined
implicitWidth: 18
implicitHeight: 18
x: statusCheckBox.leftPadding
x: !root.leftSide? root.rightPadding : root.leftPadding
y: parent.height / 2 - height / 2
radius: 2
color: (statusCheckBox.down || statusCheckBox.checked) ? Theme.palette.primaryColor1
: Theme.palette.directColor8
color: (root.down || root.checked) ? Theme.palette.primaryColor1
: Theme.palette.directColor8
StatusIcon {
icon: "checkbox"
@@ -26,19 +30,21 @@ CheckBox {
anchors.centerIn: parent
anchors.horizontalCenterOffset: 1
color: Theme.palette.white
visible: statusCheckBox.down || statusCheckBox.checked
visible: root.down || root.checked
}
}
contentItem: StatusBaseText {
text: statusCheckBox.text
font.pixelSize: statusCheckBox.font.pixelSize
text: root.text
font.pixelSize: root.font.pixelSize
opacity: enabled ? 1.0 : 0.3
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
width: parent.width
color: Theme.palette.directColor1
leftPadding: !!statusCheckBox.text ? statusCheckBox.indicator.width + statusCheckBox.spacing
: statusCheckBox.indicator.width
leftPadding: root.leftSide? (!!root.text ? root.indicator.width + root.spacing
: root.indicator.width) : 0
rightPadding: !root.leftSide? (!!root.text ? root.indicator.width + root.spacing
: root.indicator.width) : 0
}
}
@@ -8,11 +8,13 @@ RadioButton {
property string radioButtonColor: ""
property string selectionColor: StatusColors.colors['white']
property int diameter: 48
property int selectorDiameter: 20
property int diameter: 44
property int selectorDiameter: 16
implicitWidth: 48
implicitHeight: 48
spacing: 0
implicitWidth: 44
implicitHeight: 44
indicator: Rectangle {
implicitWidth: control.diameter
@@ -21,13 +23,13 @@ RadioButton {
color: radioButtonColor
Rectangle {
anchors.centerIn: parent
width: control.selectorDiameter
height: control.selectorDiameter
visible: control.checked
radius: width/2
color: selectionColor
border.color: StatusColors.colors['grey3']
visible: control.checked
anchors.centerIn: parent
}
}
}
@@ -36,6 +36,7 @@ Column {
StatusBaseText {
id: title
width: parent.width
verticalAlignment: Text.AlignVCenter
font.pixelSize: 13
color: Theme.palette.baseColor1
@@ -46,7 +47,9 @@ Column {
columns: 6
rowSpacing: 16
columnSpacing: 32
Repeater {
objectName: "statusColorRepeater"
model: root.model
delegate: StatusColorRadioButton {
implicitWidth: root.diameter
+10 -1
View File
@@ -24,6 +24,8 @@ Item {
property alias label: labelItem.text
property alias validationError: validationErrorItem.text
property string popupContentItemObjectName: ""
implicitWidth: layout.implicitWidth
implicitHeight: layout.implicitHeight
@@ -74,6 +76,13 @@ Item {
: comboBox.hovered
? Theme.palette.primaryColor2
: "transparent"
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.NoButton
enabled: root.enabled
}
}
contentItem: StatusBaseText {
@@ -123,7 +132,7 @@ Item {
contentItem: StatusListView {
id: listView
objectName: root.popupContentItemObjectName
implicitWidth: contentWidth
implicitHeight: contentHeight
+5 -9
View File
@@ -3,19 +3,15 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
StatusBaseButton {
id: statusFlatButton
normalColor: "transparent"
hoverColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor3
: Theme.palette.dangerColor3
disaledColor: "transparent"
hoverColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor3
: Theme.palette.dangerColor3
disabledColor: "transparent"
textColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor1
: Theme.palette.dangerColor1
disabledTextColor: Theme.palette.baseColor1
border.color: type === StatusBaseButton.Type.Normal || hovered ? "transparent"
: Theme.palette.baseColor2
rightPadding: icon.name !== "" ? 18 : defaultRightPadding
leftPadding: icon.name !== "" ? 14 : defaultLeftPadding
borderColor: (type === StatusBaseButton.Type.Normal || hovered) && !loading ? "transparent"
: Theme.palette.baseColor2
}
@@ -7,7 +7,7 @@ import StatusQ.Components 0.1
Rectangle {
id: statusFlatRoundButton
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings icon: StatusAssetSettings {
width: 23
height: 23
rotation: 0
@@ -113,12 +113,11 @@ Row {
implicitHeight: 32
topPadding: 8
bottomPadding: 0
defaultLeftPadding: 4
defaultRightPadding: 4
horizontalPadding: 4
hoverColor: Theme.palette.statusFloatingButtonHighlight
normalColor: Theme.palette.baseColor3
icon.name: "more"
icon.background.color: "transparent"
asset.name: "more"
asset.bgColor: "transparent"
onClicked: popupMenu.popup(parent.x, y + height + 8)
}
}
+7 -8
View File
@@ -26,14 +26,13 @@ TabButton {
id: identicon
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
image.source: statusIconTabButton.icon.source
image.width: 28
image.height: 28
icon.height: statusIconTabButton.icon.height
icon.width: statusIconTabButton.icon.width
icon.name: statusIconTabButton.icon.name
icon.color: (statusIconTabButton.hovered || highlighted || statusIconTabButton.checked) ? Theme.palette.primaryColor1 : statusIconTabButton.icon.color
icon.isLetterIdenticon: statusIconTabButton.name !== "" && !statusIconTabButton.icon.source.toString()
asset.isImage: (statusIconTabButton.icon.source.toString() !== "")
asset.name: asset.isImage ?
statusIconTabButton.icon.source : statusIconTabButton.icon.name
asset.width: asset.isImage ? 28 : statusIconTabButton.icon.width
asset.height: asset.isImage ? 28 : statusIconTabButton.icon.height
asset.color: (statusIconTabButton.hovered || highlighted || statusIconTabButton.checked) ? Theme.palette.primaryColor1 : statusIconTabButton.icon.color
asset.isLetterIdenticon: statusIconTabButton.name !== "" && !asset.isImage
name: statusIconTabButton.name
}
}
@@ -64,6 +64,7 @@ AbstractButton {
width: root.icon.width
height: root.icon.height
rotation: root.iconRotation
visible: status == Image.Ready
}
StatusBaseText {
Layout.alignment: Qt.AlignVCenter
+7 -2
View File
@@ -48,6 +48,7 @@ Item {
This property holds a reference to the TextEdit's valid property.
*/
property alias valid: statusBaseInput.valid
/*!
\qmlproperty alias StatusInput::pending
This property holds a reference to the TextEdit's pending property.
@@ -243,7 +244,7 @@ Item {
This function resets the text input validation and text.
*/
function reset() {
statusBaseInput.valid = true
statusBaseInput.valid = false
statusBaseInput.pristine = true
statusBaseInput.text = ""
root.errorMessage = ""
@@ -276,8 +277,12 @@ Item {
valid: result
}
}
result.errorMessage = validator.errorMessage
errors[validator.name] = result
// the only way to trigger bindings for var property
errors = errors
result.errorMessage = validator.errorMessage
statusBaseInput.valid = statusBaseInput.valid && false
}
}
+10 -4
View File
@@ -15,11 +15,10 @@ ItemDelegate {
icon.width: 16
icon.height: 16
contentItem: RowLayout {
contentItem: RowLayout {
spacing: root.spacing
StatusIcon {
id: iconItem
Layout.alignment: Qt.AlignVCenter
visible: !!icon
icon: root.icon.name
@@ -43,7 +42,14 @@ ItemDelegate {
background: Rectangle {
color: root.highlighted
? Theme.palette.statusPopupMenu.hoverBackgroundColor
: "transparent"
? Theme.palette.statusPopupMenu.hoverBackgroundColor
: "transparent"
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.NoButton
enabled: root.enabled
}
}
}
+25 -9
View File
@@ -39,10 +39,10 @@ Rectangle {
id: root
/*!
\qmlproperty string StatusItemPicker::image
This property holds the image settings information.
\qmlproperty string StatusItemPicker::asset
This property holds the asset(image/icon) settings information.
*/
property StatusImageSettings image
property StatusAssetSettings asset
/*!
\qmlproperty string StatusItemPicker::name
@@ -50,6 +50,12 @@ Rectangle {
*/
property string name
/*!
\qmlproperty int StatusItemPicker::namePixelSize
This property holds pixel size of the name to be displayed.
*/
property int namePixelSize: 15
/*!
\qmlproperty string StatusItemPicker::shortName
This property holds the secondary text or short name to be displayed.
@@ -81,6 +87,15 @@ Rectangle {
*/
property ButtonGroup radioGroup
/*!
\qmlproperty int StatusItemPicker::radioButtonSize
This property holds size type of the radio button.
Possible values are:
- Small
- Large (default size)
*/
property int radioButtonSize: StatusRadioButton.Size.Large
/*!
\qmlsignal StatusItemPicker::checkedChanged(bool checked)
This signal is emitted when the item is selected by pressing the radiobutton or the checkbox.
@@ -95,7 +110,7 @@ Rectangle {
QtObject {
id: d
property int minShortNameWidth: 50
readonly property int minShortNameWidth: root.shortName ? 50 : 0
function availableTextWidth() {
return root.width - imageItem.width - row.spacing - shortNameItem.anchors.rightMargin - selector.width - selector.anchors.rightMargin - 24/*Margin between both texts*/
@@ -112,10 +127,10 @@ Rectangle {
StatusIcon {
id: imageItem
anchors.verticalCenter: parent.verticalCenter
source: root.image.source ? root.image.source : ""
width: root.image.width
height: root.image.height
visible: root.image.source !== undefined
source: root.asset && root.asset.name ? root.asset.name : ""
width: root.asset ? root.asset.width : 0
height: root.asset ? root.asset.height : 0
visible: root.asset && root.asset.name !== undefined
}
StatusBaseText {
@@ -126,7 +141,7 @@ Rectangle {
dummyNameItem.width
text: root.name
color: Theme.palette.directColor1
font.pixelSize: 15
font.pixelSize: root.namePixelSize
clip: true
elide: Text.ElideRight
}
@@ -167,6 +182,7 @@ Rectangle {
Component {
id: radioBtn
StatusRadioButton {
size: root.radioButtonSize
ButtonGroup.group: root.radioGroup
checked: root.selected
onCheckedChanged: {
@@ -0,0 +1,108 @@
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
import StatusQ.Controls 0.1
/*!
\qmltype StatusPasswordInput
\inherits Item
\inqmlmodule StatusQ.Controls
\since StatusQ.Controls 0.1
\brief The StatusPasswordInput control provides a generic user password input with an option to display signing phrase
Example of how to use it:
\qml
StatusPasswordInput {
signingPhrase: "orange hello cygnet"
placeholderText: qsTr("Password")
}
\endqml
For a list of available components see StatusQ.
*/
TextField {
id: root
/*!
\qmlproperty string StatusPasswordInput::signingPhrase
This property sets the signingPhrase of TextField field and signing seed phrase.
*/
property string signingPhrase: ""
QtObject {
id: d
readonly property int inputTextPadding: 16
readonly property int pixelSize: 15
readonly property int radius: 8
readonly property int signingPhrasePadding: 8
readonly property int signingPhraseWordPadding: 8
readonly property int signingPhraseWordsSpacing: 8
readonly property int signingPhraseWordsHeight: 30
}
leftPadding: d.inputTextPadding
rightPadding: root.signingPhrase !== ""?
phrase.width + phrase.anchors.leftMargin + phrase.anchors.rightMargin :
d.inputTextPadding
verticalAlignment: Text.AlignVCenter
implicitWidth: 480
implicitHeight: 44
placeholderTextColor: Theme.palette.baseColor1
echoMode: TextInput.Password
font.pixelSize: d.pixelSize
font.family: Theme.palette.baseFont.name
color: Theme.palette.directColor1
selectionColor: Theme.palette.primaryColor2
selectedTextColor: Theme.palette.directColor1
background: Rectangle {
id: inputRectangle
anchors.fill: parent
color: Theme.palette.baseColor5
radius: d.radius
border.width: root.focus ? 1 : 0
border.color: {
if (root.focus) {
return Theme.palette.primaryColor1
}
return "transparent"
}
}
RowLayout {
id: phrase
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: d.signingPhrasePadding
anchors.rightMargin: d.signingPhrasePadding
spacing: d.signingPhraseWordsSpacing
visible: root.signingPhrase !== ""
Repeater {
model: root.signingPhrase.split(" ")
delegate: Rectangle {
width: signingPhraseWord.implicitWidth + 2 * d.signingPhraseWordPadding
height: d.signingPhraseWordsHeight
color: Theme.palette.indirectColor1
radius: d.radius
StatusBaseText {
id: signingPhraseWord
anchors.centerIn: parent
color: Theme.palette.primaryColor1
font.pixelSize: root.font.pixelSize
font.family: root.font.family
text: modelData
}
}
}
}
}
+7 -7
View File
@@ -14,13 +14,13 @@ Button {
property var type: StatusPickerButton.Type.Next
/*!
\qmlproperty StatusImageSettings StatusPickerButton::image
\qmlproperty StatusAssetSettings StatusPickerButton::image
This property holds the image settings information.
*/
property StatusImageSettings image: StatusImageSettings {
property StatusAssetSettings asset: StatusAssetSettings {
width: 20
height: 20
isIdenticon: false
imgIsIdenticon: false
}
enum Type {
@@ -51,11 +51,11 @@ Button {
height: root.icon.height
}
StatusRoundedImage {
visible: root.image.source.toString() !== ""
visible: root.asset.name.toString() !== ""
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: root.image.width
Layout.preferredHeight: root.image.height
image.source: root.image.source
Layout.preferredWidth: root.asset.width
Layout.preferredHeight: root.asset.height
image.source: root.asset.name
}
StatusBaseText {
Layout.fillWidth: true
+69 -45
View File
@@ -77,6 +77,20 @@ Item {
*/
property int circleDiameter: 16
/*!
\qmlproperty int StatusPinInput::additionalSpacingOnEveryNItems
This property allows you to customize spacing among every N-th pin. By default the value is 0, which
means only regular `circleSpacing` will be applied, meaning that spacing among all pins will be the same.
*/
property int additionalSpacingOnEveryNItems: 0
/*!
\qmlproperty int StatusPinInput::additionalSpacing
This property allows you to customize spacing between pin circles on every `additionalSpacingOnEveryNItems` items.
This additionalSpacing won't be applied if `additionalSpacingOnEveryNItems` is set to `0`.
*/
property int additionalSpacing: 0
QtObject {
id: d
property int currentPinIndex: 0
@@ -151,8 +165,8 @@ Item {
}
}
width: (root.circleDiameter + root.circleSpacing) * root.pinLen - root.circleSpacing
height: root.circleDiameter
implicitWidth: childrenRect.width
implicitHeight: childrenRect.height
// Pin input data management object:
TextInput {
@@ -196,56 +210,66 @@ Item {
id: repeater
model: root.pinLen
Rectangle {
id: background
Item {
id: container
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
height: root.circleDiameter
width: {
if (index > 0 && index < root.pinLen-1 && (index+1) % root.additionalSpacingOnEveryNItems == 0) {
return root.circleDiameter + root.additionalSpacing
}
return root.circleDiameter
}
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}
}
]
Rectangle {
width: root.circleDiameter
height: width
color: Theme.palette.primaryColor2
radius: 0.5 * width
// Animation on transitions
Behavior on width { NumberAnimation { duration: 200 } }
Rectangle {
id: inner
state: container.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 "cursor" blinking
SequentialAnimation {
id: blinkingAnimation
loops: Animation.Infinite
running: visible
NumberAnimation { target: inner; property: "opacity"; to: 0; duration: 800;}
NumberAnimation { target: inner; property: "opacity"; to: 1; duration: 800;}
}
}
// Animation on transitions
Behavior on width { NumberAnimation { duration: 200 } }
// Animation on "cursor" blinking
SequentialAnimation {
id: blinkingAnimation
loops: Animation.Infinite
running: visible
NumberAnimation { target: inner; property: "opacity"; to: 0; duration: 800;}
NumberAnimation { target: inner; property: "opacity"; to: 1; duration: 800;}
}
}
}
}
}
}
+30 -21
View File
@@ -1,41 +1,50 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQml 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
RadioButton {
id: statusRadioButton
id: root
width: indicator.implicitWidth
/*!
\qmlproperty int StatusRadioButton::size
This property holds size type of the radio button.
Possible values are:
- Small
- Large (default size)
*/
property int size: StatusRadioButton.Size.Large
enum Size {
Small,
Large
}
indicator: Rectangle {
implicitWidth: 20
implicitHeight: 20
x: 0
y: 6
radius: 10
color: statusRadioButton.checked ? Theme.palette.primaryColor1
: Theme.palette.directColor8
implicitWidth: root.size === StatusRadioButton.Size.Large ? 20 : 14
implicitHeight: root.size === StatusRadioButton.Size.Large ? 20 : 14
x: root.text ? (root.mirrored ? root.width - width - root.rightPadding : root.leftPadding) : root.leftPadding + (root.availableWidth - width) / 2
y: root.topPadding + (root.availableHeight - height) / 2
radius: width / 2
color: root.checked ? Theme.palette.primaryColor1 : Theme.palette.directColor8
Rectangle {
width: 12
height: 12
radius: 6
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: statusRadioButton.checked ? Theme.palette.white : "transparent"
visible: statusRadioButton.checked
width: root.size === StatusRadioButton.Size.Large ? 12 : 8
height: root.size === StatusRadioButton.Size.Large ? 12 : 8
radius: width / 2
anchors.centerIn: parent
color: Theme.palette.white
visible: root.checked
}
}
contentItem: StatusBaseText {
text: statusRadioButton.text
font: root.font
text: root.text
color: Theme.palette.directColor1
verticalAlignment: Text.AlignVCenter
leftPadding: !!statusRadioButton.text ? statusRadioButton.indicator.width + statusRadioButton.spacing
: statusRadioButton.indicator.width
leftPadding: root.indicator && !root.mirrored ? root.indicator.width + root.spacing : 0
rightPadding: root.indicator && root.mirrored ? root.indicator.width + root.spacing : 0
}
}
+1 -1
View File
@@ -7,7 +7,7 @@ import StatusQ.Components 0.1
Rectangle {
id: statusRoundButton
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings icon: StatusAssetSettings {
width: 23
height: 23
rotation: 0
+1 -1
View File
@@ -47,7 +47,7 @@ T.ScrollBar {
contentItem: Rectangle {
color: Theme.palette.primaryColor2
opacity: enabled && (root.hovered || root.active) ? 1.0 : 0.0
opacity: enabled && (root.hovered || root.active || (root.policy === T.ScrollBar.AlwaysOn)) ? 1.0 : 0.0
radius: Math.min(width, height) / 2
Behavior on opacity { NumberAnimation { duration: 100 } }
+3 -2
View File
@@ -23,6 +23,7 @@ Item {
property var model
property alias selectMenu: selectMenu
property color bgColorHover: bgColor
// TODO: Fix the indirect handling of children
property alias selectedItemComponent: selectedItemContainer.children
property bool caretVisible: true
property int caretRightMargin: 16
@@ -54,7 +55,7 @@ Item {
Rectangle {
property bool hovered: false
id: inputRectangle
height: 56
height: selectedItemContainer.implicitHeight
color: hovered ? bgColorHover : bgColor
radius: 8
anchors.top: root.hasLabel ? inputLabel.bottom : parent.top
@@ -64,7 +65,7 @@ Item {
border.width: !!validationError ? 1 : 0
border.color: Theme.palette.dangerColor1
Item {
GridLayout {
id: selectedItemContainer
anchors.fill: parent
}
+3 -13
View File
@@ -5,6 +5,7 @@ import QtQuick.Controls 2.14 as QC
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
Item {
@@ -57,18 +58,7 @@ Item {
contentHeight: edit.paintedHeight
boundsBehavior: Flickable.StopAtBounds
QC.ScrollBar.vertical: QC.ScrollBar { interactive: multiline; enabled: multiline }
function ensureVisible(r) {
if (width-contentX >= r.x) {
contentX = 0;
}
else if (contentX+width <= r.x+r.width) {
contentX = r.x+r.width-width;
}
if (contentY >= r.y)
contentY = r.y;
else if (contentY+height <= r.y+r.height)
contentY = r.y+r.height-height;
}
TextEdit {
id: edit
width: flick.width
@@ -83,7 +73,7 @@ Item {
font.family: Theme.palette.baseFont.name
color: Theme.palette.directColor1
textFormat: Text.RichText
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
onCursorRectangleChanged: Utils.ensureVisible(flick, cursorRectangle)
wrapMode: statusSelectableText.multiline ? Text.WrapAtWordBoundaryOrAnywhere : TextEdit.NoWrap
Keys.forwardTo: [statusSelectableText]
@@ -6,7 +6,7 @@ import StatusQ.Core.Theme 0.1
Item {
id: root
property StatusIconSettings icon: StatusIconSettings {
property StatusAssetSettings icon: StatusAssetSettings {
width: 24
height: 24
name: ""
+6 -2
View File
@@ -25,17 +25,21 @@ import StatusQ.Components 0.1
TabButton {
id: root
property alias badge: statusBadge
readonly property alias badge: statusBadge
leftPadding: 12
rightPadding: 12
background: Item { }
contentItem: Item {
contentItem: MouseArea {
implicitWidth: contentItemGrid.implicitWidth
implicitHeight: contentItemGrid.implicitHeight + 15
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.NoButton
enabled: root.enabled
RowLayout {
id: contentItemGrid
+1 -2
View File
@@ -18,7 +18,7 @@ ToolTip {
property int offset: 0
property alias arrow: arrow
implicitWidth: Math.min(maxWidth, textContent.implicitWidth + 16)
implicitWidth: Math.min(maxWidth, contentItem.implicitWidth + 16)
leftPadding: 8
rightPadding: 8
topPadding: 8
@@ -65,7 +65,6 @@ ToolTip {
}
}
contentItem: StatusBaseText {
id: textContent
text: statusToolTip.text
color: Theme.palette.white
wrapMode: Text.WordWrap
+1
View File
@@ -51,3 +51,4 @@ StatusComboBox 0.1 StatusComboBox.qml
StatusItemDelegate 0.1 StatusItemDelegate.qml
StatusTextArea 0.1 StatusTextArea.qml
StatusBackButton 0.1 StatusBackButton.qml
StatusPasswordInput 0.1 StatusPasswordInput.qml

Some files were not shown because too many files have changed in this diff Show More