2021-09-09 12:18:22 +03:00
|
|
|
/*
|
|
|
|
* Copyright (C) by Felix Weilbach <felix.weilbach@nextcloud.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
import QtQuick 2.6
|
|
|
|
import QtQuick.Layouts 1.15
|
|
|
|
import QtQuick.Controls 2.15
|
|
|
|
import QtQuick.Window 2.15
|
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
import com.nextcloud.desktopclient 1.0 as NC
|
2022-06-08 03:30:22 +03:00
|
|
|
import Style 1.0
|
2022-12-02 16:51:09 +03:00
|
|
|
import "./tray"
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2021-09-09 12:18:22 +03:00
|
|
|
ColumnLayout {
|
|
|
|
id: rootLayout
|
2022-07-20 20:56:57 +03:00
|
|
|
spacing: Style.standardSpacing * 2
|
2021-09-09 12:18:22 +03:00
|
|
|
property NC.UserStatusSelectorModel userStatusSelectorModel
|
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
ColumnLayout {
|
|
|
|
id: statusButtonsLayout
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-07-20 20:56:57 +03:00
|
|
|
Layout.fillWidth: true
|
2022-08-10 18:45:11 +03:00
|
|
|
spacing: Style.smallSpacing
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-12-02 16:51:09 +03:00
|
|
|
EnforcedPlainTextLabel {
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.bottomMargin: Style.smallSpacing
|
|
|
|
horizontalAlignment: Text.AlignHCenter
|
|
|
|
font.bold: true
|
|
|
|
text: qsTr("Online status")
|
|
|
|
}
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
GridLayout {
|
|
|
|
id: topButtonsLayout
|
|
|
|
columns: 2
|
|
|
|
rows: 2
|
|
|
|
columnSpacing: statusButtonsLayout.spacing
|
|
|
|
rowSpacing: statusButtonsLayout.spacing
|
|
|
|
|
|
|
|
property int maxButtonHeight: 0
|
|
|
|
function updateMaxButtonHeight(newHeight) {
|
|
|
|
maxButtonHeight = Math.max(maxButtonHeight, newHeight)
|
2022-07-20 20:56:57 +03:00
|
|
|
}
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
UserStatusSelectorButton {
|
|
|
|
checked: userStatusSelectorModel.onlineStatus === NC.UserStatus.Online
|
|
|
|
checkable: true
|
|
|
|
icon.source: userStatusSelectorModel.onlineIcon
|
|
|
|
icon.color: "transparent"
|
|
|
|
text: qsTr("Online")
|
|
|
|
onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.Online
|
2021-09-09 12:18:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.fillWidth: true
|
|
|
|
implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
|
|
|
|
}
|
|
|
|
UserStatusSelectorButton {
|
|
|
|
checked: userStatusSelectorModel.onlineStatus === NC.UserStatus.Away
|
|
|
|
checkable: true
|
|
|
|
icon.source: userStatusSelectorModel.awayIcon
|
|
|
|
icon.color: "transparent"
|
|
|
|
text: qsTr("Away")
|
|
|
|
onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.Away
|
2021-09-09 12:18:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.fillWidth: true
|
|
|
|
implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
|
2021-09-09 12:18:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
}
|
|
|
|
UserStatusSelectorButton {
|
|
|
|
checked: userStatusSelectorModel.onlineStatus === NC.UserStatus.DoNotDisturb
|
|
|
|
checkable: true
|
|
|
|
icon.source: userStatusSelectorModel.dndIcon
|
|
|
|
icon.color: "transparent"
|
|
|
|
text: qsTr("Do not disturb")
|
|
|
|
secondaryText: qsTr("Mute all notifications")
|
|
|
|
onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.DoNotDisturb
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.fillWidth: true
|
|
|
|
implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
|
|
|
|
Layout.preferredHeight: topButtonsLayout.maxButtonHeight
|
|
|
|
onImplicitHeightChanged: topButtonsLayout.updateMaxButtonHeight(implicitHeight)
|
|
|
|
Component.onCompleted: topButtonsLayout.updateMaxButtonHeight(implicitHeight)
|
|
|
|
}
|
|
|
|
UserStatusSelectorButton {
|
2022-10-05 22:44:02 +03:00
|
|
|
checked: userStatusSelectorModel.onlineStatus === NC.UserStatus.Invisible ||
|
|
|
|
userStatusSelectorModel.onlineStatus === NC.UserStatus.Offline
|
2022-08-10 18:45:11 +03:00
|
|
|
checkable: true
|
|
|
|
icon.source: userStatusSelectorModel.invisibleIcon
|
|
|
|
icon.color: "transparent"
|
|
|
|
text: qsTr("Invisible")
|
|
|
|
secondaryText: qsTr("Appear offline")
|
|
|
|
onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.Invisible
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.fillWidth: true
|
|
|
|
implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
|
|
|
|
Layout.preferredHeight: topButtonsLayout.maxButtonHeight
|
|
|
|
onImplicitHeightChanged: topButtonsLayout.updateMaxButtonHeight(implicitHeight)
|
|
|
|
Component.onCompleted: topButtonsLayout.updateMaxButtonHeight(implicitHeight)
|
2022-07-20 20:56:57 +03:00
|
|
|
}
|
|
|
|
}
|
2022-08-10 18:45:11 +03:00
|
|
|
}
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
ColumnLayout {
|
|
|
|
id: userStatusMessageLayout
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
spacing: Style.smallSpacing
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-12-02 16:51:09 +03:00
|
|
|
EnforcedPlainTextLabel {
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.bottomMargin: Style.smallSpacing
|
|
|
|
horizontalAlignment: Text.AlignHCenter
|
|
|
|
font.bold: true
|
|
|
|
text: qsTr("Status message")
|
|
|
|
}
|
|
|
|
|
|
|
|
RowLayout {
|
|
|
|
id: statusFieldLayout
|
|
|
|
Layout.fillWidth: true
|
|
|
|
spacing: 0
|
|
|
|
|
|
|
|
UserStatusSelectorButton {
|
|
|
|
id: fieldButton
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.preferredWidth: userStatusMessageTextField.height
|
|
|
|
Layout.preferredHeight: userStatusMessageTextField.height
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
text: userStatusSelectorModel.userStatusEmoji
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
onClicked: emojiDialog.open()
|
|
|
|
onHeightChanged: topButtonsLayout.maxButtonHeight = Math.max(topButtonsLayout.maxButtonHeight, height)
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
primary: true
|
|
|
|
padding: 0
|
|
|
|
z: hovered ? 2 : 0 // Make sure highlight is seen on top of text field
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2023-05-25 06:51:51 +03:00
|
|
|
property color borderColor: showBorder ? Style.ncBlue : palette.dark
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
// We create the square with only the top-left and bottom-left rounded corners
|
|
|
|
// by overlaying different rectangles on top of each other
|
|
|
|
background: Rectangle {
|
|
|
|
radius: Style.slightlyRoundedButtonRadius
|
2023-05-25 06:51:51 +03:00
|
|
|
color: palette.button
|
2022-08-10 18:45:11 +03:00
|
|
|
border.color: fieldButton.borderColor
|
|
|
|
border.width: Style.normalBorderWidth
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Rectangle {
|
|
|
|
anchors.fill: parent
|
|
|
|
anchors.leftMargin: parent.width / 2
|
|
|
|
anchors.rightMargin: -1
|
|
|
|
z: 1
|
2023-05-25 06:51:51 +03:00
|
|
|
color: palette.button
|
2022-07-20 20:56:57 +03:00
|
|
|
border.color: fieldButton.borderColor
|
|
|
|
border.width: Style.normalBorderWidth
|
2022-08-10 18:45:11 +03:00
|
|
|
}
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Rectangle { // We need to cover the blue border of the non-radiused rectangle
|
|
|
|
anchors.fill: parent
|
|
|
|
anchors.leftMargin: parent.width / 4
|
|
|
|
anchors.rightMargin: parent.width / 4
|
|
|
|
anchors.topMargin: Style.normalBorderWidth
|
|
|
|
anchors.bottomMargin: Style.normalBorderWidth
|
|
|
|
z: 2
|
2023-05-25 06:51:51 +03:00
|
|
|
color: palette.button
|
2022-07-20 20:56:57 +03:00
|
|
|
}
|
|
|
|
}
|
2022-08-10 18:45:11 +03:00
|
|
|
}
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Popup {
|
|
|
|
id: emojiDialog
|
|
|
|
padding: 0
|
|
|
|
margins: 0
|
|
|
|
clip: true
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
anchors.centerIn: Overlay.overlay
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
background: Rectangle {
|
2023-05-25 06:51:51 +03:00
|
|
|
color: palette.toolTipBase
|
2022-08-10 18:45:11 +03:00
|
|
|
border.width: Style.normalBorderWidth
|
2023-05-25 06:51:51 +03:00
|
|
|
border.color: palette.dark
|
2022-08-10 18:45:11 +03:00
|
|
|
radius: Style.slightlyRoundedButtonRadius
|
|
|
|
}
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
EmojiPicker {
|
|
|
|
id: emojiPicker
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
onChosen: {
|
|
|
|
userStatusSelectorModel.userStatusEmoji = emoji
|
|
|
|
emojiDialog.close()
|
2022-07-20 20:56:57 +03:00
|
|
|
}
|
2022-06-08 03:30:22 +03:00
|
|
|
}
|
2022-08-10 18:45:11 +03:00
|
|
|
}
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
TextField {
|
|
|
|
id: userStatusMessageTextField
|
2022-11-25 16:53:16 +03:00
|
|
|
|
2023-05-25 06:51:51 +03:00
|
|
|
property color borderColor: activeFocus ? Style.ncBlue : palette.dark
|
2022-11-25 16:53:16 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.fillWidth: true
|
2022-11-25 16:53:16 +03:00
|
|
|
Layout.preferredHeight: contentHeight + (Style.smallSpacing * 2)
|
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
placeholderText: qsTr("What is your status?")
|
2023-05-25 06:51:51 +03:00
|
|
|
placeholderTextColor: palette.midlight
|
2022-08-10 18:45:11 +03:00
|
|
|
text: userStatusSelectorModel.userStatusMessage
|
2022-11-25 16:53:16 +03:00
|
|
|
verticalAlignment: TextInput.AlignVCenter
|
2022-08-10 18:45:11 +03:00
|
|
|
selectByMouse: true
|
|
|
|
onEditingFinished: userStatusSelectorModel.userStatusMessage = text
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
background: Rectangle {
|
|
|
|
radius: Style.slightlyRoundedButtonRadius
|
2023-05-25 06:51:51 +03:00
|
|
|
color: palette.base
|
2022-08-10 18:45:11 +03:00
|
|
|
border.color: userStatusMessageTextField.borderColor
|
|
|
|
border.width: Style.normalBorderWidth
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
anchors.fill: parent
|
|
|
|
anchors.rightMargin: parent.width / 2
|
|
|
|
z: 1
|
2023-05-25 06:51:51 +03:00
|
|
|
color: palette.base
|
2022-07-20 20:56:57 +03:00
|
|
|
border.color: userStatusMessageTextField.borderColor
|
|
|
|
border.width: Style.normalBorderWidth
|
2022-08-10 18:45:11 +03:00
|
|
|
}
|
2022-07-20 20:56:57 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Rectangle { // We need to cover the blue border of the non-radiused rectangle
|
|
|
|
anchors.fill: parent
|
|
|
|
anchors.leftMargin: parent.width / 4
|
|
|
|
anchors.rightMargin: parent.width / 4
|
|
|
|
anchors.topMargin: Style.normalBorderWidth
|
|
|
|
anchors.bottomMargin: Style.normalBorderWidth
|
|
|
|
z: 2
|
2023-05-25 06:51:51 +03:00
|
|
|
color: palette.base
|
2022-07-20 20:56:57 +03:00
|
|
|
}
|
2022-06-08 03:30:22 +03:00
|
|
|
}
|
|
|
|
}
|
2022-08-10 18:45:11 +03:00
|
|
|
}
|
2021-09-09 12:18:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
ScrollView {
|
|
|
|
id: predefinedStatusesScrollView
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
clip: true
|
|
|
|
|
|
|
|
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
2021-09-09 12:18:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
ListView {
|
|
|
|
spacing: 0
|
|
|
|
model: userStatusSelectorModel.predefinedStatuses
|
|
|
|
delegate: PredefinedStatusButton {
|
|
|
|
anchors.left: parent.left
|
|
|
|
anchors.right: parent.right
|
|
|
|
leftPadding: 0
|
|
|
|
emojiWidth: fieldButton.width
|
|
|
|
internalSpacing: statusFieldLayout.spacing + userStatusMessageTextField.leftPadding
|
|
|
|
|
|
|
|
emoji: modelData.icon
|
2022-09-29 20:37:55 +03:00
|
|
|
statusText: modelData.message
|
|
|
|
clearAtText: userStatusSelectorModel.clearAtReadable(modelData)
|
2022-08-10 18:45:11 +03:00
|
|
|
onClicked: userStatusSelectorModel.setPredefinedStatus(modelData)
|
2021-09-09 12:18:22 +03:00
|
|
|
}
|
|
|
|
}
|
2022-08-10 18:45:11 +03:00
|
|
|
}
|
2021-09-09 12:18:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
RowLayout {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
spacing: Style.smallSpacing
|
2022-08-10 20:57:18 +03:00
|
|
|
|
2022-12-02 16:51:09 +03:00
|
|
|
EnforcedPlainTextLabel {
|
2022-08-10 18:45:11 +03:00
|
|
|
id: clearComboLabel
|
2022-08-10 20:57:18 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
verticalAlignment: Text.AlignVCenter
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
text: qsTr("Clear status message after")
|
|
|
|
wrapMode: Text.Wrap
|
|
|
|
}
|
2022-08-10 20:57:18 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
BasicComboBox {
|
|
|
|
id: clearComboBox
|
2022-08-10 20:57:18 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
Layout.minimumWidth: implicitWidth
|
|
|
|
|
|
|
|
model: userStatusSelectorModel.clearStageTypes
|
|
|
|
textRole: "display"
|
|
|
|
valueRole: "clearStageType"
|
|
|
|
displayText: userStatusSelectorModel.clearAtDisplayString
|
|
|
|
onActivated: userStatusSelectorModel.setClearAt(currentValue)
|
2022-06-08 03:30:22 +03:00
|
|
|
}
|
2021-09-09 12:18:22 +03:00
|
|
|
}
|
2022-08-10 18:45:11 +03:00
|
|
|
}
|
2021-09-09 12:18:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
ErrorBox {
|
|
|
|
width: parent.width
|
2022-06-08 03:30:22 +03:00
|
|
|
|
2022-08-10 18:45:11 +03:00
|
|
|
visible: userStatusSelectorModel.errorMessage != ""
|
2022-09-29 20:37:55 +03:00
|
|
|
text: "Error: " + userStatusSelectorModel.errorMessage
|
2021-09-09 12:18:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
RowLayout {
|
2022-08-10 18:45:11 +03:00
|
|
|
id: bottomButtonBox
|
2022-07-20 20:56:57 +03:00
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.alignment: Qt.AlignBottom
|
|
|
|
|
|
|
|
UserStatusSelectorButton {
|
2022-08-10 18:57:48 +03:00
|
|
|
// Prevent being squashed by the other buttons with larger text
|
|
|
|
Layout.minimumWidth: implicitWidth
|
|
|
|
Layout.fillHeight: true
|
2022-07-20 20:56:57 +03:00
|
|
|
primary: true
|
|
|
|
text: qsTr("Cancel")
|
|
|
|
onClicked: finished()
|
|
|
|
}
|
2022-06-08 03:30:22 +03:00
|
|
|
UserStatusSelectorButton {
|
2021-09-09 12:18:22 +03:00
|
|
|
Layout.fillWidth: true
|
2022-08-10 18:57:48 +03:00
|
|
|
Layout.fillHeight: true
|
2022-06-08 03:30:22 +03:00
|
|
|
primary: true
|
2021-09-09 12:18:22 +03:00
|
|
|
text: qsTr("Clear status message")
|
|
|
|
onClicked: userStatusSelectorModel.clearUserStatus()
|
|
|
|
}
|
2022-06-08 03:30:22 +03:00
|
|
|
UserStatusSelectorButton {
|
2022-07-20 20:56:57 +03:00
|
|
|
Layout.fillWidth: true
|
2022-08-10 18:57:48 +03:00
|
|
|
Layout.fillHeight: true
|
2022-06-08 03:30:22 +03:00
|
|
|
primary: true
|
|
|
|
colored: true
|
2021-09-09 12:18:22 +03:00
|
|
|
text: qsTr("Set status message")
|
|
|
|
onClicked: userStatusSelectorModel.setUserStatus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|