Skip to content

Commit

Permalink
Poll results
Browse files Browse the repository at this point in the history
  • Loading branch information
evgeny-nadymov committed Feb 20, 2020
1 parent d7f518c commit c3525b8
Show file tree
Hide file tree
Showing 19 changed files with 375 additions and 50 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"homepage": "http://evgeny-nadymov.github.io/telegram-react",
"name": "telegram_react",
"version": "0.0.580",
"version": "0.0.581",
"private": true,
"dependencies": {
"@material-ui/core": "^4.8.0",
Expand Down
31 changes: 16 additions & 15 deletions src/Components/Message/Media/Poll.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { setPollAnswer } from '../../../Actions/Poll';
import MessageStore from './../../../Stores/MessageStore';
import TdLibController from './../../../Controllers/TdLibController';
import './Poll.css';
import PollResultsDialog from '../../Popup/PollResultsDialog';

class Poll extends React.Component {
constructor(props) {
Expand Down Expand Up @@ -152,21 +153,26 @@ class Poll extends React.Component {
return correct_option_id === index;
}

handleOpenResults = () => {
handleOpenResults = event => {
event.preventDefault();
event.stopPropagation();

const { poll } = this.props;

this.setState({
viewResults: true
viewResultsPoll: poll
});
};

handleCloseResults = () => {
this.setState({
viewResults: false
viewResultsPoll: null
});
};

render() {
const { chatId, messageId, poll, t, meta } = this.props;
const { viewResults } = this.state;
const { viewResultsPoll } = this.state;
const { question, options, total_voter_count, type, is_closed, is_anonymous, recent_voter_user_ids } = poll;

let subtitle = t('FinalResults');
Expand Down Expand Up @@ -218,7 +224,6 @@ class Poll extends React.Component {
closed={is_closed}
maxVoterCount={maxVoterCount}
onVote={() => this.handleVote(index)}
onUnvote={this.handleUnvote}
/>
))}
</div>
Expand All @@ -242,17 +247,13 @@ class Poll extends React.Component {
{meta}
</div>
)}
{viewResults && (
<Dialog
transitionDuration={0}
open={viewResults}
{Boolean(viewResultsPoll) && (
<PollResultsDialog
chatId={chatId}
messageId={messageId}
poll={viewResultsPoll}
onClose={this.handleCloseResults}
aria-labelledby='poll-results-title'>
<DialogTitle id='poll-results-title'>
{isQuiz ? t('QuizResults') : t('PollResults')}
</DialogTitle>
<DialogContent>{}</DialogContent>
</Dialog>
/>
)}
</div>
);
Expand Down
16 changes: 1 addition & 15 deletions src/Components/Message/Media/PollOption.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,6 @@ class PollOption extends React.Component {
onVote();
};

handleCancel = event => {
const { onUnvote } = this.props;

event.stopPropagation();

onUnvote();
};

render() {
const { option, onChange, canBeSelected, closed, maxVoterCount, t, type, isCorrect } = this.props;
if (!option) return null;
Expand All @@ -63,12 +55,7 @@ class PollOption extends React.Component {
canBeSelected ? 'poll-option-unselected' : 'poll-option-selected'
)}>
<div className='poll-option-text-wrapper' title={this.getTitleString(voter_count, t)}>
<PollPercentage
value={vote_percentage}
chosen={is_chosen}
closed={closed}
onClick={this.handleCancel}
/>
<PollPercentage value={vote_percentage} chosen={is_chosen} closed={closed} />
<PollRadio
hidden={!canBeSelected}
chosen={is_chosen || isMultiChoosen}
Expand Down Expand Up @@ -114,7 +101,6 @@ PollOption.propTypes = {
type: PropTypes.oneOf(['regular', 'correct', 'incorrect']).isRequired,
option: PropTypes.object.isRequired,
onVote: PropTypes.func.isRequired,
onUnvote: PropTypes.func.isRequired,
canBeSelected: PropTypes.bool,
closed: PropTypes.bool,
maxVoterCount: PropTypes.number
Expand Down
4 changes: 2 additions & 2 deletions src/Components/Message/Media/PollRadio.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ class PollRadio extends React.Component {
}

PollRadio.propTypes = {
chosen: PropTypes.bool.isRequired,
beingChosen: PropTypes.bool.isRequired,
chosen: PropTypes.bool,
beingChosen: PropTypes.bool,
hidden: PropTypes.bool
};

Expand Down
1 change: 1 addition & 0 deletions src/Components/Popup/ChatInfoDialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@

.chat-info-dialog-paper {
width: 336px;
align-self: flex-start;
}
6 changes: 6 additions & 0 deletions src/Components/Popup/PollOptionResult.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright (c) 2018-present, Evgeny Nadymov
*
* This source code is licensed under the GPL v.3.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
49 changes: 49 additions & 0 deletions src/Components/Popup/PollOptionResult.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2018-present, Evgeny Nadymov
*
* This source code is licensed under the GPL v.3.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import PropTypes from 'prop-types';
import ListItem from '@material-ui/core/ListItem';
import User from '../Tile/User';
import UserPlaceholder from '../Tile/UserPlaceholder';
import { openUser } from '../../Actions/Client';
import TdLibController from '../../Controllers/TdLibController';
import './PollOptionResult.css';

class PollOptionResult extends React.Component {
onClick = () => {
const { userId } = this.props;
if (!userId) return;

openUser(userId, true);

setTimeout(() => {
TdLibController.clientUpdate({
'@type': 'clientUpdateClosePollResults'
});
}, 0);
};

render() {
const { index, userId } = this.props;

const content = userId ? <User userId={userId} showStatus={false} /> : <UserPlaceholder index={index} />;

return (
<ListItem button className='list-item' onClick={this.onClick}>
{content}
</ListItem>
);
}
}

PollOptionResult.propTypes = {
index: PropTypes.number.isRequired,
userId: PropTypes.number
};

export default PollOptionResult;
27 changes: 27 additions & 0 deletions src/Components/Popup/PollOptionResults.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2018-present, Evgeny Nadymov
*
* This source code is licensed under the GPL v.3.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
.poll-option-results-caption {
position: sticky;
top: 0;
padding: 17px 24px 18px;
color: var(--text-secondary);
background: var(--background-paper);
display: flex;
flex-direction: row;
z-index: 2;
}

.poll-option-results-answer {
flex-grow: 1;
flex-shrink: 1;
}

.poll-option-results-count {
margin-left: 9px;
flex-grow: 0;
flex-shrink: 0;
}
114 changes: 114 additions & 0 deletions src/Components/Popup/PollOptionResults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2018-present, Evgeny Nadymov
*
* This source code is licensed under the GPL v.3.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import PropTypes from 'prop-types';
import PollOptionResult from './PollOptionResult';
import { loadUsersContent } from '../../Utils/File';
import { POLL_RESULTS_FIRST_SLICE_LENGTH, POLL_RESULTS_LEAVE_LENGTH } from '../../Constants';
import FileStore from '../../Stores/FileStore';
import TdLibController from '../../Controllers/TdLibController';
import './PollOptionResults.css';

class PollOptionResults extends React.Component {
constructor(props) {
super(props);

const { option } = this.props;

const count =
option && option.voter_count <= POLL_RESULTS_FIRST_SLICE_LENGTH
? option.voter_count
: POLL_RESULTS_FIRST_SLICE_LENGTH - POLL_RESULTS_LEAVE_LENGTH;

this.state = {
voters: [],
offset: 0,
count
};
}

async updateVoters() {
const { chatId, messageId, optionId, option } = this.props;
const { offset, voters, count } = this.state;
if (count <= 0) return;

const result = await TdLibController.send({
'@type': 'getPollVoters',
chat_id: chatId,
message_id: messageId,
option_id: optionId,
offset: offset,
limit: count
});

if (this.props.option !== option) {
return;
}

const store = FileStore.getStore();
loadUsersContent(store, result.user_ids);

this.setState({
voters: [...voters, ...result.user_ids]
});
}

componentDidMount() {
this.updateVoters();
}

async componentDidUpdate(prevProps, prevState, snapshot) {
if (prevProps.count !== this.props.count) {
this.updateVoters();
}
}

render() {
const { option, isQuiz } = this.props;
const { voters, count } = this.state;

const { text, voter_count, vote_percentage } = option;
if (voter_count === 0) {
return null;
}

const results = [];
for (let i = 0; i < count; i++) {
const userId = i < voters.length ? voters[i] : null;
results.push(<PollOptionResult key={`${i}_userId=${userId}`} index={i} userId={userId} />);
}

const voterCount = isQuiz
? count === 1
? `${count} answers`
: `${count} answer`
: count === 1
? `${count} votes`
: `${count} vote`;

return (
<>
<div className='poll-option-results-caption'>
<div className='poll-option-results-answer'>{`${text}${vote_percentage}%`}</div>
<div className='poll-option-results-count'>{voterCount}</div>
</div>
{results}
</>
);
}
}

PollOptionResults.propTypes = {
chatId: PropTypes.number.isRequired,
messageId: PropTypes.number.isRequired,
optionId: PropTypes.number.isRequired,
option: PropTypes.object.isRequired,
isQuiz: PropTypes.bool.isRequired
};

export default PollOptionResults;
10 changes: 10 additions & 0 deletions src/Components/Popup/PollResultsDialog.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright (c) 2018-present, Evgeny Nadymov
*
* This source code is licensed under the GPL v.3.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

.poll-results-content {
padding: 0;
}
Loading

0 comments on commit c3525b8

Please sign in to comment.