2020-10-23 11:29:50 +03:00
/ *
Copyright ( C ) 2020 Sebastian J . Wolf and other contributors
This file is part of Fernschreiber .
Fernschreiber 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 3 of the License , or
( at your option ) any later version .
Fernschreiber 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 .
You should have received a copy of the GNU General Public License
along with Fernschreiber . If not , see < http: //www.gnu.org/licenses/>.
* /
import QtQuick 2.6
import Sailfish . Silica 1.0
import "../components"
import "../js/functions.js" as Functions
import "../js/twemoji.js" as Emoji
2020-11-20 23:58:26 +03:00
import "../js/debug.js" as Debug
2020-10-23 11:29:50 +03:00
Page {
id: pollResultsPage
allowedOrientations: Orientation . All
property string chatId ;
property var message: ( { } ) ;
property string messageId: message . id ;
property var pollData: message . content . poll
2022-01-07 21:18:04 +03:00
property var userInformation: tdLibWrapper . getUserInformation ( message . sender_id . user_id )
2020-10-23 11:29:50 +03:00
property bool isQuiz: pollData . type [ '@type' ] === "pollTypeQuiz"
property bool hasAnswered: {
return pollData . options . filter ( function ( option ) {
return option . is_chosen
} ) . length > 0 ;
}
property bool canAnswer: ! hasAnswered && ! pollData . is_closed
onCanAnswerChanged: {
if ( canAnswer ) { // vote removed from another client?
pageStack . pop ( )
}
}
SilicaFlickable {
anchors.fill: parent
contentHeight: pageHeader . height + contentColumn . height
PageHeader {
id: pageHeader
title: pollResultsPage . isQuiz ? qsTr ( "Quiz Results" ) : qsTr ( "Poll Results" )
2020-11-19 11:32:05 +03:00
description: qsTr ( "%Ln vote(s) total" , "number of total votes" , pollData . total_voter_count )
2020-10-23 11:29:50 +03:00
leftMargin: headerPictureThumbnail . width + Theme . paddingLarge + Theme . horizontalPageMargin
ProfileThumbnail {
id: headerPictureThumbnail
photoData: ( typeof pollResultsPage . userInformation . profile_photo !== "undefined" ) ? pollResultsPage.userInformation.profile_photo.small : ""
replacementStringHint: Emoji . emojify ( Functions . getUserName ( pollResultsPage . userInformation ) , font . pixelSize )
width: visible ? Theme.itemSizeSmall : 0
height: visible ? Theme.itemSizeSmall : 0
anchors {
verticalCenter: pageHeader . verticalCenter
left: parent . left
leftMargin: Theme . horizontalPageMargin
}
}
}
Column {
id: contentColumn
anchors {
left: parent . left
leftMargin: Theme . horizontalPageMargin
right: parent . right
rightMargin: Theme . horizontalPageMargin
top: pageHeader . bottom
}
SectionHeader {
x: 0
text: qsTr ( "Question" , "section header" )
}
// Label {
// width: parent.width
// font.pixelSize: Theme.fontSizeTiny
// wrapMode: Text.Wrap
// color: Theme.secondaryHighlightColor
// text: JSON.stringify(pollData, null, 2)
// }
// Label {
// width: parent.width
// font.pixelSize: Theme.fontSizeTiny
// wrapMode: Text.Wrap
// color: Theme.secondaryHighlightColor
// text: JSON.stringify(userInformation, null, 2)
// }
Label {
width: parent . width
wrapMode: Text . Wrap
color: Theme . secondaryHighlightColor
text: Emoji . emojify ( pollData . question , font . pixelSize )
}
Column {
id: resultsColumn
width: parent . width
topPadding: Theme . paddingLarge
bottomPadding: Theme . paddingLarge
SectionHeader {
x: 0
text: qsTr ( "Results" , "section header" )
}
Repeater {
model: pollData . options
delegate: Item {
id: optionDelegate
width: resultsColumn . width
height: displayOptionLabel . height + displayOptionStatistics . height + displayOptionUsers . height + Theme . paddingLarge
property ListModel users: ListModel { }
property string usersResponseIdentifierString: "pollResults." + pollResultsPage . chatId + "." + pollResultsPage . messageId + "." + index
function loadUsers ( ) {
if ( users . count < modelData . voter_count ) {
tdLibWrapper . getPollVoters ( pollResultsPage . chatId , pollResultsPage . messageId , index , 50 , users . length , usersResponseIdentifierString )
}
}
Component.onCompleted: {
// loadUsers()
loadUsersTimer . start ( )
}
Timer {
id: loadUsersTimer
interval: index * 80
onTriggered: {
optionDelegate . loadUsers ( ) ;
}
}
Connections {
target: tdLibWrapper
2023-11-30 01:47:59 +03:00
onMessageSendersReceived: {
Debug . log ( "Received poll users..." )
2020-10-23 11:29:50 +03:00
if ( extra === optionDelegate . usersResponseIdentifierString ) {
2023-11-30 01:47:59 +03:00
for ( var i = 0 ; i < senders . length ; i += 1 ) {
optionDelegate . users . append ( { id: senders [ i ] . user_id , user: tdLibWrapper . getUserInformation ( senders [ i ] . user_id ) } ) ;
2020-10-23 11:29:50 +03:00
}
loadUsersTimer . start ( ) ;
}
}
}
Rectangle {
id: displayOptionChosenMarker
height: parent . height
width: Theme . horizontalPageMargin / 2
color: Theme . rgba ( Theme . highlightBackgroundColor , Theme . highlightBackgroundOpacity )
visible: modelData . is_chosen
x: - width
}
OpacityRampEffect {
sourceItem: displayOptionChosenMarker
direction: OpacityRamp . LeftToRight
}
Column {
id: iconsColumn
width: pollResultsPage . isQuiz ? Theme . iconSizeSmall + Theme.paddingMedium : Theme . paddingMedium
height: displayOptionLabel . height + displayOptionStatistics . height
anchors {
left: parent . left
// verticalCenter: parent.verticalCenter
}
Icon {
highlighted: true
property bool isRight: pollResultsPage . isQuiz && pollData . type . correct_option_id === index
source: "image://theme/icon-s-accept"
visible: isRight
anchors.verticalCenter: parent . verticalCenter
}
}
Label {
id: displayOptionLabel
text: Emoji . emojify ( modelData . text , Theme . fontSizeMedium )
wrapMode: Text . WrapAtWordBoundaryOrAnywhere
anchors {
left: iconsColumn . right
top: parent . top
right: parent . right
}
color: Theme . highlightColor
}
Item {
id: displayOptionStatistics
height: optionVoterPercentage . height + optionVoterPercentageBar . height
anchors {
top: displayOptionLabel . bottom
left: iconsColumn . right
right: parent . right
}
Label {
id: optionVoterCount
font.pixelSize: Theme . fontSizeTiny
2020-11-19 11:32:05 +03:00
text: modelData . is_chosen ? qsTr ( "%Ln vote(s) including yours" , "number of votes for option" , modelData . voter_count ) : qsTr ( "%Ln vote(s)" , "number of votes for option" , modelData . voter_count )
2020-10-23 11:29:50 +03:00
anchors {
left: parent . left
right: parent . horizontalCenter
rightMargin: Theme . paddingSmall
}
color: Theme . secondaryHighlightColor
}
Label {
id: optionVoterPercentage
font.pixelSize: Theme . fontSizeTiny
2020-11-19 11:32:05 +03:00
text: qsTr ( "%Ln\%" , "% of votes for option" , modelData . vote_percentage )
2020-10-23 11:29:50 +03:00
horizontalAlignment: Text . AlignRight
anchors {
right: parent . right
left: parent . horizontalCenter
leftMargin: Theme . paddingSmall
}
color: Theme . secondaryHighlightColor
}
Rectangle {
id: optionVoterPercentageBar
height: Theme . paddingSmall
width: parent . width
color: Theme . rgba ( Theme . secondaryHighlightColor , 0.3 )
radius: height / 2
anchors {
left: parent . left
bottom: parent . bottom
}
Rectangle {
height: parent . height
color: Theme . highlightColor
radius: height / 2
width: parent . width * modelData . vote_percentage * 0.01
}
}
}
// users voted for this:
Flow {
id: displayOptionUsers
anchors.top: displayOptionStatistics . bottom
width: parent . width
visible: optionDelegate . users . count > 0
topPadding: Theme . paddingLarge
spacing: Theme . paddingMedium
leftPadding: iconsColumn . width
property int itemHeight: Theme . itemSizeExtraSmall / 2
Item {
height: displayOptionUsers . itemHeight
width: chosenByUserText . width
Label {
id: chosenByUserText
font.pixelSize: Theme . fontSizeTiny
text: qsTr ( "Chosen by:" , "This answer has been chosen by the following users" )
width: contentWidth
anchors.centerIn: parent
color: Theme . secondaryHighlightColor
}
}
Repeater {
model: optionDelegate . users
delegate:
Item {
id: chosenByUserItem
width: chosenByUserPictureThumbnail . width + chosenByUserLabel . width + Theme . paddingSmall
height: displayOptionUsers . itemHeight
ProfileThumbnail {
id: chosenByUserPictureThumbnail
photoData: ( typeof model . user . profile_photo !== "undefined" ) ? model.user.profile_photo.small : ""
replacementStringHint: chosenByUserLabel . text
width: visible ? parent.height : 0
height: width
anchors {
left: parent . left
verticalCenter: parent . verticalCenter
}
}
Label {
id: chosenByUserLabel
font.pixelSize: Theme . fontSizeSmall
text: Emoji . emojify ( Functions . getUserName ( model . user ) , font . pixelSize )
width: contentWidth
height: contentHeight
color: Theme . highlightColor
anchors {
right: parent . right
verticalCenter: parent . verticalCenter
}
}
}
}
}
}
}
}
}
}
Connections {
target: tdLibWrapper
onMessageContentUpdated: {
if ( chatId === pollResultsPage . chatId && messageId === pollResultsPage . messageId ) {
pollResultsPage . pollData = newContent . poll ;
}
}
}
}