Skip to content

Commit

Permalink
Merge pull request #2746 from GetStream/develop
Browse files Browse the repository at this point in the history
Next Release
  • Loading branch information
isekovanic authored Oct 31, 2024
2 parents f7b23b5 + 45e5959 commit b19d479
Show file tree
Hide file tree
Showing 13 changed files with 112 additions and 120 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
[![NPM](https://img.shields.io/npm/v/stream-chat-react-native.svg)](https://www.npmjs.com/package/stream-chat-react-native)
[![Build Status](https://github.com/GetStream/stream-chat-react-native/actions/workflows/release.yml/badge.svg)](https://github.com/GetStream/stream-chat-react-native/actions)
[![Component Reference](https://img.shields.io/badge/docs-component%20reference-blue.svg)](https://getstream.io/chat/docs/sdk/reactnative)
![JS Bundle Size](https://img.shields.io/badge/js_bundle_size-447%20KB-blue)
![JS Bundle Size](https://img.shields.io/badge/js_bundle_size-451%20KB-blue)

<img align="right" src="https://getstream.imgix.net/images/ios-chat-tutorial/[email protected]?auto=format,enhance" width="50%" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ import { PollVote, PollState } from 'stream-chat';
import { usePollStateStore } from 'stream-chat-react-native';

type PollOptionSelectorReturnValue = {
latest_votes_by_option: Record<string, PollVote[]>;
latestVotesByOption: Record<string, PollVote[]>;
maxVotedOptionIds: string[];
};

const selector = <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(
nextValue: PollState<StreamChatGenerics>,
): PollOptionSelectorReturnValue => ({
latest_votes_by_option: nextValue.latest_votes_by_option,
latestVotesByOption: nextValue.latestVotesByOption,
maxVotedOptionIds: nextValue.maxVotedOptionIds,
});

const { latest_votes_by_option, maxVotedOptionIds } = usePollStateStore(selector);
const { latestVotesByOption, maxVotedOptionIds } = usePollStateStore(selector);
```
14 changes: 7 additions & 7 deletions docusaurus/docs/reactnative/hooks/poll/use-poll-state.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,23 @@ It is highly recommended that the user familiarizes themselves with the [`Poll`

The `usePollState` hook returns an object containing values from the `PollState`.

### `allow_answers`
### `allowAnswers`

A property depicting whether answers (comments) are allowed to the `poll`.

| Type |
| --------- | ----------- |
| `boolean` | `undefined` |

### `allow_user_suggested_options`
### `allowUserSuggestedOptions`

A property depicting whether user option suggestions are allowed to the `poll`.

| Type |
| --------- | ----------- |
| `boolean` | `undefined` |

### `answers_count`
### `answersCount`

A property containing the number of answers (comments) to the `poll`.

Expand All @@ -49,7 +49,7 @@ This property will be `null` for anonymous polls.
| -------- | ------ |
| `object` | `null` |

### `enforce_unique_vote`
### `enforceUniqueVote`

A property depicting whether each user should have only one and unique vote or they would be able to vote multiple times during the lifespan of a `poll`.

Expand All @@ -65,7 +65,7 @@ A property depicting whether the `poll` is still open for voting or not.
| --------- |
| `boolean` |

### `latest_votes_by_option`
### `latestVotesByOption`

A property containing the latest votes for each option stored in an object by option ID. Only the last 10 votes are maintained here. If all votes are needed for an option, the [`usePollOptionVotesPagination`](./use-poll-option-votes-pagination.mdx) hook should be used instead.

Expand Down Expand Up @@ -123,15 +123,15 @@ A property containing the current user's own votes in a given `poll`, stored in
| -------------------------- |
| `Record<string, PollVote>` |

### `vote_counts_by_option`
### `voteCountsByOption`

A property containing the vote counts in a given `poll`, stored in an object by option ID.

| Type |
| ------------------------ |
| `Record<string, number>` |

### `voting_visibility`
### `votingVisibility`

A property depicting the visibility of votes in a given `poll`. It conforms to the `VotingVisibility` enum found [here](https://github.com/GetStream/stream-chat-js/blob/b447512922b19bc7e3668bd9df81debcb673dd81/src/types.ts).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ export type LatestMessagePreview<
};

export type LatestMessagePreviewSelectorReturnType = {
created_by?: UserResponse | null;
latest_votes_by_option?: Record<string, PollVote[]>;
createdBy?: UserResponse | null;
latestVotesByOption?: Record<string, PollVote[]>;
};

const selector = <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(
nextValue: PollState<StreamChatGenerics>,
): LatestMessagePreviewSelectorReturnType => ({
created_by: nextValue.created_by,
latest_votes_by_option: nextValue.latest_votes_by_option,
createdBy: nextValue.created_by,
latestVotesByOption: nextValue.latest_votes_by_option,
});

const getMessageSenderName = <
Expand Down Expand Up @@ -146,15 +146,15 @@ const getLatestMessageDisplayText = <
];
}
if (message.poll && pollState) {
const { created_by, latest_votes_by_option } = pollState;
const { createdBy, latestVotesByOption } = pollState;
let latestVotes;
if (latest_votes_by_option) {
latestVotes = Object.values(latest_votes_by_option)
if (latestVotesByOption) {
latestVotes = Object.values(latestVotesByOption)
.map((votes) => votes?.[0])
.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
}
let previewAction = 'created';
let previewUser = created_by;
let previewUser = createdBy;
if (latestVotes && latestVotes.length && latestVotes[0]?.user) {
previewAction = 'voted';
previewUser = latestVotes[0]?.user;
Expand Down Expand Up @@ -310,7 +310,7 @@ export const useLatestMessagePreview = <
const poll = client.polls.fromState(pollId);
const pollState: LatestMessagePreviewSelectorReturnType =
useStateStore(poll?.state, selector) ?? {};
const { created_by, latest_votes_by_option } = pollState;
const { createdBy, latestVotesByOption } = pollState;

useEffect(
() =>
Expand All @@ -325,14 +325,7 @@ export const useLatestMessagePreview = <
}),
),
// eslint-disable-next-line react-hooks/exhaustive-deps
[
channelLastMessageString,
forceUpdate,
readEvents,
readStatus,
latest_votes_by_option,
created_by,
],
[channelLastMessageString, forceUpdate, readEvents, readStatus, latestVotesByOption, createdBy],
);

return latestMessagePreview;
Expand Down
10 changes: 5 additions & 5 deletions package/src/components/Poll/Poll.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ export const PollButtons = () => (

export const PollHeader = () => {
const { t } = useTranslationContext();
const { enforce_unique_vote, is_closed, max_votes_allowed, name } = usePollState();
const { enforceUniqueVote, isClosed, maxVotesAllowed, name } = usePollState();
const subtitle = useMemo(() => {
if (is_closed) return t('Vote ended');
if (enforce_unique_vote) return t('Select one');
if (max_votes_allowed) return t('Select up to {{count}}', { count: max_votes_allowed });
if (isClosed) return t('Vote ended');
if (enforceUniqueVote) return t('Select one');
if (maxVotesAllowed) return t('Select up to {{count}}', { count: maxVotesAllowed });
return t('Select one or more');
}, [is_closed, t, enforce_unique_vote, max_votes_allowed]);
}, [isClosed, t, enforceUniqueVote, maxVotesAllowed]);

const {
theme: {
Expand Down
28 changes: 14 additions & 14 deletions package/src/components/Poll/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,18 @@ export const ViewResultsButton = (props: PollButtonProps) => {

export const EndVoteButton = () => {
const { t } = useTranslationContext();
const { created_by, endVote, is_closed } = usePollState();
const { createdBy, endVote, isClosed } = usePollState();
const { client } = useChatContext();

return !is_closed && created_by?.id === client.userID ? (
return !isClosed && createdBy?.id === client.userID ? (
<GenericPollButton onPress={endVote} title={t<string>('End Vote')} />
) : null;
};

export const AddCommentButton = (props: PollButtonProps) => {
const { t } = useTranslationContext();
const { message, poll } = usePollContext();
const { addComment, allow_answers, is_closed, ownAnswer } = usePollState();
const { addComment, allowAnswers, isClosed, ownAnswer } = usePollState();
const [showAddCommentDialog, setShowAddCommentDialog] = useState(false);
const { onPress } = props;

Expand All @@ -141,7 +141,7 @@ export const AddCommentButton = (props: PollButtonProps) => {

return (
<>
{!is_closed && allow_answers ? (
{!isClosed && allowAnswers ? (
<GenericPollButton onPress={onPressHandler} title={t<string>('Add a comment')} />
) : null}
{showAddCommentDialog ? (
Expand All @@ -160,7 +160,7 @@ export const AddCommentButton = (props: PollButtonProps) => {
export const ShowAllCommentsButton = (props: PollButtonProps) => {
const { t } = useTranslationContext();
const { message, poll } = usePollContext();
const { answers_count } = usePollState();
const { answersCount } = usePollState();
const [showAnswers, setShowAnswers] = useState(false);
const { onPress } = props;

Expand All @@ -181,10 +181,10 @@ export const ShowAllCommentsButton = (props: PollButtonProps) => {

return (
<>
{answers_count && answers_count > 0 ? (
{answersCount && answersCount > 0 ? (
<GenericPollButton
onPress={onPressHandler}
title={t<string>('View {{count}} comments', { count: answers_count })}
title={t<string>('View {{count}} comments', { count: answersCount })}
/>
) : null}
{showAnswers ? (
Expand Down Expand Up @@ -262,7 +262,7 @@ export const AnswerListAddCommentButton = (props: PollButtonProps) => {
export const SuggestOptionButton = (props: PollButtonProps) => {
const { t } = useTranslationContext();
const { message, poll } = usePollContext();
const { addOption, allow_user_suggested_options, is_closed } = usePollState();
const { addOption, allowUserSuggestedOptions, isClosed } = usePollState();
const [showAddOptionDialog, setShowAddOptionDialog] = useState(false);
const { onPress } = props;

Expand All @@ -277,7 +277,7 @@ export const SuggestOptionButton = (props: PollButtonProps) => {

return (
<>
{!is_closed && allow_user_suggested_options ? (
{!isClosed && allowUserSuggestedOptions ? (
<GenericPollButton onPress={onPressHandler} title={t<string>('Suggest an option')} />
) : null}
{showAddOptionDialog ? (
Expand Down Expand Up @@ -343,7 +343,7 @@ export const ShowAllOptionsButton = (props: PollButtonProps) => {

export const VoteButton = ({ onPress, option }: PollVoteButtonProps) => {
const { message, poll } = usePollContext();
const { is_closed, ownVotesByOptionId } = usePollState();
const { isClosed, ownVotesByOptionId } = usePollState();
const ownCapabilities = useOwnCapabilitiesContext();

const {
Expand Down Expand Up @@ -374,7 +374,7 @@ export const VoteButton = ({ onPress, option }: PollVoteButtonProps) => {
toggleVote();
}, [message, onPress, poll, toggleVote]);

return ownCapabilities.castPollVote && !is_closed ? (
return ownCapabilities.castPollVote && !isClosed ? (
<TouchableOpacity
onPress={onPressHandler}
style={[
Expand All @@ -398,7 +398,7 @@ export const VoteButton = ({ onPress, option }: PollVoteButtonProps) => {
export const ShowAllVotesButton = (props: ShowAllVotesButtonProps) => {
const { t } = useTranslationContext();
const { message, poll } = usePollContext();
const { vote_counts_by_option } = usePollState();
const { voteCountsByOption } = usePollState();
const ownCapabilities = useOwnCapabilitiesContext();
const [showAllVotes, setShowAllVotes] = useState(false);
const { onPress, option } = props;
Expand All @@ -421,8 +421,8 @@ export const ShowAllVotesButton = (props: ShowAllVotesButtonProps) => {
return (
<>
{ownCapabilities.queryPollVotes &&
vote_counts_by_option &&
vote_counts_by_option?.[option.id] > 5 ? (
voteCountsByOption &&
voteCountsByOption?.[option.id] > 5 ? (
<GenericPollButton onPress={onPressHandler} title={t<string>('Show All')} />
) : null}
{showAllVotes ? (
Expand Down
6 changes: 3 additions & 3 deletions package/src/components/Poll/components/PollAnswersList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type PollAnswersListProps<

export const PollAnswerListItem = ({ answer }: { answer: PollAnswer }) => {
const { t, tDateTimeParser } = useTranslationContext();
const { voting_visibility } = usePollState();
const { votingVisibility } = usePollState();

const {
theme: {
Expand All @@ -49,8 +49,8 @@ export const PollAnswerListItem = ({ answer }: { answer: PollAnswer }) => {
);

const isAnonymous = useMemo(
() => voting_visibility === VotingVisibility.anonymous,
[voting_visibility],
() => votingVisibility === VotingVisibility.anonymous,
[votingVisibility],
);

return (
Expand Down
21 changes: 8 additions & 13 deletions package/src/components/Poll/components/PollOption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,18 @@ export const PollAllOptions = ({
);

export const PollOption = ({ option, showProgressBar = true }: PollOptionProps) => {
const { is_closed, latest_votes_by_option, maxVotedOptionIds, vote_counts_by_option } =
usePollState();
const { isClosed, latestVotesByOption, maxVotedOptionIds, voteCountsByOption } = usePollState();

const relevantVotes = useMemo(
() => latest_votes_by_option?.[option.id]?.slice(0, 2) || [],
[latest_votes_by_option, option.id],
() => latestVotesByOption?.[option.id]?.slice(0, 2) || [],
[latestVotesByOption, option.id],
);
const maxVotes = useMemo(
() =>
maxVotedOptionIds?.[0] && vote_counts_by_option
? vote_counts_by_option[maxVotedOptionIds[0]]
: 0,
[maxVotedOptionIds, vote_counts_by_option],
maxVotedOptionIds?.[0] && voteCountsByOption ? voteCountsByOption[maxVotedOptionIds[0]] : 0,
[maxVotedOptionIds, voteCountsByOption],
);
const votes = vote_counts_by_option[option.id] || 0;
const votes = voteCountsByOption[option.id] || 0;

const {
theme: {
Expand Down Expand Up @@ -118,17 +115,15 @@ export const PollOption = ({ option, showProgressBar = true }: PollOptionProps)
{relevantVotes.map((vote: PollVote) => (
<Avatar image={vote.user?.image as string} key={vote.id} size={20} />
))}
<Text style={{ color: black, marginLeft: 2 }}>
{vote_counts_by_option[option.id] || 0}
</Text>
<Text style={{ color: black, marginLeft: 2 }}>{voteCountsByOption[option.id] || 0}</Text>
</View>
</View>
{showProgressBar ? (
<View style={[styles.progressBar, progressBar]}>
<View
style={{
backgroundColor:
is_closed && maxVotedOptionIds.length === 1 && maxVotedOptionIds[0] === option.id
isClosed && maxVotedOptionIds.length === 1 && maxVotedOptionIds[0] === option.id
? progressBarWinnerFill || accent_info
: progressBarVotedFill || accent_dark_blue,
flex: maxVotes > 0 ? votes / maxVotes : 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type PollOptionFullResultsProps<
};

export const PollOptionFullResultsItem = ({ item }: { item: PollVoteClass }) => (
<PollVote {...item} />
<PollVote vote={item} />
);

export const PollOptionFullResultsContent = ({
Expand All @@ -33,7 +33,7 @@ export const PollOptionFullResultsContent = ({
}: Pick<PollOptionFullResultsProps, 'option' | 'additionalFlatListProps'>) => {
const { t } = useTranslationContext();
const { hasNextPage, loadMore, votes } = usePollOptionVotesPagination({ option });
const { vote_counts_by_option } = usePollState();
const { voteCountsByOption } = usePollState();

const {
theme: {
Expand All @@ -48,11 +48,11 @@ export const PollOptionFullResultsContent = ({
() => (
<View style={[styles.headerContainer, headerContainer]}>
<Text style={[styles.headerText, { color: black }, headerText]}>
{t<string>('{{count}} votes', { count: vote_counts_by_option[option.id] ?? 0 })}
{t<string>('{{count}} votes', { count: voteCountsByOption[option.id] ?? 0 })}
</Text>
</View>
),
[black, headerContainer, headerText, option.id, t, vote_counts_by_option],
[black, headerContainer, headerText, option.id, t, voteCountsByOption],
);

return (
Expand Down
Loading

0 comments on commit b19d479

Please sign in to comment.