1. Added icon disabledColor property under StatusIconSettings
2. Added Tertiary and Quaternary type to accomodate hovered behavior needed in many buttons
3. Added a missing gif icon.
This is a select component to pick from various supplied colors.
Usage:
```qml
import StatusQ.Controls 0.1
StatusColorSelector {
model: ["red", "blue", "green"]
}
```
Closes#444
This introduces a `StatusAddress` component which renders an address
and can be made `expandable` by applying a `width`:
```qml
import StatusQ.Components 0.1
// Simple case
StatusAddress {
text: "0x9ce0056c5fc6bb9459a4dcfa35eaad8c1fee5ce9"
}
// Expandable case
Item {
width: 200
height: childrenRect.height
StatusAddress {
text: "0x9ce0056c5fc6bb9459a4dcfa35eaad8c1fee5ce9"
expandable: true
width: parent.width
}
}
```
Closes#430
This introduces a new `StatusSelect` component which is a select form control.
The `model` property can be used to apply a `ListModel` for dynamic data.
To give users full control over what the menu items look like, `StatusSelect`
exposes a `selectMenu.delegate` property.
Most of the time this should be a `StatusMenuItemDelegate` to get access to the
comple `MenuItem` component (remember that `StatusMenuItem` is merely an `Action`
type).
`StatusMenuItemDelegate` derives most of its behaviour by its applied `action`,
so the easiest way to construct a dynamic select with StatusQ menu item look and feel
is a combination of `StatusMenuItemDelegate` and `StatusMenuItem` as shown below.
Further more, because `StatusSelect` can't know what the `delegate` is going to look like
it also can't decide what data goes into a `selectedItem`. Therefore, it offers another API,
the `selectedItemComponent` which can be any component. This component can then be accessed
by menu item actions to set corresponding properties.
Usage:
```qml
import StatusQ.Controls 0.1
StatusSelect {
label: "Some label"
model: ListModel {
ListElement {
name: "Pascal"
}
ListElement {
name: "Khushboo"
}
ListElement {
name: "Alexandra"
}
ListElement {
name: "Eric"
}
}
selectMenu.delegate: StatusMenuItemDelegate {
statusPopupMenu: select
action: StatusMenuItem {
iconSettings.name: "filled-account"
text: name
onTriggered: {
selectedItem.text = name
}
}
}
selectedItemComponent: Item {
id: selectedItem
anchors.fill: parent
property string text: ""
StatusBaseText {
text: selectedItem.text
anchors.centerIn: parent
color: Theme.palette.directColor1
}
}
}
```
Closes#436
This extracts the `MenuItem` delegate used in `StatusPopupMenu` into its
own component so it can be easily reused for cases where simply supplying the
popup menu with `StatusMenuItem` (which is of type `Action`) isn't enough.
Ideally, the `StatusMenuItemDelegate` would be called `StatusMenuItem` but that
would be a breaking change.
Usage:
```qml
StatusPopupMenu {
delegate: StatusMenuItemDelegate {
...
}
}
Category `opened` state is tracked and restored on model change.
Previously, when the model data for categories and channels was changed, all unexpanded, or collapsed categories would automatically expand. This was due to the default state of the category `opened` property being restored (which was set to true) when the model data changed.
With this change in place, the opened state of each category is tracked in the parent component (`StatusChatListAndCategories`), and on each model change, the opened state is restored.
NOTE: it was tempting to the put the changes inside of the `StatusChatListCategory` component, however this would not work as the component is used as a delegate, and all state is wiped on each model change.
Ever since we've moved to `DelegateModel` which is passed to the `Repeater`
which was previously aliased as `chatListItems`, we no longer get access to the
`model.itemAt` method. This is because `DelegateModel` doesn't have such a method.
So in order to restore that access, we have to expose `Repeater` additionally.
The reason this method is needed, is so that apps like Status Desktop can update
individual chat list items based on `Connection` events
Allows asynchronous validation, with the ability to track the validated value for use in the StatusInput as a value that is separate from the entered text.
Async operations are debounced internally to the StatusAsyncValidator.
- `validate`: the input value to this function is the value sent to `asyncComplete`, which must be called by the validator. Return true when the value from the async operation is valid.
- `asyncComplete`: signal to be called by the validator after the async operation has completed. It should contain the value returned by the async operation that should be validated in `validate`.
- `validatedValue`: This is the valid value returned from the async operation. It it tracked separately so that the input text on the `StatusInput` can remain as entered by the user. Use this property and the `onValidatedValueChanged` signal handler for the “real” value to be used by other components.
Closes#395
List items' mouse area was also triggered when chevron
(sub menu) button was clicked so it was unsetting the
opened variable which is responsible for opening/closing
the chats list.
This property enables users to load any component into the input field.
This is useful for rendering a "clearable" icon button, simple icons or
even more complex buttons.
Usage:
```qml
StatusBaseInput {
...
component: StatusIcon {
name: "cancel"
color: Theme.palette.dangerColor1
width: 16
}
}
```
The `clearable` property of `StatusBaseInput` also renders and icon button
on the right hand side. With this new feature, `clearable` is just a short-hand
for:
```qml
StatusBaseInput {
...
component: StatusFlatRoundButton {
visible: edit.text.length != 0 &&
statusBaseInput.clearable &&
!statusBaseInput.multiline &&
edit.activeFocus
type: StatusFlatRoundButton.Type.Secondary
width: 24
height: 24
icon.name: "clear"
icon.width: 16
icon.height: 16
icon.color: Theme.palette.baseColor1
onClicked: {
edit.clear()
}
}
}
```
Closes#380
This allows users to configure how validation is run. There are two modes:
1. `ValidationMode.OnlyWhenDirty`
2. `ValidationMode.Always`
By default, validation happens when the inputs value changes, or on
initial `Component.onCompleted` event. The first mode allows for not
performing validation when the input field is blank and validation.
isn't necessary (yet).
Validators can now define a default `errorMessage` like so:
```qml
StatusValidator {
...
errorMessage: "..."
}
```
Because there's no access to runtime validation errors, `errorMessage` have to
be static. However, if applications wish to provide their own `errorMessage`
they can still override it and make it dynamic:
```qml
SomeValidator {
...
errorMessage: input.errors.someValidator ? "Whoopsie" : ""
}
```
Renamed StatusExpandableSettingsItem to StatusExpandableItem.
Added support for dofferent types of styles for the item.
Type Primary: Relates to Settings Design
Type Secondary: Relates to Collectibles Design
Type Tertiary: Relates to the Collectibles detailed view design
BREAKING CHANGE: Renamed and expanded features of the StatusExpandableSettingsItem to StatusExpandableItem
This is used to enforce focus on the search input when the popup
is opened. In fact users decide to override the search popup's
`onOpened` handler, they still get access to this API to make use of it.
This margin shows because of `handle` width incuded in `SplitView` width. Handle have `Component` type and can't accessable for getting sizes. I add `magic constant` as hotfix.
Closes: #307
Due to design updates in AddAccount modal, updates are
needed in StatusBaseInput and StatusInput
* Added the possibility of having the icon on the right
side
* Added secondaryLabel for title
* Added examples in StatusInputPage
Closes#383
This introduces a new API to allow users to provide a function that formats
timestamps in the search results.
```qml
StatusSearchPopup {
formatTimestampFn: function (ts) {
return // formatted ts
}
}
```
Closes#363
Turns out the icons used in the navigation bar of the application actually
are designed to be bigger than the usual icons.
We can't just use the original source and scale them up in QML because that
will impact the stroke width of the SVGs as well, hence we need to introduce
a special set of icons that are design bigger but presever the feature ratios.
This adds a new `value` property to the component to set label for a
selected value and also rendering a chevron as an indicator that the list
item becomes clickable.
This changes the share of the model expected to render search results.
BREAKING CHANGE:
The model has changed in the following way:
- `image` field added
- `color` field added
- `badgeIdenticonColor` field renamed to `badgeIconColor`
- `isLetterIdenticon` field renamed to `badgeIsLetterIdenticon`
There are now two new properties in `StatusModalHeaderSettings`:
- `titleElide`
- `subTitleElide`
These can be used to configure the `elide` property of both header titles.
The default values for both of them is `Text.ElideRight`.
Closes#353
This commit add elide flags to text in title and subtitle and add flexibility to width. Now compoents use next rules:
1. If width is set - text should be elided when implicit text width is more than root object width
2. Component grows if width is not set based on inner elements natural sizes
Closes: #335 and #338
There was an explicit `width` introduced on `statusListItemTitle`, most likely
to make room for it when `titleAsideText` is supplied.
This unfortunately causes the title get a very small width, resulting in broken
UI.
Since we can assume that there should be enough space for the titleAsideText
when it's used, we probably don't have to calculate a fixed width for the title
in the first place.
This commit therefore removes that explicit setting.
* feat(StatusChatListAndCategories): add drag and drop support for categories
This adds support for dragging and dropping chat list categories.
To persist reorder of chat categories, the new `onChatListCategoryReordered`
signal can be leveraged.
Drag and drop of categories is turned off by default and needs to
be turned on using `draggableCategories: true`.
Closes#227
* feat(Status.Core): introduce Utils namespace
This adds a new package for utility related things.
This fixes a bug that was introduced in 01da750899 with a breaking change
where `StatusChatListCategoryItem`'s `clicked` signal would no longer receive
a `mouse` event object.
The reason this is happening is because we've introduced a new `clicked` signal
on `StatusListItem`. The idea was to rely on that within `StatusChatListCategoryItem`,
however, we didn't take into account that the new `clicked` signal in `StatusListItem`
doesn't emit a `mouse` event object.
To fix this issue could either reintroduce the custom `clicked` handler on
`StatusChatListCategoryItem`, or listen to the original `sensor.onClicked` and
`onTitleClicked` signals exposed by `StatusListItem` instead, ensuring the required
`mouse` event data exists.
Fixes#333
This implements drag and drop capabilities of chat items within a `StatusChatList`.
The commit introduces a `DelegateModal` to visually reorder chat items
when they're being dragged and dropped onto a `DropArea`.
To persist the new order of chat items, various signals have been introduced to chat
list related components:
```qml
StatusChatList {
onChatItemReordered: function (id, from, to) {
// ...
}
}
StatusChatListAndCategories {
onChatItemReordered: function (categoryId, chatId, from, to) {
// ...
}
}
```
There's no such API on the `StatusChatListCategory` type because that one already
exposes its underlying `StatusChatList` via `chatList`, which makes the signal available.
Dragging and dropping chat items is disabled by default and needs to be turned on
using the `draggableItems` property:
```qml
StatusChatList {
draggableItems: true
...
}
```
These properties can be used to determine whether a user has either
interacted with the form control, or changed its value.
It's also used in initial validation to ensure validation is done but
visually, form controls stay untouched.
Closes#327
A single `signal itemClicked(string firstLevelItemValue, string secondLevelItemValue)`
with parameters referring to the first level and second level item is exposed
and replaced multiple signals we had before for the same purpose.
A click on the item's title or whole item emits appropriate `titleClicked` or
`clicked` signal with `titleId` or `itemId` value respectively. `titleId` and
`itemId` may or may not defer from their display values, it's up to logic which
is applied.
This is introduced because of need of the issue-2934.
There's a new `validators` property that can be used to add validators to `StatusInput` instances, which are executed in the same order:
```qml
StatusInput {
text: "Some value"
validators: [...]
}
```
For convenience StatusQ provides some common validation methods, such as `StatusMinLengthValidator`, StatusMaxLengthValidator` and could be extended to other (e.g. email validation etc):
```qml
StatusInput {
text: "Some value"
validators: [
StatusMinLengthValidator { minLength: 3 }
]
}
```
Validators are executed every time the text of the input changes. They are executed in the same order they have been applied, which enables users to create cascading conditions like "First make sure the value is at least 3 characters long, then make sure it matches a certain pattern".
When a validation fails, it sets the validity of the input (`valid: false`) accordingly and optionally exposes additional error information on `StatusInput.errors`:
```qml
StatusInput {
text: "Fo"
onTextChanged: {
if (errors) {
/**
* errors now has the following structure:
* errors: {
* minLength: { minValue: 3, actual: ... }
* }
* Also, `StatusInput` is now `valid = false`
**/
errorMesssage = "Expected " + errors.minLenght.minValue + " but got: "+ errors.minLength.actual; // i18n'able
}
}
validators: [
StatusMinLengthValidator { minLength: 3 }
]
}
```
There can be any number of error objects on the `errors` property, depending on who many validators have been run that failed validation.
Custom validators can be implemented by introducing a new `StatusValidator` type that has to implement a `validate()` function and defines the validators name. The `validate()` function has to return either `true` or `false` depending on whether the value is valid.
Alternatively, the function can return an error object which gets exposed on the underlying input's `errors` property, at which point it's considered invalid as well.
Here's a simple custom validator:
```qml
// HelloValidator.qml
import StatusQ.Controls.Validators 0.1
StatusValidator {
property string name: "hello"
validate: function (value) { // `value` is the `text` value of the underlying control
return value === "hello"
}
}
```
Applying this validators would look like this:
```qml
StatusInput {
text: "Some value"
validators: [
HelloValidator {}
]
onTextChanged: {
if (errors.hello) {
errorMessage = "Doesn't say hello!"
}
}
}
```
Alternatively, validators can return error objects to provide more information about what went wrong. Here's the implementation of the `StatusMinLengthValidator` as an example:
```qml
StatusValidator {
property int minLength: 0
name: "minLength"
validate: function (value) {
return value.length >= minLength ? true : {
min: minLength,
actual: value.length
}
}
}
```
Because validators as components, they can hold any custom properties they need to be configured.
There has been concern that, with this API, error messages need to be potentially defined in multiple places, given that there could be multiple instances of any validator. This is easily solved by having a centralized function figure out what the error message is, given a certain error object:
```qml
StatusInput {
validators: [
StatusMinLengthValidator { minLength: 3 }
]
onTextChanged: {
if (errors) {
errorMessage = getErrorMessage(errors) // this function is provided by global or elsewhere
}
}
}
```
Closes#298
Prior to this commit, setting `charLimit` on `StatusInput` would only have a visual effect
(rendering the char limit), however it wouldn't actually enforce this limit.
This was by intended behaviour, because we wanted to leave some room
for possible validators to kick in (for example a max length validator).
If however the char limit is enforce, such a validator would never kick in.
There seems to be consensus in the team that the limit should be enforced though.
This commit enables that.
The menu has a CloseOnReleaseOutside policy and so it
was closing and immediately re-opened when the kebab icon
was clicked since it's outside the menu area and also was
calling the popup function of the menu. Added dummy bool
property to detect whether the menu is already closed and
not open it again
Closes#308
There's some usage specific color being added to the chat input (which doesn't live in
StatusQ yet). To make sure we don't lose that change, I'm adding the new
colors to StatusQ theming system and have Status Desktop use it for the time being
until `StatusChatInput` is moved to StatusQ anyways.
This extends the popup menu to accept image or icon configurations a la `StatusIconSettings`
and `StatusImageSettings` in menu items, as well as nested menus.
Usage:
```qml
StatusPopupMenu {
StatusMenuItem {
text: "Custom Image icon"
image.source: // image source
}
StatusMenuItem {
text: "Custom identicon icon"
image.source: // identicon source
image.isIdenticon: true
}
StatusMenuItem {
text: "Custom letter identicon"
iconSettings.isLetterIdenticon: true
iconSettings.background.color: "red"
}
}
```
Few things to note:
- Because `StatusMenuItem` is an `Action` type, we can't extend its `icon` property,
so we have to introduce our own (`iconSettings`) which can be of type `StatusIconSettings`
- Where possible, `StatusPopupMenu` will prefer `iconSettings.[...]` over `icon.[...]`,
which means, both would work: `icon.name` and `iconSettings.name`.
This is for consistency's sake. Consumers can switch completely to `iconSettings` if desired.
- When `isLetterIdenticon` is true, `iconSettings.background.color` must be set, similar
to how it work in any other StatusQ component that makes use of this configuration type.
Closes#263