commit
5d1a545317
1 changed files with 108 additions and 90 deletions
|
@ -26,27 +26,24 @@ import "../js/twemoji.js" as Emoji
|
||||||
Item {
|
Item {
|
||||||
id: pollMessageComponent
|
id: pollMessageComponent
|
||||||
|
|
||||||
|
|
||||||
property ListItem messageListItem
|
property ListItem messageListItem
|
||||||
property MessageOverlayFlickable overlayFlickable
|
property MessageOverlayFlickable overlayFlickable
|
||||||
property var rawMessage: messageListItem ? messageListItem.myMessage : overlayFlickable.overlayMessage
|
readonly property var rawMessage: messageListItem ? messageListItem.myMessage : overlayFlickable.overlayMessage
|
||||||
property string chatId: rawMessage.chat_id
|
readonly property string chatId: rawMessage.chat_id
|
||||||
|
readonly property bool isOwnMessage: messageListItem ? messageListItem.isOwnMessage : overlayFlickable.isOwnMessage
|
||||||
property bool isOwnMessage: messageListItem ? messageListItem.isOwnMessage : overlayFlickable.isOwnMessage
|
readonly property string messageId: rawMessage.id
|
||||||
|
readonly property bool canEdit: rawMessage.can_be_edited
|
||||||
property string messageId: rawMessage.id
|
readonly property var pollData: rawMessage.content.poll
|
||||||
property bool canEdit: rawMessage.can_be_edited
|
|
||||||
property var pollData: rawMessage.content.poll
|
|
||||||
property var chosenPollData:({})
|
property var chosenPollData:({})
|
||||||
property var chosenIndexes: []
|
property var chosenIndexes: []
|
||||||
property bool hasAnswered: {
|
readonly property bool hasAnswered: {
|
||||||
return pollData.options.filter(function(option){
|
return pollData.options.filter(function(option){
|
||||||
return option.is_chosen
|
return option.is_chosen
|
||||||
}).length > 0;
|
}).length > 0;
|
||||||
}
|
}
|
||||||
property bool canAnswer: !hasAnswered && !pollData.is_closed
|
readonly property bool canAnswer: !hasAnswered && !pollData.is_closed
|
||||||
property bool isQuiz: pollData.type['@type'] === "pollTypeQuiz"
|
readonly property bool isQuiz: pollData.type['@type'] === "pollTypeQuiz"
|
||||||
property bool highlighted;
|
property bool highlighted
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: pollColumn.height
|
height: pollColumn.height
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
@ -78,6 +75,7 @@ Item {
|
||||||
id: pollColumn
|
id: pollColumn
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Theme.paddingSmall
|
spacing: Theme.paddingSmall
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
@ -99,7 +97,7 @@ Item {
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
visible: !pollMessageComponent.canAnswer
|
visible: !pollMessageComponent.canAnswer
|
||||||
width: parent.width
|
width: 1
|
||||||
height: Theme.paddingSmall
|
height: Theme.paddingSmall
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,88 +115,89 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: resultDelegate
|
id: resultDelegate
|
||||||
Item {
|
Row {
|
||||||
id: optionDelegate
|
id: optionDelegate
|
||||||
width: pollMessageComponent.width
|
height: Math.max(Theme.itemSizeExtraSmall, implicitHeight)
|
||||||
height: displayOptionLabel.height + displayOptionStatistics.height
|
|
||||||
|
|
||||||
Rectangle {
|
Item {
|
||||||
id: displayOptionChosenMarker
|
|
||||||
height: parent.height
|
height: parent.height
|
||||||
width: Theme.horizontalPageMargin/2
|
width: Theme.horizontalPageMargin/2
|
||||||
color: Theme.rgba(Theme.highlightBackgroundColor, Theme.highlightBackgroundOpacity)
|
anchors.bottom: parent.bottom
|
||||||
visible: modelData.is_chosen
|
|
||||||
x: -width
|
|
||||||
}
|
|
||||||
OpacityRampEffect {
|
|
||||||
sourceItem: displayOptionChosenMarker
|
|
||||||
direction: OpacityRamp.LeftToRight
|
|
||||||
}
|
|
||||||
Column {
|
|
||||||
id: iconsColumn
|
|
||||||
width: pollMessageComponent.isQuiz ?Theme.iconSizeSmall + Theme.paddingMedium : Theme.paddingMedium
|
|
||||||
|
|
||||||
anchors {
|
Rectangle {
|
||||||
left: parent.left
|
id: displayOptionChosenMarker
|
||||||
verticalCenter: parent.verticalCenter
|
anchors.fill: parent
|
||||||
|
color: Theme.rgba(Theme.highlightBackgroundColor, Theme.highlightBackgroundOpacity)
|
||||||
|
visible: modelData.is_chosen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OpacityRampEffect {
|
||||||
|
sourceItem: displayOptionChosenMarker
|
||||||
|
direction: OpacityRamp.LeftToRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: Theme.paddingMedium + (pollMessageComponent.isQuiz ? Theme.iconSizeSmall : 0)
|
||||||
|
height: correctAnswerIcon.height
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom
|
||||||
|
bottomMargin: (votePercentageBar.height - height)/2
|
||||||
|
}
|
||||||
Icon {
|
Icon {
|
||||||
|
id: correctAnswerIcon
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
highlighted: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted
|
highlighted: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted
|
||||||
property bool isRight: pollMessageComponent.isQuiz && pollData.type.correct_option_id === index
|
readonly property bool isRight: pollMessageComponent.isQuiz && pollData.type.correct_option_id === index
|
||||||
source: "image://theme/icon-s-accept"
|
source: "image://theme/icon-s-accept"
|
||||||
visible: isRight
|
visible: isRight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Column {
|
||||||
id: displayOptionLabel
|
width: list.width - x
|
||||||
text: Emoji.emojify(modelData.text, Theme.fontSizeMedium)
|
anchors.bottom: parent.bottom
|
||||||
textFormat: Text.StyledText
|
|
||||||
|
|
||||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
Item {
|
||||||
anchors {
|
width: parent.width
|
||||||
left: iconsColumn.right
|
height: Math.max(voteTextLabel.height, votePercentageLabel.y + votePercentageLabel.height)
|
||||||
top: parent.top
|
|
||||||
right: parent.right
|
|
||||||
}
|
|
||||||
color: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.highlightColor : Theme.primaryColor
|
|
||||||
}
|
|
||||||
Item {
|
|
||||||
id: displayOptionStatistics
|
|
||||||
height: optionVoterPercentage.height + optionVoterPercentageBar.height
|
|
||||||
anchors {
|
|
||||||
top: displayOptionLabel.bottom
|
|
||||||
left: iconsColumn.right
|
|
||||||
right: parent.right
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: optionVoterPercentage
|
id: voteTextLabel
|
||||||
font.pixelSize: Theme.fontSizeTiny
|
property int lastLineWidth
|
||||||
text: qsTr("%Ln\%", "% of votes for option", modelData.vote_percentage)
|
width: parent.width
|
||||||
horizontalAlignment: Text.AlignRight
|
text: Emoji.emojify(modelData.text, Theme.fontSizeMedium)
|
||||||
anchors {
|
textFormat: Text.StyledText
|
||||||
right: parent.right
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
left: parent.horizontalCenter
|
color: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.highlightColor : Theme.primaryColor
|
||||||
leftMargin: Theme.paddingSmall
|
onTextChanged: lastLineWidth = 0
|
||||||
|
onLineLaidOut: {
|
||||||
|
if (line.isLast) {
|
||||||
|
lastLineWidth = line.x + line.implicitWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: votePercentageLabel
|
||||||
|
y: (voteTextLabel.lastLineWidth + Theme.paddingLarge) > x ? voteTextLabel.height : Math.max(0, voteTextLabel.height - height)
|
||||||
|
font.pixelSize: Theme.fontSizeTiny
|
||||||
|
text: qsTr("%Ln\%", "% of votes for option", modelData.vote_percentage)
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
anchors.right: parent.right
|
||||||
|
color: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||||
}
|
}
|
||||||
color: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: optionVoterPercentageBar
|
id: votePercentageBar
|
||||||
height: Theme.paddingSmall
|
height: Theme.paddingSmall
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
color: Theme.rgba(pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor, 0.3)
|
color: Theme.rgba(pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor, 0.3)
|
||||||
radius: height/2
|
radius: height/2
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
height: parent.height
|
height: parent.height
|
||||||
color: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.highlightColor : Theme.primaryColor
|
color: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.highlightColor : Theme.primaryColor
|
||||||
|
@ -210,32 +209,35 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
ListView {
|
||||||
|
id: list
|
||||||
model: pollData.options
|
model: pollData.options
|
||||||
|
x: -Theme.horizontalPageMargin/2
|
||||||
|
width: parent.width - x
|
||||||
|
height: contentHeight
|
||||||
|
interactive: false
|
||||||
delegate: pollMessageComponent.canAnswer ? canAnswerDelegate : resultDelegate
|
delegate: pollMessageComponent.canAnswer ? canAnswerDelegate : resultDelegate
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Item {
|
||||||
layoutDirection: Qt.RightToLeft
|
width: 1
|
||||||
width: parent.width
|
height: Theme.paddingSmall
|
||||||
spacing: Theme.paddingMedium
|
}
|
||||||
Behavior on height { NumberAnimation {}}
|
|
||||||
|
|
||||||
|
Item {
|
||||||
Label {
|
x: -Theme.horizontalPageMargin/2
|
||||||
id: totalVoterCount
|
width: parent.width - x
|
||||||
font.pixelSize: Theme.fontSizeTiny
|
height: Math.max(voteButtons.height, totalVoterCount.height + Theme.paddingSmall)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: qsTr("%Ln vote(s) total", "number of total votes", pollData.total_voter_count)
|
|
||||||
width: contentWidth
|
|
||||||
height: contentHeight
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
color: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
|
id: voteButtons
|
||||||
spacing: Theme.paddingSmall
|
spacing: Theme.paddingSmall
|
||||||
width: parent.width - totalVoterCount.width - parent.spacing
|
width: parent.width - totalVoterCount.width - parent.spacing
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
|
||||||
IconButton {
|
IconButton {
|
||||||
visible: !pollData.is_closed && pollMessageComponent.chosenIndexes.length > 0 && pollData.type.allow_multiple_answers && !pollMessageComponent.hasAnswered
|
visible: !pollData.is_closed && pollMessageComponent.chosenIndexes.length > 0 && pollData.type.allow_multiple_answers && !pollMessageComponent.hasAnswered
|
||||||
opacity: visible ? 1.0 : 0.0
|
opacity: visible ? 1.0 : 0.0
|
||||||
|
@ -246,7 +248,6 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IconButton {
|
IconButton {
|
||||||
visible: !pollMessageComponent.canAnswer && !pollData.is_anonymous && pollData.total_voter_count > 0
|
visible: !pollMessageComponent.canAnswer && !pollData.is_anonymous && pollData.total_voter_count > 0
|
||||||
icon.source: "image://theme/icon-m-media-artists"
|
icon.source: "image://theme/icon-m-media-artists"
|
||||||
|
@ -263,9 +264,25 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: totalVoterCount
|
||||||
|
font.pixelSize: Theme.fontSizeTiny
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
right: parent.right
|
||||||
|
left: voteButtons.right
|
||||||
|
leftMargin: Theme.paddingMedium
|
||||||
|
}
|
||||||
|
text: qsTr("%Ln vote(s) total", "number of total votes", pollData.total_voter_count)
|
||||||
|
width: contentWidth
|
||||||
|
height: contentHeight
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
color: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: closePollMenuItemComponent
|
id: closePollMenuItemComponent
|
||||||
MenuItem {
|
MenuItem {
|
||||||
|
@ -276,6 +293,7 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: resetAnswerMenuItemComponent
|
id: resetAnswerMenuItemComponent
|
||||||
MenuItem {
|
MenuItem {
|
||||||
|
|
Loading…
Reference in a new issue