feat(settings/profile): add social links' ui primitives

iterates: #6797
This commit is contained in:
Patryk Osmaczko 2022-08-10 10:27:45 +02:00 committed by osmaczko
parent 6783f3a321
commit 46e01afa04
8 changed files with 433 additions and 0 deletions

View File

@ -0,0 +1,91 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import utils 1.0
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import shared.controls 1.0
Item {
id: root
property alias hyperlink: hyperlinkInput.text
property alias url: urlInput.text
readonly property alias removeButton: removeButton
implicitHeight: layout.implicitHeight
implicitWidth: layout.implicitWidth
RowLayout {
id: layout
anchors.fill: parent
ColumnLayout {
id: leftLayout
spacing: 26
StatusInput {
id: hyperlinkInput
Layout.fillWidth: true
label: qsTr("Hyperlink Text")
placeholderText: qsTr("Example: My Myspace Profile")
charLimit: 24
}
StatusInput {
id: urlInput
Layout.fillWidth: true
label: qsTr("URL")
placeholderText: qsTr("Link URL")
}
}
Item {
Layout.preferredWidth: 280
Layout.fillHeight: true
clip: true
ColumnLayout {
x: 64
anchors.verticalCenter: parent.verticalCenter
spacing: 10
StatusBaseText {
text: qsTr("Preview")
color: Theme.palette.baseColor1
font.pixelSize: 15
}
SocialLinkPreview {
text: !!hyperlinkInput.text ? hyperlinkInput.text : qsTr("My Myspace Profile")
url: !!urlInput.text ? urlInput.text : urlInput.placeholderText
linkType: Constants.socialLinkType.custom
}
}
}
}
StatusFlatButton {
id: removeButton
anchors {
right: parent.right
top: parent.top
}
icon.name: "delete"
text: qsTr("Remove")
size: StatusBaseButton.Small
}
}

View File

@ -0,0 +1,35 @@
import QtQuick 2.14
import utils 1.0
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
StatusInput {
id: root
property int linkType
placeholderText: {
if (linkType === Constants.socialLinkType.twitter) return qsTr("Twitter Handle")
if (linkType === Constants.socialLinkType.personalSite) return qsTr("Personal Site")
if (linkType === Constants.socialLinkType.github) return qsTr("Github")
if (linkType === Constants.socialLinkType.youtube) return qsTr("YouTube Channel")
if (linkType === Constants.socialLinkType.discord) return qsTr("Discord Handle")
if (linkType === Constants.socialLinkType.telegram) return qsTr("Telegram Handle")
return ""
}
input.icon {
name: {
if (linkType === Constants.socialLinkType.twitter) return "twitter"
if (linkType === Constants.socialLinkType.personalSite) return "language"
if (linkType === Constants.socialLinkType.github) return "github"
if (linkType === Constants.socialLinkType.youtube) return "youtube"
if (linkType === Constants.socialLinkType.discord) return "discord"
if (linkType === Constants.socialLinkType.telegram) return "telegram"
return ""
}
width: 20
height: 20
}
}

View File

@ -0,0 +1,76 @@
import QtQuick 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.Controls.Validators 0.1
import utils 1.0
import "../controls"
Item {
id: root
property alias displayName: displayNameInput
property alias bio: bioInput
property var socialLinksModel
signal socialLinkChanged(string uuid, string text, string url)
signal addSocialLinksClicked
implicitHeight: layout.implicitHeight
implicitWidth: layout.implicitWidth
ColumnLayout {
id: layout
anchors.fill: parent
spacing: 19 // by design
StatusInput {
id: displayNameInput
Layout.fillWidth: true
label: qsTr("Display name")
placeholderText: qsTr("Display Name")
charLimit: 24
validators: Constants.validators.displayName
}
StatusInput {
id: bioInput
Layout.fillWidth: true
Layout.topMargin: 5 // by design
label: qsTr("Bio")
placeholderText: qsTr("Tell us about yourself")
charLimit: 240
multiline: true
minimumHeight: 108
maximumHeight: 108
input.verticalAlignment: TextEdit.AlignTop
}
Repeater {
model: root.socialLinksModel
delegate: StaticSocialLinkInput {
Layout.fillWidth: true
linkType: model.linkType
text: model.url
onTextChanged: root.socialLinkChanged(model.uuid, model.text, text)
}
}
StatusIconTextButton {
Layout.topMargin: -8 // by design
text: qsTr("Add more social links")
onClicked: root.addSocialLinksClicked()
}
}
}

View File

