diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/answer-list-navigation.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/answer-list-navigation.png new file mode 100644 index 000000000..6c549ee94 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/answer-list-navigation.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/attachment-picker-poll-button.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/attachment-picker-poll-button.png new file mode 100644 index 000000000..d4cf37995 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/attachment-picker-poll-button.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-answers-list.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-answers-list.png new file mode 100644 index 000000000..0c32c8fe2 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-answers-list.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-comments-creation-1.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-comments-creation-1.png new file mode 100644 index 000000000..74c863630 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-comments-creation-1.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-comments-creation-2.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-comments-creation-2.png new file mode 100644 index 000000000..912e33fb3 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-comments-creation-2.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-creation-1.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-creation-1.png new file mode 100644 index 000000000..e28a9cea0 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-creation-1.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-creation-2.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-creation-2.png new file mode 100644 index 000000000..3d4b83a61 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-creation-2.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-poll-background.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-poll-background.png new file mode 100644 index 000000000..0f06d61e2 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-poll-background.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-results-title.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-results-title.png new file mode 100644 index 000000000..055d340ab Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-results-title.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-results.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-results.png new file mode 100644 index 000000000..59d1a57ce Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-results.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-step-1-1.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-step-1-1.png new file mode 100644 index 000000000..afa0f50eb Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-step-1-1.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-step-1-2.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-step-1-2.png new file mode 100644 index 000000000..1b0673793 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/custom-step-1-2.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/default-ui-1.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/default-ui-1.png new file mode 100644 index 000000000..31a8eb72a Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/default-ui-1.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/default-ui-2.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/default-ui-2.png new file mode 100644 index 000000000..a86a60847 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/default-ui-2.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/default-ui-3.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/default-ui-3.png new file mode 100644 index 000000000..59245029c Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/default-ui-3.png differ diff --git a/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/enable-polls.png b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/enable-polls.png new file mode 100644 index 000000000..82fefd237 Binary files /dev/null and b/docusaurus/docs/reactnative/assets/guides/custom-poll-flow/enable-polls.png differ diff --git a/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/close-poll-creation-dialog.mdx b/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/close-poll-creation-dialog.mdx new file mode 100644 index 000000000..911ae371d --- /dev/null +++ b/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/close-poll-creation-dialog.mdx @@ -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` | diff --git a/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/create-and-send-poll.mdx b/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/create-and-send-poll.mdx new file mode 100644 index 000000000..9112949d1 --- /dev/null +++ b/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/create-and-send-poll.mdx @@ -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` | diff --git a/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/create-poll-content.mdx b/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/create-poll-content.mdx new file mode 100644 index 000000000..23d12f657 --- /dev/null +++ b/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/create-poll-content.mdx @@ -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) | diff --git a/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/create-poll-option-height.mdx b/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/create-poll-option-height.mdx new file mode 100644 index 000000000..c9a1e65bc --- /dev/null +++ b/docusaurus/docs/reactnative/common-content/contexts/create-poll-context/create-poll-option-height.mdx @@ -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 | diff --git a/docusaurus/docs/reactnative/common-content/contexts/message-input-context/close-poll-creation-dialog.mdx b/docusaurus/docs/reactnative/common-content/contexts/message-input-context/close-poll-creation-dialog.mdx new file mode 100644 index 000000000..0c885ef61 --- /dev/null +++ b/docusaurus/docs/reactnative/common-content/contexts/message-input-context/close-poll-creation-dialog.mdx @@ -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 | diff --git a/docusaurus/docs/reactnative/common-content/contexts/message-input-context/show-poll-creation-dialog.mdx b/docusaurus/docs/reactnative/common-content/contexts/message-input-context/show-poll-creation-dialog.mdx new file mode 100644 index 000000000..00bf17abc --- /dev/null +++ b/docusaurus/docs/reactnative/common-content/contexts/message-input-context/show-poll-creation-dialog.mdx @@ -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 | diff --git a/docusaurus/docs/reactnative/common-content/contexts/poll-context/poll.mdx b/docusaurus/docs/reactnative/common-content/contexts/poll-context/poll.mdx new file mode 100644 index 000000000..ad66595ea --- /dev/null +++ b/docusaurus/docs/reactnative/common-content/contexts/poll-context/poll.mdx @@ -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 | diff --git a/docusaurus/docs/reactnative/common-content/ui-components/channel/props/has-create-poll.mdx b/docusaurus/docs/reactnative/common-content/ui-components/channel/props/has-create-poll.mdx new file mode 100644 index 000000000..c7502ec7d --- /dev/null +++ b/docusaurus/docs/reactnative/common-content/ui-components/channel/props/has-create-poll.mdx @@ -0,0 +1,5 @@ +A boolean value that is responsible for controlling whether the poll creation button is visible or not. + +| Type | +| ------- | +| boolean | diff --git a/docusaurus/docs/reactnative/common-content/ui-components/channel/props/open-poll-creation-dialog.mdx b/docusaurus/docs/reactnative/common-content/ui-components/channel/props/open-poll-creation-dialog.mdx new file mode 100644 index 000000000..7ca547b50 --- /dev/null +++ b/docusaurus/docs/reactnative/common-content/ui-components/channel/props/open-poll-creation-dialog.mdx @@ -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 }` | diff --git a/docusaurus/docs/reactnative/common-content/ui-components/poll/poll-content.mdx b/docusaurus/docs/reactnative/common-content/ui-components/poll/poll-content.mdx new file mode 100644 index 000000000..63f0e1116 --- /dev/null +++ b/docusaurus/docs/reactnative/common-content/ui-components/poll/poll-content.mdx @@ -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) | diff --git a/docusaurus/docs/reactnative/contexts/create-poll-context.mdx b/docusaurus/docs/reactnative/contexts/create-poll-context.mdx new file mode 100644 index 000000000..a85257148 --- /dev/null +++ b/docusaurus/docs/reactnative/contexts/create-poll-context.mdx @@ -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 + +###
_forwarded from [MessageInputContext](../../contexts/message-input-context#sendmessage)_ props
sendMessage {#sendmessage} + + + +### `closePollCreationDialog` + + + +### `createAndSendPoll` + + + +### `createPollOptionHeight` + + diff --git a/docusaurus/docs/reactnative/contexts/message-input-context.mdx b/docusaurus/docs/reactnative/contexts/message-input-context.mdx index 73319587c..b73f013bc 100644 --- a/docusaurus/docs/reactnative/contexts/message-input-context.mdx +++ b/docusaurus/docs/reactnative/contexts/message-input-context.mdx @@ -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). @@ -490,3 +492,11 @@ const { sendMessage, toggleAttachmentPicker } = useMessageInputContext(); ###
_forwarded from [Channel](../../core-components/channel#uploadprogressindicator)_ props
UploadProgressIndicator {#uploadprogressindicator} + +### `closePollCreationDialog` + + + +### `showPollCreationDialog` + + diff --git a/docusaurus/docs/reactnative/contexts/messages-context.mdx b/docusaurus/docs/reactnative/contexts/messages-context.mdx index 5ace299ae..626cfb060 100644 --- a/docusaurus/docs/reactnative/contexts/messages-context.mdx +++ b/docusaurus/docs/reactnative/contexts/messages-context.mdx @@ -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'; @@ -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 @@ -260,6 +262,14 @@ Upserts a given message in local channel state. Please note that this function d | ------------------- | | `(message) => void` | +###
_forwarded from [Channel](../../core-components/channel#openpollcreationdialog)_ props
openPollCreationDialog {#openPollCreationDialog} + + + +###
_forwarded from [Channel](../../core-components/channel#hascreatepoll)_ props
hasCreatePoll {#hascreatepoll} + + + ###
_forwarded from [Channel](../../core-components/channel#attachment)_ props
Attachment {#attachment} @@ -419,3 +429,7 @@ Upserts a given message in local channel state. Please note that this function d ###
_forwarded from [Channel](../../core-components/channel#videothumbnail)_ props
VideoThumbnail {#videoThumbnail} + +###
_forwarded from [Channel](../../core-components/channel#pollcontent)_ props
PollContent {#pollcontent} + + diff --git a/docusaurus/docs/reactnative/contexts/own-capabilities-context.mdx b/docusaurus/docs/reactnative/contexts/own-capabilities-context.mdx index 1e60f3409..143b902d1 100644 --- a/docusaurus/docs/reactnative/contexts/own-capabilities-context.mdx +++ b/docusaurus/docs/reactnative/contexts/own-capabilities-context.mdx @@ -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 | diff --git a/docusaurus/docs/reactnative/contexts/poll-context.mdx b/docusaurus/docs/reactnative/contexts/poll-context.mdx new file mode 100644 index 000000000..fa2dbc233 --- /dev/null +++ b/docusaurus/docs/reactnative/contexts/poll-context.mdx @@ -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 + +###
_forwarded from [MessageContext](../../contexts/message-context#message)_ props
message {#message} + + + +### `poll` \* + + diff --git a/docusaurus/docs/reactnative/core-components/channel.mdx b/docusaurus/docs/reactnative/core-components/channel.mdx index cc3c35334..21a19744f 100644 --- a/docusaurus/docs/reactnative/core-components/channel.mdx +++ b/docusaurus/docs/reactnative/core-components/channel.mdx @@ -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`. @@ -727,6 +731,14 @@ Callback function to set the [ref](https://reactjs.org/docs/refs-and-the-dom.htm +### `openPollCreationDialog` + + + +### `hasCreatePoll` + + + ## UI Components Props @@ -1028,3 +1040,11 @@ Component to render upload progress indicator as an overlay above [ImageUploadPr ### UrlPreview + +### CreatePollContent + + + +### PollContent + + diff --git a/docusaurus/docs/reactnative/guides/custom-poll-flow.mdx b/docusaurus/docs/reactnative/guides/custom-poll-flow.mdx new file mode 100644 index 000000000..8d7495ce3 --- /dev/null +++ b/docusaurus/docs/reactnative/guides/custom-poll-flow.mdx @@ -0,0 +1,725 @@ +--- +id: custom-poll-flow +title: Custom Poll Flow +--- + +import DefaultUI1 from '../assets/guides/custom-poll-flow/default-ui-1.png'; +import DefaultUI2 from '../assets/guides/custom-poll-flow/default-ui-2.png'; +import DefaultUI3 from '../assets/guides/custom-poll-flow/default-ui-3.png'; + +import CustomStep11 from '../assets/guides/custom-poll-flow/custom-step-1-1.png'; +import CustomStep12 from '../assets/guides/custom-poll-flow/custom-step-1-2.png'; + +import CustomCreation1 from '../assets/guides/custom-poll-flow/custom-creation-1.png'; +import CustomCreation2 from '../assets/guides/custom-poll-flow/custom-creation-2.png'; + +import CustomCommentsCreation1 from '../assets/guides/custom-poll-flow/custom-comments-creation-1.png'; +import CustomCommentsCreation2 from '../assets/guides/custom-poll-flow/custom-comments-creation-2.png'; + +In this cookbook we'll go over how we can create and customize a `Channel` screen containing the [`Poll` component](../ui-components/poll.mdx), along with adding navigation to all of its underlying screens rather than relying on modals. + +### Prerequisites + +This cookbook assumes that you've already set up a screen that is able to display a `Channel` with a `MessageList` inside. As `poll`s are tightly coupled with messages, we need to have this working before we add the `poll` message type. + +Polls are disabled by default and can be enabled through the Stream Dashboard by toggling the `Poll` button. + +![Enable Polls](../assets/guides/custom-poll-flow/enable-polls.png) + +Doing that will include the `Poll` button in your attachment picker: + +![Enable Polls](../assets/guides/custom-poll-flow/attachment-picker-poll-button.png) + +It also assumes that you have a functioning `chatClient` that is used elsewhere. + +For illustration purposes, we are going to be using the `React Navigation` library for navigation (however, any navigation library can be used). + +### The initial UI + +Without doing any form of customization yet, we should have something similar to the following: + +```tsx +import { OverlayProvider, Chat, Channel, MessageList, MessageInput } from 'stream-chat-react-native'; + +const ChannelScreen = () => { + return ( + + + + + + + + + + ); +}; +``` + +and the `poll` creation flow should come out of the box with its default UI: + +
+ Default UI 1 + Default UI 2 + Default UI 3 +
+ +At this point, let's try to customize the `Poll` component within the message. To do this, we can set the `PollContent` prop on our `Channel` component. + +For now, we want to remove the `Poll` header and modify the behaviour of the buttons at the bottom. To do this, we can reuse the default `PollContent` component exported by the SDK that allows us to do modifications. + +Additionally, we can reuse all of the buttons that we need and modify the ones that we want to do something else. + +```tsx +import { + OverlayProvider, + Chat, + Channel, + MessageList, + MessageInput, + // highlight-next-line + PollContent, +} from 'stream-chat-react-native'; + +// highlight-start +const MyPollButtons = () => { + return ( + <> + + Alert.alert(`Message ID: ${message.id} and Poll ID: ${poll.id}`)} + /> + + + ); +}; + +const MyPollContent = () => null} PollButtons={MyPollButtons} />; +// highlight-end + +const ChannelScreen = () => { + return ( + + + // highlight-next-line + + + + + + + + ); +}; +``` + +
+ Step 1-1 + Step 1-2 +
+ +As we can see, now we only display 2 buttons at the bottom, which are the `View Results` and `End Vote` ones. Clicking on the `View Results` button displays an `Alert` with some information about the `Poll` instead of opening the modal. + +At this point we might realize that we no longer have access to the `PollResults` screen anymore. So, let's bring it back. However, we do not want to use the default navigation which is based on [React Native Modals](https://reactnative.dev/docs/modal), but rather introduce our own navigation. + +To do this, let's rely on `React Navigation`. Since we need all of the `Poll` screens to also be children of the `Channel` component, we can introduce an additional `Stack` navigator that would take care of this. + +```tsx +import { OverlayProvider, Chat, Channel, MessageList, MessageInput, PollContent } from 'stream-chat-react-native'; +// highlight-next-line +import { createStackNavigator } from '@react-navigation/stack'; + +const MyPollButtons = () => { + return ( + <> + + Alert.alert(`Message ID: ${message.id} and Poll ID: ${poll.id}`)} + /> + + + ); +}; + +const MyPollContent = () => null} PollButtons={MyPollButtons} />; + +// highlight-start +const ChannelMessageList = () => { + return ( + <> + + + + + ); +}; +// highlight-end + +// highlight-next-line +const ChannelStack = createStackNavigator(); + +const ChannelScreen = () => { + return ( + + + + // highlight-start + + + null} /> + + // highlight-end + + + + ); +}; +``` + +For now, we'll leave the `PollResultsScreen` empty. With the code above, we're allowed to create a new navigation stack within the `Channel` component that we can then use for all of the `Poll` screens. + +It would allow us to not have to move the `channel` prop around (as well as all other `Channel` customizations we might have) and still handle everything with our own navigation. + +As a next step, let's reconstruct the `PollResults` screen. For this, we may use the `PollModalHeader` and `PollResults` components and get the default UI out of the box. + +```tsx +import { + OverlayProvider, + Chat, + Channel, + MessageList, + MessageInput, + PollContent, + // highlight-start + PollResults, + PollModalHeader, + // highlight-end +} from 'stream-chat-react-native'; +import { createStackNavigator } from '@react-navigation/stack'; + +const MyPollButtons = () => { + return ( + <> + + + navigation.navigate('PollResultsScreen', { + message, + poll, + }); + } + /> + + + ) +} + +// ... rest of the components + +// highlight-start +const PollResultsScreen = ({ + route: { + params: { message, poll }, + }, +}) => { + const navigation = useNavigation(); + return ( + + navigation.goBack()} /> + + + ); +}; +// highlight-end + +const ChannelScreen = () => { + return ( + + + + + + + + + + + ); +}; +``` + +Clicking on the `View Results` button now will successfully navigate us to the `PollResults` screen. It is no longer a modal but rather part of the navigation stack that we introduced. + +![Custom Results](../assets/guides/custom-poll-flow/custom-results.png) + +It looks exactly the same as the default UI, however the title is changed to `RESULTS` rather than the `Poll Results`. + +As a next step, let's say that we want to include the `Poll` name pinned at the top so it's present all the time in case we get many options. + +For this purpose, we can use the `usePollState` hook and the `PollResultsContent` component. + +```tsx +import { + // ...rest of the imports + // highlight-start + usePollState, + PollResultsContent, + // highlight-end +} from 'stream-chat-react-native'; +import { createStackNavigator } from '@react-navigation/stack'; + +// ... rest of the components + +// highlight-start +const MyPollResultsContent = () => { + const { name } = usePollState(); + const navigation = useNavigation(); + return ( + <> + navigation.goBack()} /> + + + ); +}; + +const PollResultsScreen = ({ + route: { + params: { message, poll }, + }, +}) => { + return ( + + + + ); +}; +// highlight-end + +const ChannelScreen = () => { + return ( + + + + + + + + + + + ); +}; +``` + +Providing us with the following UI: + +![Custom Results Title](../assets/guides/custom-poll-flow/custom-results-title.png) + +We are indeed allowed to do this because `PollResults` comes pre-wrapped within a `PollContext` and the button `onPress` callback provides us with all of the data we need to render initialize the `PollContextProvider`. + +Since we did this to the results screen, let's do the same for the poll creation one for consistency. + +```tsx +import { + // ...rest of the imports + // highlight-next-line + CreatePoll, +} from 'stream-chat-react-native'; +import { createStackNavigator } from '@react-navigation/stack'; + +// ... rest of the components + +// highlight-start +const MyCreatePollContent = ({ + route: { + params: { sendMessage }, + }, +}) => { + const navigation = useNavigation(); + return ( + + navigation.goBack()} /> + + ); +}; +// highlight-end + +const ChannelScreen = () => { + // highlight-next-line + const navigation = useNavigation(); + return ( + + + navigation.navigate('CreatePollScreen', { sendMessage })} + // highlight-end + > + + + + // highlight-start + + + + // highlight-end + + + + + ); +}; +``` + +giving us the final UI: + +
+ Step 1-1 + Step 1-2 +
+ +Going forward with customizations, let's change the background color of our `Poll`s. Since all `Poll` components are `theme` compatible, we can do this by overriding the default theme: + +```tsx +import { + // ...rest of the imports + // highlight-next-line + ThemeProvider, +} from 'stream-chat-react-native'; +import { createStackNavigator } from '@react-navigation/stack'; + +// ... rest of the components + +// highlight-start +const myTheme: DeepPartial = { + poll: { + message: { + container: { + backgroundColor: 'pink', + }, + }, + }, +}; +// highlight-end + +const ChannelScreen = () => { + const navigation = useNavigation(); + return ( + // highlight-next-line + + + + navigation.navigate('CreatePollScreen', { sendMessage })} + > + + + + + + + + + + + // highlight-next-line + + ); +}; +``` + +which gives us a changed `Poll` background: + +![Custom Poll Background](../assets/guides/custom-poll-flow/custom-poll-background.png) + +:::note +Make sure that the `theme` is set above your `OverlayProvider` to make sure that the `Poll` customizations are also reflected on the message preview whenever it's long pressed. +::: + +As one final step, let's assume we want to add an `PollAnswersList`; however the default UI doesn't fit our requirements and we want something more custom. + +To do this, we first need to add the `ShowAllCommentsButton` and `AddCommentButton` components to our custom `Buttons` UI: + +```tsx +import { + // ...rest of the imports + // highlight-start + ShowAllCommentsButton, + AddCommentButton + // highlight-end +} from 'stream-chat-react-native'; +import { createStackNavigator } from '@react-navigation/stack'; + +// ... rest of the components + +const MyPollButtons = () => { + return ( + <> + + // highlight-start + + + // highlight-end + + navigation.navigate('PollResultsScreen', { + message, + poll, + }); + } + /> + + + ) +} + +// ... the ChannelScreen component +``` + +Next, to actually create comments we need a poll that accepts answers (comments) as well as adding a comment. We can do this by enabling the option when creating a poll and then clicking on the `Add Comment` button: + +
+ Step 1-1 + Step 1-2 +
+ +Now, similar to how we handled the other screens we would want to create a separate `Screen` in the navigation stack for our `AnswersList`. For now, we'll use the default UI: + +```tsx +import { + // ...rest of the imports + // highlight-next-line + PollAnswersList, +} from 'stream-chat-react-native'; +import { createStackNavigator } from '@react-navigation/stack'; + +// ... rest of the components + +const MyPollButtons = () => { + return ( + <> + + // highlight-start + { + navigation.navigate('PollAnswersScreen', { + message, + poll, + }); + }} + /> + // highlight-end + + + navigation.navigate('PollResultsScreen', { + message, + poll, + }); + } + /> + + + ) +} + +// highlight-start +const PollAnswersScreen = ({ + route: { + params: { message, poll }, + }, +}) => { + const navigation = useNavigation(); + return ( + + navigation.goBack()} /> + + + ); +}; +// highlight-end + +const ChannelScreen = () => { + const navigation = useNavigation(); + return ( + + + + navigation.navigate('CreatePollScreen', { sendMessage })} + > + + + + // highlight-start + + // highlight-end + + + + + + + + + ); +}; +``` + +which will give allow us to navigate to the default `PollAnswersList` UI: + +![Answer List Navigation](../assets/guides/custom-poll-flow/answer-list-navigation.png) + +Now, let's finally customize the UI. To achieve this we can override the `PollAnswersListContent` of our `PollAnswersList`. + +Since the list of answers can be very large and we want to be able to still display all answers, we will use the `usePollAnswersPagination` hook to get them: + +```tsx +import { + // ...rest of the imports + // highlight-next-line + usePollAnswersPagination, +} from 'stream-chat-react-native'; +import { createStackNavigator } from '@react-navigation/stack'; + +// ... rest of the components + +// highlight-start +const LoadingIndicator = () => { + /* some LoadingIndicator logic here */ +}; + +const MyItem = ({ item }) => { + const { answer_text, user } = item; + return ( + + {user.name} commented: {answer_text} + + ); +}; + +const MyPollAnswersContent = () => { + const { pollAnswers, loading, loadMore } = usePollAnswersPagination(); + return ( + : null} + /> + ); +}; +// highlight-end + +const PollAnswersScreen = ({ + route: { + params: { message, poll }, + }, +}) => { + const navigation = useNavigation(); + return ( + + navigation.goBack()} /> + // highlight-start + + // highlight-end + + ); +}; + +// ... the Channel screen +``` + +And we get the final content: + +![Custom Answers List](../assets/guides/custom-poll-flow/custom-answers-list.png) + +The list will be fully compatible with loading the pagination when scrolling to the bottom and displaying a loading indicator whenever that happens as well. + +With that, we have finished the customizations we wanted to do for our polls. + +As a last note; any components that you'd like to reuse from the default UI are free to be imported from within the SDK. + +An extensive list of these includes: + +- All buttons mentioned [here](../ui-components/poll-buttons.mdx) +- `CreatePollContent` +- `PollContent` +- `PollButtons` +- `PollHeader` +- `PollModalHeader` +- `PollInputDialog` +- `CreatePollIcon` +- `PollOption` +- `PollResultsContent` +- `PollResultsItem` +- `PollVote` +- `PollAllOptionsContent` diff --git a/docusaurus/docs/reactnative/guides/custom-thread-list.mdx b/docusaurus/docs/reactnative/guides/custom-thread-list.mdx index 5ba4de291..665e3b562 100644 --- a/docusaurus/docs/reactnative/guides/custom-thread-list.mdx +++ b/docusaurus/docs/reactnative/guides/custom-thread-list.mdx @@ -3,8 +3,6 @@ id: custom-thread-list title: Custom Thread List --- -import loadMoreButton from '../assets/guides/custom-channel-list/load_more_button.png'; - In this cookbook we'll go over how we can create and customize a screen containing the [`ThreadList` component](../ui-components/thread-list.mdx). The goal will be to display a list of threads as well as have a banner that displays the number of unread threads within the list. ### Prerequisites diff --git a/docusaurus/docs/reactnative/hooks/poll/use-create-poll-context.mdx b/docusaurus/docs/reactnative/hooks/poll/use-create-poll-context.mdx new file mode 100644 index 000000000..e0688daf8 --- /dev/null +++ b/docusaurus/docs/reactnative/hooks/poll/use-create-poll-context.mdx @@ -0,0 +1,6 @@ +--- +id: use-create-poll-context +title: useCreatePollContext +--- + +A hook that returns the [`CreatePollContext` value](../../contexts/create-poll-context.mdx#value). diff --git a/docusaurus/docs/reactnative/hooks/poll/use-poll-answers-pagination.mdx b/docusaurus/docs/reactnative/hooks/poll/use-poll-answers-pagination.mdx new file mode 100644 index 000000000..02b7104de --- /dev/null +++ b/docusaurus/docs/reactnative/hooks/poll/use-poll-answers-pagination.mdx @@ -0,0 +1,78 @@ +--- +id: use-poll-answers-pagination +title: usePollAnswersPagination +--- + +A hook that queries answers for a given `Poll` and returns them in a paginated fashion. It can be used whenever we want to view all answers in a given `poll`, like in the [`PollAnswersList` component](../../ui-components/poll-answers-list.mdx) for example. + +## Properties + +### `loadFirstPage` + +A property that depicts whether the hook should load the first page of answers when first invoked or not. Default to `true` if omitted. + +| Type | +| --------- | +| `boolean` | + +### `paginationParams` + +An object containing the pagination parameters that we may want to pass to the hook that will then be used to query for answers. + +Its type can be found [here](https://github.com/GetStream/stream-chat-js/blob/master/src/types.ts) under the name `PollAnswersQueryParams`. + +| Type | +| -------- | +| `object` | + +## Return type + +The `usePollAnswersPagination` hook returns an object containing pagination values for the `poll`'s answers. + +### error + +An object containing an error if one is thrown during querying for the answers. + +| Type | +| -------- | +| `object` | + +### hasNextPage + +A property depicting whether the list of answers has a next page to load or not. + +| Type | +| --------- | +| `boolean` | + +### loading + +A property depicting whether the next page of answers is currently loading or not. + +| Type | +| --------- | +| `boolean` | + +### loadMore + +A function that loads the next page of answers whenever invoked. It will automatically update [`pollAnswers`](#pollanswers) + +| Type | +| ------------ | +| `() => void` | + +### next + +A reference to the next cursor in the pagination. + +| Type | +| -------- | +| `string` | + +### pollAnswers + +A list of answers that has been loaded so far. It automatically updates itself whenever `loadMore()` is invoked and triggers a `state` update. + +| Type | +| -------------- | +| `PollAnswer[]` | diff --git a/docusaurus/docs/reactnative/hooks/poll/use-poll-context.mdx b/docusaurus/docs/reactnative/hooks/poll/use-poll-context.mdx new file mode 100644 index 000000000..d7046a7a2 --- /dev/null +++ b/docusaurus/docs/reactnative/hooks/poll/use-poll-context.mdx @@ -0,0 +1,6 @@ +--- +id: use-poll-context +title: usePollContext +--- + +A hook that returns the [`PollContext` value](../../contexts/poll-context.mdx#value). diff --git a/docusaurus/docs/reactnative/hooks/poll/use-poll-option-votes-pagination.mdx b/docusaurus/docs/reactnative/hooks/poll/use-poll-option-votes-pagination.mdx new file mode 100644 index 000000000..fb932bff7 --- /dev/null +++ b/docusaurus/docs/reactnative/hooks/poll/use-poll-option-votes-pagination.mdx @@ -0,0 +1,88 @@ +--- +id: use-poll-option-votes-pagination +title: usePollOptionVotesPagination +--- + +A hook that queries votes for a given option in a `Poll` and returns them in a paginated fashion. It can be used whenever we want to view all votes for an option in a given `poll`, like in the [`PollOptionFullResults` component](../../ui-components/poll-option-full-results.mdx) for example. + +## Properties + +### `loadFirstPage` + +A property that depicts whether the hook should load the first page of answers when first invoked or not. Default to `true` if omitted. + +| Type | +| --------- | +| `boolean` | + +### `option` \* + +The `poll` option that we want to query the votes for. + +| Type | +| -------- | +| `object` | + +### `paginationParams` + +An object containing the pagination parameters that we may want to pass to the hook that will then be used to query for votes. + +Its type can be found [here](https://github.com/GetStream/stream-chat-js/blob/master/src/types.ts) under the name `PollOptionVotesQueryParams`. + +The `{ option_id: }` filter is mandatory and will be added regardless of overrides. + +| Type | +| -------- | +| `object` | + +## Return type + +The `usePollOptionVotesPagination` hook returns an object containing pagination values for the `poll` option's votes. + +### error + +An object containing an error if one is thrown during querying for the votes. + +| Type | +| -------- | +| `object` | + +### hasNextPage + +A property depicting whether the list of votes has a next page to load or not. + +| Type | +| --------- | +| `boolean` | + +### loading + +A property depicting whether the next page of votes is currently loading or not. + +| Type | +| --------- | +| `boolean` | + +### loadMore + +A function that loads the next page of votes whenever invoked. It will automatically update [`votes`](#votes) + +| Type | +| ------------ | +| `() => void` | + +### next + +A reference to the next cursor in the pagination. + +| Type | +| -------- | +| `string` | + +### vote + +A list of votes that has been loaded so far. It automatically updates itself whenever `loadMore()` is invoked and triggers a `state` update. + +| Type | +| ------------ | +| `PollVote[]` | diff --git a/docusaurus/docs/reactnative/hooks/poll/use-poll-state-store.mdx b/docusaurus/docs/reactnative/hooks/poll/use-poll-state-store.mdx new file mode 100644 index 000000000..58e756c5a --- /dev/null +++ b/docusaurus/docs/reactnative/hooks/poll/use-poll-state-store.mdx @@ -0,0 +1,31 @@ +--- +id: use-poll-state-store +title: usePollStateStore +--- + +A utility hook used to access the `poll` state store directly by passing a [`selector`](../../state-and-offline-support/state-overview.mdx#what-are-selectors). + +The full extent of the `Poll` state can be found [here](https://github.com/GetStream/stream-chat-js/blob/master/src/poll.ts), under the `PollState` type. + +This hook can only be used within a child of [`PollContext`](../../contexts/poll-context.mdx). + +## Example usage + +```tsx +import { PollVote, PollState } from 'stream-chat'; +import { usePollStateStore } from 'stream-chat-react-native'; + +type PollOptionSelectorReturnValue = { + latest_votes_by_option: Record; + maxVotedOptionIds: string[]; +}; + +const selector = ( + nextValue: PollState, +): PollOptionSelectorReturnValue => ({ + latest_votes_by_option: nextValue.latest_votes_by_option, + maxVotedOptionIds: nextValue.maxVotedOptionIds, +}); + +const { latest_votes_by_option, maxVotedOptionIds } = usePollStateStore(selector); +``` diff --git a/docusaurus/docs/reactnative/hooks/poll/use-poll-state.mdx b/docusaurus/docs/reactnative/hooks/poll/use-poll-state.mdx new file mode 100644 index 000000000..e35a75d4b --- /dev/null +++ b/docusaurus/docs/reactnative/hooks/poll/use-poll-state.mdx @@ -0,0 +1,140 @@ +--- +id: use-poll-state +title: usePollState +--- + +This is the hook containing most of the important properties from the `PollState`. It also provides several other utilities that make it easier to handle the UI for polls. + +The full extent of the `Poll` state can be found [here](https://github.com/GetStream/stream-chat-js/blob/master/src/poll.ts), under the `PollState` type. If the properties from the hook are not enough for rendering their desired UI, integrators are encouraged to write their own `selectors` and use the [`usePollStateStore`](./use-poll-state-store.mdx) hook instead. + +This hook can only be used within a child of [`PollContext`](../../contexts/poll-context.mdx). + +It is highly recommended that the user familiarizes themselves with the [`Poll` client documentation](https://getstream.io/chat/docs/javascript/polls_api/?language=javascript&q=poll) in order to understand the properties better. + +## Return type + +The `usePollState` hook returns an object containing values from the `PollState`. + +### `allow_answers` + +A property depicting whether answers (comments) are allowed to the `poll`. + +| Type | +| --------- | ----------- | +| `boolean` | `undefined` | + +### `allow_user_suggested_options` + +A property depicting whether user option suggestions are allowed to the `poll`. + +| Type | +| --------- | ----------- | +| `boolean` | `undefined` | + +### `answers_count` + +A property containing the number of answers (comments) to the `poll`. + +| Type | +| -------- | +| `number` | + +### `created_by` + +A property containing information about the user who created the `poll`. Its type can be found [here](https://github.com/GetStream/stream-chat-js/blob/b447512922b19bc7e3668bd9df81debcb673dd81/src/types.ts) under `UserResponse`. + +This property will be `null` for anonymous polls. + +| Type | +| -------- | ------ | +| `object` | `null` | + +### `enforce_unique_vote` + +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`. + +| Type | +| --------- | +| `boolean` | + +### `is_closed` + +A property depicting whether the `poll` is still open for voting or not. + +| Type | +| --------- | +| `boolean` | + +### `latest_votes_by_option` + +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. + +This property is not available for anonymous polls. + +| Type | +| -------------------------- | +| `Record` | + +### `max_votes_allowed` + +A property containing the maximum number of votes allowed per user. + +| Type | +| -------- | +| `number` | + +### `maxVotedOptionIds` + +An array of `Poll` option IDs of all of the options with the maximum number of votes in it. Will only contain more than 1 ID if there's a tie between options. + +| Type | +| ---------- | +| `string[]` | + +### `name` + +A property depicting the name of the `poll`. + +| Type | +| -------- | +| `string` | + +### `options` + +A property that is a list of all of the options a `poll` has. A `poll` cannot have more than 100 options. + +| Type | +| -------------- | +| `PollOption[]` | + +### `ownAnswer` + +A property containing the answer (comment) of a user to the current `poll`. Only one answer can be provided by a single user. This property will not be present in anonymous polls. + +| Type | +| ------------ | ----------- | +| `PollAnswer` | `undefined` | + +### `ownVotesByOptionId` + +A property containing the current user's own votes in a given `poll`, stored in an object by option ID. + +| Type | +| -------------------------- | +| `Record` | + +### `vote_counts_by_option` + +A property containing the vote counts in a given `poll`, stored in an object by option ID. + +| Type | +| ------------------------ | +| `Record` | + +### `voting_visibility` + +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). + +| Type | +| ------------------ | ----------- | +| `VotingVisibility` | `undefined` | diff --git a/docusaurus/docs/reactnative/state-and-offline-support/state-overview.mdx b/docusaurus/docs/reactnative/state-and-offline-support/state-overview.mdx index 51474fc6f..0e1c11975 100644 --- a/docusaurus/docs/reactnative/state-and-offline-support/state-overview.mdx +++ b/docusaurus/docs/reactnative/state-and-offline-support/state-overview.mdx @@ -248,12 +248,12 @@ To disconnect a user you can call `disconnect` on the client. await client.disconnectUser(); ``` -## Thread and ThreadManager +## POJO -With the new [threads feature](../guides/custom-thread-list.mdx) we've decided to refresh our state management and moved to a subscribable POJO with selector based system to make developer experience better when it came to rendering information provided by our `StreamChat` client. +With a few of our new features, we've decided to refresh our state management and moved to a subscribable POJO with selector based system to make developer experience better when it came to rendering information provided by our `StreamChat` client. :::note -This change is currently only available within `StreamChat.threads` but will be reused across the whole SDK later on. +This change is currently only available within `StreamChat.threads`, `StreamChat.poll` and `StreamChat.polls` but will be reused across the whole SDK later on. ::: ### Why POJO (State Object) @@ -349,7 +349,7 @@ thread?.state.getLatestValue(/*...*/); #### useStateStore Hook -For the ease of use - the React SDK comes with the appropriate state access hook which wraps `StateStore.subscribeWithSelector` API for the React-based applications. +For the ease of use - the React Native SDK comes with the appropriate state access hook which wraps `StateStore.subscribeWithSelector` API for the React-based applications. ```tsx import { useStateStore } from 'stream-chat-react-native'; @@ -370,3 +370,65 @@ const CustomThreadList = () => { ); }; ``` + +## Thread and ThreadManager + +One of the feature that follows the new POJO style of state management is the [threads feature](../guides/custom-thread-list.mdx). + +It provides a reactive state for both a single `Thread` (through a reactive `threadInstance`) and a list of threads (through `StreamChat.threads`). + +Both states can be accessed through `selector`s as outlined in the examples above. + +## Poll and PollManager + +Our new polls feature also follows the new POJO style of state management. A `poll` in itself is something that needs to be linked to a `message` in order for it to work. When a poll is created, the only way to make it visible to the users is to send it as a message. This `message` needs to have a `poll_id` attached to it and preferably no text. + +You can access each `poll`'s reactive state by getting it by ID using `StreamChat.polls.fromState()`. + +:::note +Please keep in mind that `message.poll` is not going to be reactive, but will rather contain the raw `poll` data as returned by our backend. +::: + +### Utility hooks + +The React Native SDK provides 2 utility hooks to help with consuming the `poll` state. They can be found listed below: + +- [`usePollStateStore`](./hooks/poll/use-poll-state-store.mdx) +- [`usePollState`](./hooks/poll/use-poll-state.mdx) + +Similarly to the `threads` feature, one can also directly use `useStateStore` and access `StreamChat.polls.fromState().state` through custom `selector`s. + +:::note +Both `usePollStateStore` and `usePollState` can only be used in children of a [`PollContext`](./contexts/poll-context.mdx). This impediment does not exist however on `useStateStore`. +::: + +Due to this, all `poll` related components within the SDK are self-wrapped within a `PollContext` and require `message` and `poll` as mandatory props. + +#### Example + +```tsx +import { usePollState } from 'stream-chat-react-native'; + +const CustomPollComponent = () => { + const { name, options } = usePollState(); + + return ( + + {name} + {options.map(option => ( + {option.text} + ))} + + ); +}; + +const PollMessage = ({ message }) => { + const { client } = useChatContext(); + const pollInstance = client.polls.fromState(message?.poll_id); + return ( + + + + ); +}; +``` diff --git a/docusaurus/docs/reactnative/ui-components/create-poll.mdx b/docusaurus/docs/reactnative/ui-components/create-poll.mdx new file mode 100644 index 000000000..cc5977108 --- /dev/null +++ b/docusaurus/docs/reactnative/ui-components/create-poll.mdx @@ -0,0 +1,49 @@ +--- +id: create-poll +title: CreatePoll +--- + +import ClosePollCreationDialog from '../common-content/contexts/create-poll-context/close-poll-creation-dialog.mdx'; +import CreatePollContent from '../common-content/contexts/create-poll-context/create-poll-content.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'; + +A component used to render the entirety of the poll creation form. It encapsulates the `CreatePollContent` component within a [`CreatePollContext`](../contexts/create-poll-context.mdx). Needs to be structured inside a [`Channel` component](../core-components/channel). + +The default behaviour of this component is it opening in a [React Native Modal](https://reactnative.dev/docs/modal). Integrators are highly encouraged to write their own UI for the dialog with the specific options and flexibility they require. + +## General Usage + +```tsx +import { OverlayProvider, Chat, Channel, CreatePoll } from 'stream-chat-react-native'; + +const App = () => { + return ( + + + + + + + + ); +}; +``` + +## Props + +###
_forwarded from [MessageInputContext](../../contexts/message-input-context#sendmessage)_ props
sendMessage {#sendmessage} + + + +### `closePollCreationDialog` + + + +### `onThreadSelect` + + + +### `CreatePollContent` + + diff --git a/docusaurus/docs/reactnative/ui-components/poll-all-options.mdx b/docusaurus/docs/reactnative/ui-components/poll-all-options.mdx new file mode 100644 index 000000000..2bfdeb0e6 --- /dev/null +++ b/docusaurus/docs/reactnative/ui-components/poll-all-options.mdx @@ -0,0 +1,87 @@ +--- +id: poll-all-options +title: PollAllOptions +--- + +import MessageProp from '../common-content/contexts/message-context/message.mdx'; +import Poll from '../common-content/contexts/poll-context/poll.mdx'; + +A component used to render a list of all of the options that a `Poll` has. Voting on each option on this screen is also enabled. Needs to be structured inside a [`Channel` component](../core-components/channel). + +It will render its default `PollAllOptionsContent`, which can be overridden for custom UI. Its children have access to the entire `poll` state through the `usePollState` hook. + +## General Usage + +```tsx +import { OverlayProvider, Chat, Channel, PollAllOptions } from 'stream-chat-react-native'; + +const App = () => { + return ( + + + + + + + + ); +}; +``` + +## Props + +###
_forwarded from [MessageContext](../../contexts/message-context#message)_ props
message {#message} + + + +### `poll` \* + + + +### `additionalScrollViewProps` + +A prop used to override the underlying [`ScrollView`](https://reactnative.dev/docs/scrollview#props) props of the `PollAllOptions`. + +```jsx +const flatListProps = { bounces: true }; + +; +``` + +| Type | +| ------ | +| object | + +### `PollAllOptionsContent` + +A `Component` prop used to render the content of the `PollAllOptions` component. + +The component has full access to the entire `Poll` reactive state through the `usePollState` hook. + +| Type | Default | +| ------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| ComponentType | [`PollAllOptionsContent`](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Poll/PollOption.tsx) | + +#### Usage + +```tsx +import { Text } from 'react-native'; +import { OverlayProvider, Chat, Channel, PollAllOptions, usePollState } from 'stream-chat-react-native'; + +const MyPollAllOptionsContent = () => { + const { options } = usePollState(); + return options.map(option => {option.id}); +}; + +const App = () => { + return ( + + + + + + + + ); +}; +``` diff --git a/docusaurus/docs/reactnative/ui-components/poll-answers-list.mdx b/docusaurus/docs/reactnative/ui-components/poll-answers-list.mdx new file mode 100644 index 000000000..6c0dc4a9c --- /dev/null +++ b/docusaurus/docs/reactnative/ui-components/poll-answers-list.mdx @@ -0,0 +1,104 @@ +--- +id: poll-answers-list +title: PollAnswersList +--- + +import MessageProp from '../common-content/contexts/message-context/message.mdx'; +import Poll from '../common-content/contexts/poll-context/poll.mdx'; + +A component used to render a list of answers that a `Poll` has. The results will be paginated and only one answer per user is allowed. Needs to be structured inside a [`Channel` component](../core-components/channel). + +It will render its default `PollAnswersListContent`, which can be overridden for custom UI. Its children have access to the entire `poll` state through the `usePollState` hook. + +To access the paginated list of answers, the `usePollAnswersPagination` hook can be used. + +## General Usage + +```tsx +import { OverlayProvider, Chat, Channel, PollAnswersList } from 'stream-chat-react-native'; + +const App = () => { + return ( + + + + + + + + ); +}; +``` + +## Props + +###
_forwarded from [MessageContext](../../contexts/message-context#message)_ props
message {#message} + + + +### `poll` \* + + + +### `additionalFlatListProps` + +A prop used to override the underlying [`FlatList`](https://reactnative.dev/docs/flatlist#props) props of the `PollAnswersList`. + +```jsx +const flatListProps = { bounces: true }; + +; +``` + +| Type | +| ------ | +| object | + +### `PollAnswersListContent` + +A `Component` prop used to render the content of the `PollAnswersList` component. + +The component has full access to the entire `Poll` reactive state through the `usePollState` hook. + +| Type | Default | +| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| ComponentType | [`PollAnswersListContent`](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Poll/PollAnswersList.tsx) | + +#### Usage + +```tsx +import { Text, FlatList } from 'react-native'; +import { + OverlayProvider, + Chat, + Channel, + PollAnswersList, + usePollAnswersPagination, + usePollState, +} from 'stream-chat-react-native'; + +// will only display the first page of answers without loading more +const MyPollAnswersListContent = () => { + const { name } = usePollState(); + const { pollAnswers } = usePollAnswersPagination(); + return ( + {name}} + data={pollAnswers} + renderItem={({ item }) => {item.answer_text}} + /> + ); +}; + +const App = () => { + return ( + + + + + + + + ); +}; +``` diff --git a/docusaurus/docs/reactnative/ui-components/poll-buttons.mdx b/docusaurus/docs/reactnative/ui-components/poll-buttons.mdx new file mode 100644 index 000000000..b022d2f3a --- /dev/null +++ b/docusaurus/docs/reactnative/ui-components/poll-buttons.mdx @@ -0,0 +1,258 @@ +--- +id: poll-buttons +title: Poll Buttons +--- + +For the purposes of managing the `Poll` UI more easily, we expose various button components that have an overridable `onPress` property in case the default behaviour needs to be changed. + +The `onPress` property should be typically used to navigate to the various `Poll` screens using a popular navigation library rather than relying on the default [React Native Modal](https://reactnative.dev/docs/modal) implementation. Integrators are encouraged to handle navigation to these screens like this rather than relying on the defaults. + +In order to be able to render the screens, all of the required props will be passed to the `onPress` method. + +Conversely, if one wishes to use the default button behaviour they may render them without any props. + +All of the buttons need to be structured inside a [`Channel` component](../core-components/channel). + +## `GenericPollButton` + +A generic button component that has the default UI encapsulated within it. + +### Props + +#### `title` \* + +The text that is going to be rendered as the button's content. + +| Type | +| ------ | +| string | + +#### `onPress` \* + +A press handler that will be invoked whenever the button is pressed. + +| Type | +| ------------ | +| `() => void` | + +### Example usage + +```tsx +import { GenericPollButton } from 'stream-chat-react-native'; + +const button = () => console.log('I got pressed !')} />; +``` + +## `ViewResultsButton` + +A button responsible for opening the `PollResults` modal. + +### Props + +#### `onPress` + +A press handler that will be invoked whenever the button is pressed. + +| Type | +| ----------------------------- | +| `({ message, poll }) => void` | + +### Example usage + +```tsx +import { ViewResultsButton } from 'stream-chat-react-native'; + +const button = () => ( + console.log(`Poll ID: ${poll.id}; Message ID: ${message.id}`)} /> +); +``` + +## `EndVoteButton` + +A button responsible for closing voting on the `Poll`. + +### Example usage + +```tsx +import { EndVoteButton } from 'stream-chat-react-native'; + +const button = () => ; +``` + +## `AddCommentButton` + +A button responsible for opening the `Poll` input dialog used to add a new comment to it. + +### Props + +#### `onPress` + +A press handler that will be invoked whenever the button is pressed. + +| Type | +| ----------------------------- | +| `({ message, poll }) => void` | + +### Example usage + +```tsx +import { AddCommentButton } from 'stream-chat-react-native'; + +const button = () => ( + console.log(`Poll ID: ${poll.id}; Message ID: ${message.id}`)} /> +); +``` + +## `ShowAllCommentsButton` + +A button responsible for opening the `PollAnswersList` modal. + +### Props + +#### `onPress` + +A press handler that will be invoked whenever the button is pressed. + +| Type | +| ----------------------------- | +| `({ message, poll }) => void` | + +### Example usage + +```tsx +import { ShowAllCommentsButton } from 'stream-chat-react-native'; + +const button = () => ( + console.log(`Poll ID: ${poll.id}; Message ID: ${message.id}`)} + /> +); +``` + +## `AnswerListAddCommentButton` + +A button responsible for opening the `Poll` input dialog used to add a new comment to it, from within `PollAnswersList`. + +It has the same props and usage as [`AddCommentButton`](#addcommentbutton). + +## `SuggestOptionButton` + +A button responsible for opening the `Poll` input dialog used to suggest new options to the it. + +### Props + +#### `onPress` + +A press handler that will be invoked whenever the button is pressed. + +| Type | +| ----------------------------- | +| `({ message, poll }) => void` | + +### Example usage + +```tsx +import { SuggestOptionButton } from 'stream-chat-react-native'; + +const button = () => ( + console.log(`Poll ID: ${poll.id}; Message ID: ${message.id}`)} /> +); +``` + +## `ShowAllOptionsButton` + +A button responsible for opening the `PollAllOptions` modal. + +### Props + +#### `onPress` + +A press handler that will be invoked whenever the button is pressed. + +| Type | +| ----------------------------- | +| `({ message, poll }) => void` | + +### Example usage + +```tsx +import { ShowAllOptionsButton } from 'stream-chat-react-native'; + +const button = () => ( + console.log(`Poll ID: ${poll.id}; Message ID: ${message.id}`)} + /> +); +``` + +## `VoteButton` + +A button responsible for voting on a specific option within a `Poll`. + +### Props + +#### `option` \* + +The `poll` option that we want to vote on. + +| Type | +| ------ | +| object | + +#### `onPress` + +A press handler that will be invoked whenever the button is pressed. + +| Type | +| ----------------------------- | +| `({ message, poll }) => void` | + +### Example usage + +```tsx +import { VoteButton } from 'stream-chat-react-native'; + +const button = () => ( + console.log(`Poll ID: ${poll.id}; Message ID: ${message.id}`)} + /> +); +``` + +## `ShowAllVotesButton` + +A button responsible for opening the `PollOptionFullResults` modal. + +### Props + +#### `option` \* + +The `poll` option that we want to vote on. + +| Type | +| ------ | +| object | + +#### `onPress` + +A press handler that will be invoked whenever the button is pressed. + +| Type | +| ------------------------------------- | +| `({ message, option, poll }) => void` | + +### Example usage + +```tsx +import { ShowAllVotesButton } from 'stream-chat-react-native'; + +const button = () => ( + + console.log(`Poll ID: ${poll.id}; Message ID: ${message.id}; Option ID: ${option.id}`) + } + /> +); +``` diff --git a/docusaurus/docs/reactnative/ui-components/poll-option-full-results.mdx b/docusaurus/docs/reactnative/ui-components/poll-option-full-results.mdx new file mode 100644 index 000000000..a0a389230 --- /dev/null +++ b/docusaurus/docs/reactnative/ui-components/poll-option-full-results.mdx @@ -0,0 +1,117 @@ +--- +id: poll-option-full-results +title: PollOptionFullResults +--- + +import MessageProp from '../common-content/contexts/message-context/message.mdx'; +import Poll from '../common-content/contexts/poll-context/poll.mdx'; + +A component all of the votes for a specific `Poll` option. The results will be paginated and updated as they change. Needs to be structured inside a [`Channel` component](../core-components/channel). + +It will render its default `PollOptionFullResultsContent`, which can be overridden for custom UI. Its children have access to the entire `poll` state through the `usePollState` hook. + +To access the paginated list of votes, the `usePollOptionVotesPagination` hook can be used. + +## General Usage + +```tsx +import { OverlayProvider, Chat, Channel, PollOptionFullResults } from 'stream-chat-react-native'; + +const App = () => { + return ( + + + + + + + + ); +}; +``` + +## Props + +###
_forwarded from [MessageContext](../../contexts/message-context#message)_ props
message {#message} + + + +### `poll` \* + + + +### `option` \* + +The `poll` option that we want to display the results for. + +| Type | +| ------ | +| object | + +### `additionalFlatListProps` + +A prop used to override the underlying [`FlatList`](https://reactnative.dev/docs/flatlist#props) props of the `PollOptionFullResults`. + +```jsx +const flatListProps = { bounces: true }; + +; +``` + +| Type | +| ------ | +| object | + +### `PollOptionFullResultsContent` + +A `Component` prop used to render the content of the `PollOptionFullResults` component. + +The component has full access to the entire `Poll` reactive state through the `usePollState` hook. + +| Type | Default | +| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ComponentType | [`PollOptionFullResultsContent`](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Poll/PollOptionFullResults.tsx) | + +#### Usage + +```tsx +import { Text, FlatList } from 'react-native'; +import { + OverlayProvider, + Chat, + Channel, + PollOptionFullResults, + usePollOptionVotesPagination, + usePollState, +} from 'stream-chat-react-native'; + +// will only display the first page of votes without loading more +const MyPollOptionFullResultsContent = ({ option }) => { + const { name } = usePollState(); + const { votes } = usePollOptionVotesPagination({ option }); + return ( + {name}} + data={votes} + renderItem={({ item }) => {item.id}} + /> + ); +}; + +const App = () => { + return ( + + + + + + + + ); +}; +``` diff --git a/docusaurus/docs/reactnative/ui-components/poll-results.mdx b/docusaurus/docs/reactnative/ui-components/poll-results.mdx new file mode 100644 index 000000000..370c519e0 --- /dev/null +++ b/docusaurus/docs/reactnative/ui-components/poll-results.mdx @@ -0,0 +1,87 @@ +--- +id: poll-results +title: PollResults +--- + +import MessageProp from '../common-content/contexts/message-context/message.mdx'; +import Poll from '../common-content/contexts/poll-context/poll.mdx'; + +A component used to render a list of all of the votes per option that a `Poll` has. Each option will display the 5 most recent votes. If an option has more than 5 votes it will add a button at the bottom that opens the [`PollOptionFullResults`](./poll-option-full-results.mdx) Modal. Needs to be structured inside a [`Channel` component](../core-components/channel). + +It will render its default `PollResultsContent`, which can be overridden for custom UI. Its children have access to the entire `poll` state through the `usePollState` hook. + +## General Usage + +```tsx +import { OverlayProvider, Chat, Channel, PollResults } from 'stream-chat-react-native'; + +const App = () => { + return ( + + + + + + + + ); +}; +``` + +## Props + +###
_forwarded from [MessageContext](../../contexts/message-context#message)_ props
message {#message} + + + +### `poll` \* + + + +### `additionalScrollViewProps` + +A prop used to override the underlying [`ScrollView`](https://reactnative.dev/docs/scrollview#props) props of the `PollResults`. + +```jsx +const flatListProps = { bounces: true }; + +; +``` + +| Type | +| ------ | +| object | + +### `PollResultsContent` + +A `Component` prop used to render the content of the `PollResults` component. + +The component has full access to the entire `Poll` reactive state through the `usePollState` hook. + +| Type | Default | +| ------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| ComponentType | [`PollResultsContent`](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Poll/PollResults.tsx) | + +#### Usage + +```tsx +import { Text } from 'react-native'; +import { OverlayProvider, Chat, Channel, PollResults, usePollState } from 'stream-chat-react-native'; + +const MyPollResultsContent = () => { + const { options } = usePollState(); + return options.map(option => {option.id}); +}; + +const App = () => { + return ( + + + + + + + + ); +}; +``` diff --git a/docusaurus/docs/reactnative/ui-components/poll.mdx b/docusaurus/docs/reactnative/ui-components/poll.mdx new file mode 100644 index 000000000..fa26908ef --- /dev/null +++ b/docusaurus/docs/reactnative/ui-components/poll.mdx @@ -0,0 +1,26 @@ +--- +id: poll +title: Poll +--- + +import MessageProp from '../common-content/contexts/message-context/message.mdx'; +import Poll from '../common-content/contexts/poll-context/poll.mdx'; +import PollContent from '../common-content/ui-components/poll/poll-content.mdx'; + +A component used to render a poll within a `MessageList`. Needs to be structured inside a [`Channel` component](../core-components/channel). + +It will render its default `PollContent`, which can be overridden for custom UI. Its children have access to the entire `poll` state through the `usePollState` hook. + +## Props + +###
_forwarded from [MessageContext](../../contexts/message-context#message)_ props
message {#message} + + + +### `poll` \* + + + +### `PollContent` + + diff --git a/docusaurus/sidebars-react-native.json b/docusaurus/sidebars-react-native.json index 7e2bff155..e4df12e1b 100644 --- a/docusaurus/sidebars-react-native.json +++ b/docusaurus/sidebars-react-native.json @@ -98,6 +98,27 @@ { "Thread List": ["ui-components/thread-list", "ui-components/thread-list-item"] }, + { + "Poll": [ + "ui-components/create-poll", + "ui-components/poll", + "ui-components/poll-all-options", + "ui-components/poll-answers-list", + "ui-components/poll-results", + "ui-components/poll-option-full-results", + "ui-components/poll-buttons", + { + "Hooks": [ + "hooks/poll/use-poll-context", + "hooks/poll/use-create-poll-context", + "hooks/poll/use-poll-state-store", + "hooks/poll/use-poll-state", + "hooks/poll/use-poll-answers-pagination", + "hooks/poll/use-poll-option-votes-pagination" + ] + } + ] + }, { "Contexts": [ "customization/contexts", @@ -112,7 +133,9 @@ "contexts/translation-context", "contexts/typing-context", "contexts/threads-context", - "contexts/thread-list-item-context" + "contexts/thread-list-item-context", + "contexts/create-poll-context", + "contexts/poll-context" ] } ], @@ -129,7 +152,8 @@ "guides/file-compression", "guides/blocking-users", "guides/live-location-sharing", - "guides/custom-thread-list" + "guides/custom-thread-list", + "guides/custom-poll-flow" ], "State and Offline Support": [ "state-and-offline-support/state-overview",