Skip to content

Commit

Permalink
feat: polls implementation (#2719)
Browse files Browse the repository at this point in the history
* feat: add create poll button and base modal

* feat: successfully create and send a poll

* chore: restructure a bit and provide baseline for component development

* feat: add create poll context

* feat: add list of options

* fix: optimize rendering of poll options

* feat: add radio buttons as well

* fix: actually pass radio button values

* feat: implement draggable list

* chore: introduce reverse index cache as a util

* fix: reshuffling edge case

* chore: clean up the impl of the draggable list

* chore: move poll options creation control in its own component

* chore: make option height configurable

* fix: revert testing changes

* chore: cleanup

* feat: make opening and closing the modal configurable

* fix: android bugs with textinput

* feat: add poll button to native attachment picker as well

* chore: add extra field and validation

* feat: add initial stub poll message ui

* chore: add some values to poll state ui

* fix: infinite setState bug

* feat: add poll options and voting capabilities, see all options modal

* fix: minor bugs

* chore: remove redundant change

* feat: implement progress bar

* fix: offline support issues

* feat: add impl for creating options and comments

* feat: add answers modal

* fix: handle real time updates of answers

* chore: simplify calculations

* feat: implement results screen

* fix: properly handle manual state changes

* chore: cleanup

* feat: move PollInputDialog out of the Poll one

* chore: more cleanup

* chore: refactor and clean up types

* chore: move out PollOption as well

* chore: extract ShowAllOptionsContent

* fix: handle max nb of answers properly

* chore: separate button concerns

* fix: dependency array in hooks

* chore: renaming to be in line with react sdk

* feat: impl poll message design

* feat: result screen styling and logic

* feat: impl full option results design

* feat: impl all poll options design

* feat: impl poll answer list designs

* feat: impl improved poll state management system

* fix: poll activity state edge cases

* fix: ui bug in poll results preview

* fix: closed poll colors

* chore: cleanup

* feat: offline support for polls

* fix: offline storage for polls

* fix: revamp poll context entirely and rely on hooks dependent on it

* fix: thread replies to poll issue

* fix: forgotten issues with new state hook

* chore: refactor show all options button

* chore: refactor poll results

* chore: refactor full option results

* chore: refactor add comment button

* chore: refactor suggest option button

* chore: refactor remained of the modals

* chore: refactor answers list add comment button as well

* chore: refactor end vote button

* feat: add poll previews

* fix: disable polls within threads

* feat: major cleanup and PollButtons configurability

* feat: make poll header configurable

* feat: make entire poll configurable

* feat: make button actions configurable

* fix: remove local db upsertion

* feat: make PollAnswersList configurable

* fix: properly override PollAnswersList

* feat: make PollResults customizable and add minor fixes

* feat: make show all optinos configurable

* feat: make full option results configurable

* chore: unify poll header across poll components

* fix: create poll dialog styles

* feat: add icons in poll modal screens

* fix: filter out empty options

* feat: add duplicate option text validation

* feat: add disabling of poll creation if invalid

* fix: add check for whether max votes per person is enabled

* feat: implement proper channel poll preview

* fix: refactor some customization options in poll creation

* fix: typescript errors

* fix: make poll creation dialog configurable

* fix: ts errors

* feat: add theming to poll content creation

* feat: add theming to poll option creation

* feat: add theming to poll and polloption

* feat: add theming to all options screen

* feat: theming for modal header

* feat: add theming to answers list

* feat: add theming to poll input dialog

* feat: add theming to poll results

* feat: add theming to full option results

* feat: add theming to buttons

* chore: refactor buttons

* fix: missing hook deps

* chore: remove redundant style

* chore: force-link stream-chat-js in ci

* chore: change ci so trigger branch build

* chore: bump yarn.lock in sample app

* feat: add translations for every language

* fix: colors so that theme works

* fix: add fix in SampleApp too

* fix: issue with scrollview

* fix: wrong colors

* fix: all options list screen fixes

* fix: hook dep

* fix: poll votes issue with multiple answers

* fix: odd translations

* fix: revert stream-chat version to force release

* fix: translations and trigger correct build

* fix: broken translation

* fix: tests

* fix: pin stream-chat version to specific commit pointer

* fix: add sampleapp yarn.lock as well

* fix: comments from pr review

* fix: cast vote on option suggestion

* fix: auto focus input dialogs

* fix: preserve own answer in input dialog

* fix: wrap dialogs in keyboard avoiding view

* fix: only allow poll creation when capability is there

* fix: add support for own capabilities

* chore: bump stream-chat-js ref

* fix: long press on poll message issues

* chore: add comment

* chore: move components down to MessagesContext

* chore: add customization option for CreatePollContent

* chore: remove cursor paginator as it is not used

* chore: bump stream-chat-js ref

* fix: answers for anonymous polls

* fix: answer and results list anonymity fixes

* chore: bump stream-chat-js commit ref

* fix: all issues with state store api change

* chore: force sample app to build

* docs: poll documentation and type fixes

* docs: add docs for Poll and PollContent components

* docs: add docs for answers list and results screens

* chore: add docs for more screens and move vote button logic inside

* docs: add full option list docs

* docs: extend docs with more examples and specifications

* docs: add documentation for all of the poll buttons

* docs: add docs for most state hooks and fix channel props

* docs:  finish documenting hooks

* fix: createAndSendPoll data issue

* docs: add poll state overview docs

* docs: add ui cookbook and fix various docs inconsistencies

* fix: lint errors

* fix: pr review changes

* fix: poll styles

* fix: results screen styling fixes

* fix: revert unwanted change

* fix: comp type declarations

* fix: failing vale vocab

* fix: actually fix typo

* bump stream-chat-js to latest

* fix: another vale vocab issue

* fix: failing tst

* chore: revert branch release changes

* chore: add jsdocs and return types for hooks

* fix: component override docs

* docs: finalize docs with answer list customizations

* fix: lint issues

* fix: check for poll creation from channel settings too

* fix: remove unnecessary selector

* fix: lint issues

* fix: channel config edge cases

* fix: type

* fix: update docs with guide on how to enable polls
  • Loading branch information
isekovanic authored Oct 31, 2024
1 parent e81c6bc commit c770854
Show file tree
Hide file tree
Showing 125 changed files with 5,845 additions and 46 deletions.
7 changes: 7 additions & 0 deletions .styles/Vocab/Base/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,10 @@ Async
subscribable
memoizing
Boolean
draggable
sendMessage
overridable
loadMore
pollAnswers
enum
SendMessage
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
A method that will be used as a callback whenever the default `CreatePoll` component back button is pressed in the header. Unless used, it will have no effect if the default `CreatePollContent` is overridden.

| Type |
| ------------ |
| `() => void` |
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
A method that will be used as a callback whenever send button is clicked on the `CreatePoll` modal. If a custom UI is used for `CreatePollContent`, it can be used as an out-of-the-box method to create and send a poll to the `MessageList`.

It expects to receive an argument that conforms to the `CreatePollData` type that can be found [here](https://github.com/GetStream/stream-chat-js/blob/master/src/types.ts).

| Type |
| --------------------------------------------- |
| `(pollData: CreatePollData) => Promise<void>` |
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
A custom UI component used to render the entire poll creation form. It has access to the [`CreatePollContext`](../../../contexts/create-poll-context.mdx) values by default through the `useCreatePollContext` hook.

| Type | Default |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| ComponentType | [`CreatePollContent`](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Poll/CreatePollContent.tsx) |
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
A property used to define the height of the poll options in the `CreatePollContent` draggable list. The items can have a constant and equal height only and this should only be used if custom theming implies that the static height of the items changes. Has no effect if a custom UI for `CreatePollContent` is provided.

| Type |
| ------ |
| number |
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Function called whenever the close button is pressed on the poll creation modal. Has no effect if [`PollCreateContent`](../../../core-components/channel.mdx#createpollcontent) is custom.

| Type |
| -------- |
| function |
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
A boolean signifying whether the poll creation dialog is shown or not. Will always be `false` if [`PollCreateContent`](../../../core-components/channel.mdx#createpollcontent) is custom.

| Type |
| ------- |
| boolean |
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
An instance of the [`Poll` class](https://github.com/GetStream/stream-chat-js/blob/master/src/poll.ts) containing reactive state.

It is used by the underlying `usePollContext`, `usePollStateStore` and `usePollState` hooks to provide us with the reactive `Poll` state.

:::note

If you need the `Poll` instance you may get it from `client.polls.fromState(pollId)`.

:::

| Type |
| ------ |
| object |
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
A boolean value that is responsible for controlling whether the poll creation button is visible or not.

| Type |
| ------- |
| boolean |
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Function called immediately when the poll creation button is clicked in the attachment picker. Can be used to override the default behaviour of the poll creation UI appearing as a Modal.

If overridden, a `payload` is passed containing the `sendMessage` callback from [`MessageInputContext`](../../../../contexts/message-input-context.mdx) is passed, so that [`CreatePoll`](../../../../ui-components/create-poll.mdx)

| Type |
| -------- |
| function |

| Parameter | Description |
| --------- | ----------------- |
| payload | `{ sendMessage }` |
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
A `Component` prop used to render the content of the `Poll` component in `MessageList`.

The component has full access to the entire `Poll` reactive state through the `usePollState` hook.

| Type | Default |
| ------------- | --------------------------------------------------------------------------------------------------------------------- |
| ComponentType | [`PollContent`](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Poll/Poll.tsx) |

#### Props

##### `PollHeader`

A `Component` prop used to render the header of the `PollContent` component.

| Type | Default |
| ------------- | -------------------------------------------------------------------------------------------------------------------- |
| ComponentType | [`PollHeader`](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Poll/Poll.tsx) |

##### `PollButtons`

A `Component` prop used to render the buttons of the `PollContent` component.

| Type | Default |
| ------------- | --------------------------------------------------------------------------------------------------------------------- |
| ComponentType | [`PollButtons`](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Poll/Poll.tsx) |
50 changes: 50 additions & 0 deletions docusaurus/docs/reactnative/contexts/create-poll-context.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
id: create-poll-context
title: CreatePollContext
---

import ClosePollCreationDialog from '../common-content/contexts/create-poll-context/close-poll-creation-dialog.mdx';
import CreateAndSendPoll from '../common-content/contexts/create-poll-context/create-and-send-poll.mdx';
import CreatePollOptionHeight from '../common-content/contexts/create-poll-context/create-poll-option-height.mdx';
import SendMessage from '../common-content/contexts/message-input-context/send_message.mdx';

The `CreatePollContext` is provided by the [`CreatePoll`](../../ui-components/create-poll) component. If you are not familiar with React Context API, please read about it on [React docs](https://reactjs.org/docs/context.html).

The `CreatePollContext` needs to be used within the [`Channel` component](../../core-components/channel) as it depends on the [`MessageInputContext`](./message-input-context.mdx) which is added by it.

## Basic Usage

The `CreatePollContext` can be consumed by any of the child components of `Channel` as following:

```tsx
import { useContext } from 'react';
import { CreatePollContext } from 'stream-chat-react-native';

const value = useContext(CreatePollContext);
```

Alternatively, you can also use the `useCreatePollContext` hook provided by library to consume `CreatePollContext`.

```tsx
import { useCreatePollContext } from 'stream-chat-react-native';

const value = useCreatePollContext();
```

## Value

### <div class="label description">_forwarded from [MessageInputContext](../../contexts/message-input-context#sendmessage)_ props</div> sendMessage {#sendmessage}

<SendMessage />

### `closePollCreationDialog`

<ClosePollCreationDialog />

### `createAndSendPoll`

<CreateAndSendPoll />

### `createPollOptionHeight`

<CreatePollOptionHeight />
10 changes: 10 additions & 0 deletions docusaurus/docs/reactnative/contexts/message-input-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ import UploadImage from '../common-content/contexts/message-input-context/upload
import UpdateMessage from '../common-content/contexts/message-input-context/update_message.mdx';
import UploadNewFile from '../common-content/contexts/message-input-context/upload_new_file.mdx';
import UploadNewImage from '../common-content/contexts/message-input-context/upload_new_image.mdx';
import ClosePollCreationDialog from '../common-content/contexts/message-input-context/close-poll-creation-dialog.mdx';
import ShowPollCreationDialog from '../common-content/contexts/message-input-context/show-poll-creation-dialog.mdx';

`MessageInputContext` is provided by [`Channel`](../../core-components/channel) component. If you are not familiar with React Context API, please read about it on [React docs](https://reactjs.org/docs/context.html).

Expand Down Expand Up @@ -490,3 +492,11 @@ const { sendMessage, toggleAttachmentPicker } = useMessageInputContext();
### <div class="label description">_forwarded from [Channel](../../core-components/channel#uploadprogressindicator)_ props</div> UploadProgressIndicator {#uploadprogressindicator}

<UploadProgressIndicator />

### `closePollCreationDialog`

<ClosePollCreationDialog />

### `showPollCreationDialog`

<ShowPollCreationDialog />
16 changes: 15 additions & 1 deletion docusaurus/docs/reactnative/contexts/messages-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import InitialScrollToFirstUnreadMessage from '../common-content/ui-components/c
import InlineDateSeparator from '../common-content/ui-components/channel/props/inline_date_separator.mdx';
import InlineUnreadIndicator from '../common-content/ui-components/channel/props/inline_unread_indicator.mdx';
import IsAttachmentEqual from '../common-content/ui-components/channel/props/is_attachment_equal.mdx';
import LegacyImageViewerSwipeBehaviour from '../common-content/ui-components/channel/props/legacy_image_viewer_swipe_behaviour.mdx';
import MarkdownRules from '../common-content/ui-components/channel/props/markdown_rules.mdx';
import MessageAvatar from '../common-content/ui-components/channel/props/message-avatar.mdx';
import MessageBounce from '../common-content/ui-components/channel/props/message-bounce.mdx';
Expand Down Expand Up @@ -73,6 +72,9 @@ import TypingIndicator from '../common-content/ui-components/channel/props/typin
import TypingIndicatorContainer from '../common-content/ui-components/channel/props/typing_indicator_container.mdx';
import UrlPreview from '../common-content/ui-components/channel/props/url_preview.mdx';
import VideoThumbnail from '../common-content/ui-components/channel/props/video_thumbnail.mdx';
import OpenPollCreationDialog from '../common-content/ui-components/channel/props/open-poll-creation-dialog.mdx';
import HasCreatePoll from '../common-content/ui-components/channel/props/has-create-poll.mdx';
import PollContent from '../common-content/ui-components/poll/poll-content.mdx';

## Value

Expand Down Expand Up @@ -260,6 +262,14 @@ Upserts a given message in local channel state. Please note that this function d
| ------------------- |
| `(message) => void` |

### <div class="label description">_forwarded from [Channel](../../core-components/channel#openpollcreationdialog)_ props</div> openPollCreationDialog {#openPollCreationDialog}

<OpenPollCreationDialog />

### <div class="label description">_forwarded from [Channel](../../core-components/channel#hascreatepoll)_ props</div> hasCreatePoll {#hascreatepoll}

<HasCreatePoll />

### <div class="label description">_forwarded from [Channel](../../core-components/channel#attachment)_ props</div> Attachment {#attachment}

<Attachment />
Expand Down Expand Up @@ -419,3 +429,7 @@ Upserts a given message in local channel state. Please note that this function d
### <div class="label description">_forwarded from [Channel](../../core-components/channel#videothumbnail)_ props</div> VideoThumbnail {#videoThumbnail}

<VideoThumbnail />

### <div class="label description">_forwarded from [Channel](../../core-components/channel#pollcontent)_ props</div> PollContent {#pollcontent}

<PollContent />
24 changes: 24 additions & 0 deletions docusaurus/docs/reactnative/contexts/own-capabilities-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,27 @@ Ability to upload message attachments.
| Type |
| ------- |
| boolean |

### `sendPoll`

Ability to send polls as messages.

| Type |
| ------- |
| boolean |

### `queryPollVotes`

Ability to query for the votes of polls.

| Type |
| ------- |
| boolean |

### `castPollVote`

Ability to cast a vote on polls.

| Type |
| ------- |
| boolean |
40 changes: 40 additions & 0 deletions docusaurus/docs/reactnative/contexts/poll-context.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
id: poll-context
title: PollContext
---

import MessageProp from '../common-content/contexts/message-context/message.mdx';
import Poll from '../common-content/contexts/poll-context/poll.mdx';

The `PollContext` is provided by the [`Poll`](../../ui-components/poll) component. If you are not familiar with React Context API, please read about it on [React docs](https://reactjs.org/docs/context.html).

The `PollContext` needs to be used within the [`Channel` component](../../core-components/channel) as it depends on various values provided by it in order to work.

## Basic Usage

The `PollContext` can be consumed by any of the child components of `Channel` as following:

```tsx
import { useContext } from 'react';
import { CreatePollContext } from 'stream-chat-react-native';

const value = useContext(PollContext);
```

Alternatively, you can also use the `usePollContext` hook provided by library to consume `PollContext`.

```tsx
import { usePollContext } from 'stream-chat-react-native';

const value = usePollContext();
```

## Value

### <div class="label description">_forwarded from [MessageContext](../../contexts/message-context#message)_ props</div> message {#message}

<MessageProp />

### `poll` \*

<Poll />
20 changes: 20 additions & 0 deletions docusaurus/docs/reactnative/core-components/channel.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ import ThreadList from '../common-content/ui-components/channel/props/thread_lis
import TypingIndicator from '../common-content/ui-components/channel/props/typing_indicator.mdx';
import TypingIndicatorContainer from '../common-content/ui-components/channel/props/typing_indicator_container.mdx';
import UrlPreview from '../common-content/ui-components/channel/props/url_preview.mdx';
import CreatePollContent from '../common-content/contexts/create-poll-context/create-poll-content.mdx';
import OpenPollCreationDialog from '../common-content/ui-components/channel/props/open-poll-creation-dialog.mdx';
import HasCreatePoll from '../common-content/ui-components/channel/props/has-create-poll.mdx';
import PollContent from '../common-content/ui-components/poll/poll-content.mdx';

The `Channel` component is the main entry point for many Stream Chat customizations and contains the majority of the content providers and a significant amount of the logic utilized by Stream Chat for React Native.
Components, custom and out of the box, channel information, and UI integrated chat functions are disseminated by the contexts contained in `Channel`.
Expand Down Expand Up @@ -727,6 +731,14 @@ Callback function to set the [ref](https://reactjs.org/docs/refs-and-the-dom.htm

<ThreadList />

### `openPollCreationDialog`

<OpenPollCreationDialog />

### `hasCreatePoll`

<HasCreatePoll />

<!-- ### updateSuggestions -->

## UI Components Props
Expand Down Expand Up @@ -1028,3 +1040,11 @@ Component to render upload progress indicator as an overlay above [ImageUploadPr
### UrlPreview

<UrlPreview />

### CreatePollContent

<CreatePollContent />

### PollContent

<PollContent />
Loading

0 comments on commit c770854

Please sign in to comment.