@ -0,0 +1,95 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import utils 1.0
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
Rectangle {
id: root
property string text
property string url
property int linkType: 1
implicitWidth: layout.implicitWidth + 16
implicitHeight: layout.implicitHeight + 10
color: "transparent"
border {
width: 1
color: Theme.palette.baseColor2
}
radius: height/2
RowLayout {
id: layout
anchors.centerIn: parent
StatusIcon {
Layout.preferredWidth: 20
Layout.preferredHeight: 20
icon: {
if (root.linkType === Constants.socialLinkType.twitter) return "twitter"
if (root.linkType === Constants.socialLinkType.personalSite) return "language"
if (root.linkType === Constants.socialLinkType.github) return "github"
if (root.linkType === Constants.socialLinkType.youtube) return "youtube"
if (root.linkType === Constants.socialLinkType.discord) return "discord"
if (root.linkType === Constants.socialLinkType.telegram) return "telegram"
return ""
}
visible: icon !== ""
color: Theme.palette.directColor1
}
StatusBaseText {
text: root.linkType === Constants.socialLinkType.custom ? root.text : root.url
color: Theme.palette.directColor4
font.weight: Font.Medium
}
}
StatusToolTip {
id: toolTip
contentItem: RowLayout {
StatusBaseText {
Layout.fillHeight: true
Layout.bottomMargin: 8
text: toolTip.text
color: Theme.palette.white
wrapMode: Text.WordWrap
font.pixelSize: 13
font.weight: Font.Medium
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
StatusFlatRoundButton {
Layout.preferredHeight: 24
Layout.preferredWidth: 24
Layout.bottomMargin: 8
icon.name: "copy"
icon.width: 18
icon.height: 18
type: StatusFlatRoundButton.Tertiary
onClicked: {
globalUtils.copyToClipboard(toolTip.text)
toolTip.visible = false
}
}
}
}
MouseArea {
anchors.fill: parent
onClicked: toolTip.show(root.url, -1)
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
}
}

View File

@ -25,3 +25,4 @@ TransactionDelegate 1.0 TransactionDelegate.qml
TransactionFormGroup 1.0 TransactionFormGroup.qml
EmojiHash 1.0 EmojiHash.qml
InformationTile 1.0 InformationTile.qml
SocialLinkPreview 1.0 SocialLinkPreview.qml

View File

@ -0,0 +1,124 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import QtQml.Models 2.14
import utils 1.0
import StatusQ.Core 0.1
import "../controls"
import SortFilterProxyModel 0.2
Item {
id: root
property string bio
property string userSocialLinksJson
onUserSocialLinksJsonChanged: d.buildSocialLinksModel()
implicitWidth: layout.implicitWidth
implicitHeight: layout.implicitHeight
QtObject {
id: d
function textToType(text) {
if (text === "__twitter") return Constants.socialLinkType.twitter
if (text === "__personal_site") return Constants.socialLinkType.personalSite
if (text === "__github") return Constants.socialLinkType.github
if (text === "__youtube") return Constants.socialLinkType.youtube
if (text === "__discord") return Constants.socialLinkType.discord
if (text === "__telegram") return Constants.socialLinkType.telegram
return Constants.socialLinkType.custom
}
// Unfortunately, nim can't expose temporary QObjects thorugh slots
// The only way to expose static models on demand is through json strings (see getContactDetailsAsJson)
// Model is built here manually, which I know is completely wrong..
function buildSocialLinksModel() {
socialLinksModel.clear()
if (root.userSocialLinksJson == "") return
try {
let links = JSON.parse(root.userSocialLinksJson)
for (let i=0; i<links.length; i++) {
let obj = links[i]
socialLinksModel.append({
"text": obj.text,
"url": obj.url,
"linkType": textToType(obj.text)
})
}
}
catch (e) {
console.warn("can't parse userSocialLinksJson", e)
}
}
}
ListModel {
id: socialLinksModel
}
SortFilterProxyModel {
id: sortedSocialLinksModel
function customsLastPredicate(linkTypeLeft, linkTypeRight) {
if (linkTypeLeft === Constants.socialLinkType.custom) return false
if (linkTypeRight === Constants.socialLinkType.custom) return true
return linkTypeLeft < linkTypeRight
}
sourceModel: socialLinksModel
filters: ExpressionFilter {
expression: model.text !== "" && model.url !== ""
}
sorters: [
ExpressionSorter {
expression: sortedSocialLinksModel.customsLastPredicate(modelLeft.linkType, modelRight.linkType)
},
StringSorter {
roleName: "text"
caseSensitivity: Qt.CaseInsensitive
}
]
}
ColumnLayout {
id: layout
anchors.fill: parent
spacing: 20
StatusBaseText {
Layout.fillWidth: true
text: root.bio
wrapMode: Text.WordWrap
}
Flow {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: 10
Layout.rightMargin: 10
spacing: 16
visible: repeater.count > 0
Repeater {
id: repeater
model: sortedSocialLinksModel
delegate: SocialLinkPreview {
text: model.text
url: model.url
linkType: model.linkType
}
}
}
}
}

View File

@ -8,6 +8,7 @@ ImageLoader 1.0 ImageLoader.qml
LabelValueRow 1.0 LabelValueRow.qml
ModuleWarning 1.0 ModuleWarning.qml
NotificationWindow 1.0 NotificationWindow.qml
ProfileBioSocialsPanel 1.0 ProfileBioSocialsPanel.qml
RoundedIcon 1.0 RoundedIcon.qml
RoundedImage 1.0 RoundedImage.qml
Separator 1.0 Separator.qml

View File

@ -345,6 +345,16 @@ QtObject {
}
}
readonly property QtObject socialLinkType: QtObject {
readonly property int custom: 0
readonly property int twitter: 1
readonly property int personalSite: 2
readonly property int github: 3
readonly property int youtube: 4
readonly property int discord: 5
readonly property int telegram: 6
}
readonly property int communityImported: 0
readonly property int communityImportingInProgress: 1
readonly property int communityImportingError: 2