From b99437578cfac730f771ed6fe84c2c1ceb772c95 Mon Sep 17 00:00:00 2001 From: automated-signal <37887102+automated-signal@users.noreply.github.com> Date: Fri, 14 Oct 2022 14:27:24 -0700 Subject: [PATCH] stories: sending/failed states in stories list Co-authored-by: Jamie Kyle <113370520+jamiebuilds-signal@users.noreply.github.com> --- _locales/en/messages.json | 8 ++++ stylesheets/components/StoryListItem.scss | 21 ++++++++- ts/components/MyStoriesButton.stories.tsx | 33 +++++++++++++ ts/components/MyStoriesButton.tsx | 57 ++++++++++++++++++++--- ts/messages/MessageSendState.ts | 2 + 5 files changed, 113 insertions(+), 8 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 5613ddce7..abe5da4a2 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -5451,6 +5451,14 @@ "message": "No recent stories to show right now", "description": "Description for when there are no stories to show" }, + "Stories__list--sending": { + "message": "Sending...", + "description": "Pending text for story being sent in list view" + }, + "Stories__list--send_failed": { + "message": "Send failed", + "description": "Error text for story failed to send in list view" + }, "Stories__placeholder--text": { "message": "Click to view a story", "description": "Placeholder label for the story view" diff --git a/stylesheets/components/StoryListItem.scss b/stylesheets/components/StoryListItem.scss index c75e15e20..98a14f6cf 100644 --- a/stylesheets/components/StoryListItem.scss +++ b/stylesheets/components/StoryListItem.scss @@ -60,11 +60,30 @@ color: $color-gray-05; } - &--timestamp { + &--timestamp, + &--sending, + &--send_failed { @include font-body-2; color: $color-gray-25; } + &--send_failed { + display: flex; + align-items: center; + &::before { + content: ''; + display: flex; + flex-shrink: 0; + height: 12px; + width: 12px; + margin-right: 8px; + @include color-svg( + '../images/icons/v2/error-outline-12.svg', + $color-accent-red + ); + } + } + &--replies { &--others { @include color-svg( diff --git a/ts/components/MyStoriesButton.stories.tsx b/ts/components/MyStoriesButton.stories.tsx index 7ad0b52e2..b9777251e 100644 --- a/ts/components/MyStoriesButton.stories.tsx +++ b/ts/components/MyStoriesButton.stories.tsx @@ -13,6 +13,7 @@ import { MyStoriesButton } from './MyStoriesButton'; import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation'; import { getFakeStoryView } from '../test-both/helpers/getFakeStory'; import { setupI18n } from '../util/setupI18n'; +import { SendStatus } from '../messages/MessageSendState'; const i18n = setupI18n('en', enMessages); @@ -81,3 +82,35 @@ ManyStories.story = { name: 'Many Stories', }; ManyStories.play = interactionTest; + +export const SendingStory = Template.bind({}); +SendingStory.story = { + name: 'Sending Story', +}; +SendingStory.args = { + newestStory: { + ...getFakeStoryView(), + sendState: [ + { + status: SendStatus.Pending, + recipient: getDefaultConversation(), + }, + ], + }, +}; + +export const FailedSendStory = Template.bind({}); +FailedSendStory.story = { + name: 'Failed Send Story', +}; +FailedSendStory.args = { + newestStory: { + ...getFakeStoryView(), + sendState: [ + { + status: SendStatus.Failed, + recipient: getDefaultConversation(), + }, + ], + }, +}; diff --git a/ts/components/MyStoriesButton.tsx b/ts/components/MyStoriesButton.tsx index 4b3d4fecc..a0afd3750 100644 --- a/ts/components/MyStoriesButton.tsx +++ b/ts/components/MyStoriesButton.tsx @@ -6,7 +6,7 @@ import classNames from 'classnames'; import type { ConversationType } from '../state/ducks/conversations'; import type { LocalizerType } from '../types/Util'; import type { ShowToastActionCreatorType } from '../state/ducks/toast'; -import type { StoryViewType } from '../types/Stories'; +import type { StorySendStateType, StoryViewType } from '../types/Stories'; import { Avatar, AvatarSize } from './Avatar'; import { HasStories } from '../types/Stories'; import { StoryImage } from './StoryImage'; @@ -14,6 +14,7 @@ import { getAvatarColor } from '../types/Colors'; import { MessageTimestamp } from './conversation/MessageTimestamp'; import { StoriesAddStoryButton } from './StoriesAddStoryButton'; +import { isFailed, isPending } from '../messages/MessageSendState'; export type PropsType = { hasMultiple: boolean; @@ -26,6 +27,32 @@ export type PropsType = { showToast: ShowToastActionCreatorType; }; +enum ResolvedSendStatus { + Failed, + Sending, + Sent, +} + +function resolveSendStatus( + sendStates: Array +): ResolvedSendStatus { + let anyPending = false; + for (const sendState of sendStates) { + if (isFailed(sendState.status)) { + // Immediately return if any send failed + return ResolvedSendStatus.Failed; + } + if (isPending(sendState.status)) { + // Don't return yet in case we have a failure + anyPending = true; + } + } + if (anyPending) { + return ResolvedSendStatus.Sending; + } + return ResolvedSendStatus.Sent; +} + export const MyStoriesButton = ({ hasMultiple, i18n, @@ -87,6 +114,10 @@ export const MyStoriesButton = ({ ); } + const newStoryResolvedSendStatus = resolveSendStatus( + newestStory.sendState ?? [] + ); + return (
@@ -133,12 +164,24 @@ export const MyStoriesButton = ({
{i18n('Stories__mine')}
- + {newStoryResolvedSendStatus === ResolvedSendStatus.Sending && ( + + {i18n('Stories__list--sending')} + + )} + {newStoryResolvedSendStatus === ResolvedSendStatus.Failed && ( + + {i18n('Stories__list--send_failed')} + + )} + {newStoryResolvedSendStatus === ResolvedSendStatus.Sent && ( + + )}
= { export const maxStatus = (a: SendStatus, b: SendStatus): SendStatus => STATUS_NUMBERS[a] > STATUS_NUMBERS[b] ? a : b; +export const isPending = (status: SendStatus): boolean => + status === SendStatus.Pending; export const isViewed = (status: SendStatus): boolean => status === SendStatus.Viewed; export const isRead = (status: SendStatus): boolean =>