From 98ef4c627a00309fdfe6897adcd2d5491df025a7 Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Thu, 17 Nov 2022 16:45:19 -0800 Subject: [PATCH] Update eslint to 8.27.0 --- .eslintrc.js | 27 + package.json | 20 +- sticker-creator/app/index.tsx | 6 +- sticker-creator/app/stages/AppStage.tsx | 4 +- sticker-creator/app/stages/DropStage.tsx | 4 +- sticker-creator/app/stages/EmojiStage.tsx | 4 +- sticker-creator/app/stages/MetaStage.tsx | 4 +- sticker-creator/app/stages/ShareStage.tsx | 4 +- sticker-creator/app/stages/UploadStage.tsx | 4 +- sticker-creator/components/ConfirmModal.tsx | 4 +- sticker-creator/components/ShareButtons.tsx | 2 +- .../components/StickerFrame.stories.tsx | 4 +- sticker-creator/components/StickerFrame.tsx | 432 +++--- .../components/StickerPackPreview.tsx | 44 +- sticker-creator/components/Toaster.tsx | 6 +- sticker-creator/elements/Button.tsx | 6 +- sticker-creator/elements/ConfirmDialog.tsx | 6 +- sticker-creator/elements/CopyText.tsx | 2 +- sticker-creator/elements/DropZone.tsx | 6 +- sticker-creator/elements/LabeledCheckbox.tsx | 48 +- sticker-creator/elements/LabeledInput.tsx | 51 +- sticker-creator/elements/MessageBubble.tsx | 7 +- sticker-creator/elements/MessageMeta.tsx | 2 +- sticker-creator/elements/MessageSticker.tsx | 6 +- sticker-creator/elements/PageHeader.tsx | 8 +- sticker-creator/elements/ProgressBar.tsx | 22 +- sticker-creator/elements/StoryRow.tsx | 6 +- sticker-creator/elements/Toast.tsx | 24 +- .../elements/Typography.stories.tsx | 10 +- sticker-creator/elements/Typography.tsx | 56 +- sticker-creator/elements/icons/AddEmoji.tsx | 12 +- sticker-creator/root.tsx | 26 +- sticker-creator/store/ducks/stickers.ts | 5 +- sticker-creator/util/i18n.tsx | 8 +- ts/components/About.tsx | 6 +- ts/components/AddCaptionModal.stories.tsx | 1 + ts/components/AddCaptionModal.tsx | 6 +- .../AddGroupMemberErrorDialog.stories.tsx | 16 +- ts/components/AddGroupMemberErrorDialog.tsx | 8 +- .../AddUserToAnotherGroupModal.stories.tsx | 1 + ts/components/AddUserToAnotherGroupModal.tsx | 7 +- ts/components/Alert.stories.tsx | 100 +- ts/components/Alert.tsx | 34 +- ts/components/AnimatedEmojiGalore.stories.tsx | 6 +- ts/components/AnimatedEmojiGalore.tsx | 6 +- .../AnnouncementsOnlyGroupBanner.tsx | 6 +- ts/components/App.tsx | 6 +- ts/components/Avatar.stories.tsx | 6 +- ts/components/Avatar.tsx | 14 +- ts/components/AvatarColorPicker.stories.tsx | 22 +- ts/components/AvatarColorPicker.tsx | 6 +- ts/components/AvatarEditor.stories.tsx | 39 +- ts/components/AvatarEditor.tsx | 6 +- ts/components/AvatarIconEditor.stories.tsx | 44 +- ts/components/AvatarIconEditor.tsx | 6 +- ts/components/AvatarLightbox.stories.tsx | 36 +- ts/components/AvatarLightbox.tsx | 6 +- ts/components/AvatarModalButtons.stories.tsx | 22 +- ts/components/AvatarModalButtons.tsx | 6 +- ts/components/AvatarPopup.stories.tsx | 24 +- ts/components/AvatarPopup.tsx | 4 +- ts/components/AvatarPreview.stories.tsx | 110 +- ts/components/AvatarPreview.tsx | 6 +- ts/components/AvatarSpacer.tsx | 8 +- ts/components/AvatarTextEditor.stories.tsx | 52 +- ts/components/AvatarTextEditor.tsx | 6 +- ts/components/AvatarUploadButton.stories.tsx | 6 +- ts/components/AvatarUploadButton.tsx | 6 +- ts/components/BackboneHost.tsx | 4 +- ts/components/BadgeDescription.stories.tsx | 30 +- ts/components/BadgeDialog.stories.tsx | 146 +- ts/components/BetterAvatar.stories.tsx | 66 +- ts/components/BetterAvatar.tsx | 6 +- ts/components/BetterAvatarBubble.stories.tsx | 60 +- ts/components/BetterAvatarBubble.tsx | 6 +- ts/components/Button.stories.tsx | 88 +- ts/components/Button.tsx | 2 +- ts/components/CallBackgroundBlur.tsx | 6 +- ts/components/CallManager.stories.tsx | 228 ++-- ts/components/CallManager.tsx | 10 +- ts/components/CallNeedPermissionScreen.tsx | 6 +- ts/components/CallScreen.stories.tsx | 171 +-- ts/components/CallScreen.tsx | 6 +- .../CallingAudioIndicator.stories.tsx | 8 +- ts/components/CallingButton.stories.tsx | 40 +- ts/components/CallingButton.tsx | 6 +- .../CallingDeviceSelection.stories.tsx | 16 +- ts/components/CallingDeviceSelection.tsx | 6 +- ts/components/CallingHeader.stories.tsx | 96 +- ts/components/CallingHeader.tsx | 183 +-- ts/components/CallingLobby.stories.tsx | 48 +- ts/components/CallingLobby.tsx | 6 +- ts/components/CallingLobbyJoinButton.tsx | 23 +- .../CallingParticipantsList.stories.tsx | 16 +- ts/components/CallingParticipantsList.tsx | 7 +- ts/components/CallingPip.stories.tsx | 20 +- ts/components/CallingPip.tsx | 6 +- ts/components/CallingPipRemoteVideo.tsx | 12 +- ts/components/CallingPreCallInfo.stories.tsx | 354 ++--- ts/components/CallingPreCallInfo.tsx | 7 +- ...CallingScreenSharingController.stories.tsx | 8 +- .../CallingScreenSharingController.tsx | 6 +- ...ngSelectPresentingSourcesModal.stories.tsx | 4 +- .../CallingSelectPresentingSourcesModal.tsx | 12 +- ts/components/CallingToast.tsx | 27 +- ts/components/CallingToastManager.tsx | 4 +- ts/components/ChatColorPicker.stories.tsx | 30 +- ts/components/ChatColorPicker.tsx | 18 +- ts/components/Checkbox.stories.tsx | 22 +- ts/components/Checkbox.tsx | 6 +- ts/components/CompositionArea.stories.tsx | 78 +- ts/components/CompositionArea.tsx | 6 +- ts/components/CompositionInput.stories.tsx | 28 +- ts/components/CompositionTextArea.tsx | 6 +- ts/components/CompositionUpload.tsx | 4 +- .../ConfirmDiscardDialog.stories.tsx | 6 +- ts/components/ConfirmDiscardDialog.tsx | 6 +- ts/components/ConfirmationDialog.stories.tsx | 8 +- ts/components/ConfirmationDialog.tsx | 186 ++- ts/components/ContactPill.tsx | 7 +- ts/components/ContactPills.stories.tsx | 78 +- ts/components/ContactPills.tsx | 8 +- ts/components/ContextMenu.stories.tsx | 4 +- ts/components/ConversationList.stories.tsx | 596 ++++---- ts/components/ConversationList.tsx | 12 +- ts/components/CustomColorEditor.stories.tsx | 6 +- ts/components/CustomColorEditor.tsx | 246 ++-- ...omizingPreferredReactionsModal.stories.tsx | 32 +- ts/components/DebugLogWindow.tsx | 6 +- ts/components/DialogExpiredBuild.tsx | 6 +- ts/components/DialogNetworkStatus.stories.tsx | 164 ++- ts/components/DialogNetworkStatus.tsx | 6 +- ts/components/DialogRelink.stories.tsx | 8 +- ts/components/DialogRelink.tsx | 6 +- ts/components/DialogUpdate.stories.tsx | 408 +++--- ts/components/DialogUpdate.tsx | 6 +- ts/components/DirectCallRemoteParticipant.tsx | 6 +- .../DisappearingTimeDialog.stories.tsx | 90 +- .../DisappearingTimerSelect.stories.tsx | 16 +- ts/components/DisappearingTimerSelect.tsx | 4 +- .../EditUsernameModalBody.stories.tsx | 1 + ts/components/EditUsernameModalBody.tsx | 6 +- ts/components/ErrorModal.stories.tsx | 8 +- ts/components/ErrorModal.tsx | 4 +- ts/components/ForwardMessageModal.stories.tsx | 48 +- ts/components/ForwardMessageModal.tsx | 7 +- ts/components/GlobalAudioContext.tsx | 6 +- ts/components/GlobalModalContainer.tsx | 6 +- ts/components/GradientDial.tsx | 6 +- .../GroupCallOverflowArea.stories.tsx | 107 +- ts/components/GroupCallOverflowArea.tsx | 8 +- .../GroupCallRemoteParticipant.stories.tsx | 94 +- ts/components/GroupCallRemoteParticipant.tsx | 2 +- ts/components/GroupCallRemoteParticipants.tsx | 6 +- .../GroupDescriptionInput.stories.tsx | 26 +- ts/components/GroupDescriptionInput.tsx | 5 +- ts/components/GroupDescriptionText.tsx | 7 +- ts/components/GroupDialog.tsx | 69 +- ts/components/GroupTitleInput.stories.tsx | 26 +- ts/components/GroupTitleInput.tsx | 5 +- .../GroupV1MigrationDialog.stories.tsx | 41 +- ts/components/GroupV1MigrationDialog.tsx | 2 +- ts/components/GroupV2JoinDialog.stories.tsx | 24 +- ts/components/GroupV2JoinDialog.tsx | 4 +- ts/components/IdenticonSVG.stories.tsx | 4 +- ts/components/InContactsIcon.stories.tsx | 4 +- ts/components/InContactsIcon.tsx | 4 +- ts/components/Inbox.tsx | 6 +- ts/components/IncomingCallBar.stories.tsx | 160 ++- ts/components/IncomingCallBar.tsx | 16 +- ts/components/Input.stories.tsx | 124 +- ts/components/Input.tsx | 373 +++-- ts/components/InstallScreen.tsx | 2 +- ts/components/Intl.stories.tsx | 1 + ts/components/LeftPane.stories.tsx | 1201 +++++++++-------- ts/components/LeftPane.tsx | 22 +- ts/components/LeftPaneDialog.tsx | 6 +- ts/components/LeftPaneSearchInput.tsx | 6 +- ts/components/Lightbox.stories.tsx | 330 ++--- ts/components/ListView.tsx | 6 +- ts/components/MainHeader.stories.tsx | 1 + ts/components/MediaEditor.stories.tsx | 64 +- ts/components/MediaEditor.tsx | 6 +- .../MediaQualitySelector.stories.tsx | 22 +- ts/components/MediaQualitySelector.tsx | 6 +- ts/components/Modal.stories.tsx | 374 ++--- ts/components/Modal.tsx | 5 +- ts/components/ModalHost.tsx | 216 ++- ts/components/MyStories.stories.tsx | 1 + ts/components/MyStories.tsx | 6 +- ts/components/MyStoryButton.stories.tsx | 1 + ts/components/MyStoryButton.tsx | 20 +- .../NeedsScreenRecordingPermissionsModal.tsx | 6 +- ...atedGroupInvitedContactsDialog.stories.tsx | 40 +- ...NewlyCreatedGroupInvitedContactsDialog.tsx | 14 +- .../OutgoingGiftBadgeModal.stories.tsx | 8 +- ts/components/OutgoingGiftBadgeModal.tsx | 6 +- ts/components/PermissionsPopup.tsx | 6 +- ts/components/PopperRootContext.tsx | 6 +- ts/components/Preferences.stories.tsx | 1 + ts/components/Preferences.tsx | 18 +- ts/components/ProfileEditor.stories.tsx | 1 + ts/components/ProfileEditor.tsx | 6 +- ts/components/ProfileEditorModal.tsx | 40 +- ts/components/Profiler.tsx | 8 +- ts/components/ProgressDialog.stories.tsx | 4 +- ts/components/ProgressDialog.tsx | 4 +- ts/components/ProgressModal.stories.tsx | 4 +- ts/components/ProgressModal.tsx | 4 +- ts/components/QrCode.stories.tsx | 14 +- ts/components/ReactionPickerPicker.tsx | 141 +- .../SafetyNumberChangeDialog.stories.tsx | 32 +- ts/components/SafetyNumberChangeDialog.tsx | 6 +- ts/components/SafetyNumberModal.tsx | 6 +- ts/components/SafetyNumberViewer.stories.tsx | 28 +- ts/components/SafetyNumberViewer.tsx | 6 +- ts/components/SampleMessageBubbles.tsx | 60 +- ts/components/SearchInput.tsx | 4 +- ts/components/Select.stories.tsx | 30 +- ts/components/Select.tsx | 92 +- ts/components/SendStoryModal.stories.tsx | 1 + ts/components/SendStoryModal.tsx | 6 +- ts/components/SharedGroupNames.tsx | 7 +- ts/components/ShortcutGuide.stories.tsx | 12 +- ts/components/ShortcutGuide.tsx | 4 +- ts/components/ShortcutGuideModal.tsx | 4 +- .../SignalConnectionsModal.stories.tsx | 1 + ts/components/SignalConnectionsModal.tsx | 6 +- ts/components/Slider.stories.tsx | 16 +- ts/components/Slider.tsx | 6 +- ts/components/Spinner.stories.tsx | 12 +- ts/components/Spinner.tsx | 6 +- ts/components/StandaloneRegistration.tsx | 12 +- ts/components/StopPropagation.tsx | 24 +- ts/components/Stories.stories.tsx | 1 + ts/components/Stories.tsx | 6 +- ts/components/StoriesAddStoryButton.tsx | 6 +- ts/components/StoriesPane.tsx | 134 +- .../StoriesSettingsModal.stories.tsx | 1 + ts/components/StoriesSettingsModal.tsx | 30 +- ts/components/StoryCreator.stories.tsx | 1 + ts/components/StoryCreator.tsx | 6 +- ts/components/StoryDetailsModal.stories.tsx | 1 + ts/components/StoryDetailsModal.tsx | 6 +- ts/components/StoryDistributionListName.tsx | 6 +- ts/components/StoryImage.stories.tsx | 194 +-- ts/components/StoryImage.tsx | 6 +- ts/components/StoryLinkPreview.stories.tsx | 1 + ts/components/StoryLinkPreview.tsx | 6 +- ts/components/StoryListItem.stories.tsx | 1 + ts/components/StoryListItem.tsx | 34 +- ts/components/StoryViewer.stories.tsx | 1 + ts/components/StoryViewer.tsx | 96 +- .../StoryViewsNRepliesModal.stories.tsx | 1 + ts/components/StoryViewsNRepliesModal.tsx | 12 +- ts/components/Tabs.tsx | 4 +- ts/components/TextAttachment.stories.tsx | 518 +++---- ts/components/TextAttachment.tsx | 90 +- ts/components/TextStoryCreator.tsx | 6 +- ts/components/TitleBarContainer.tsx | 4 +- ts/components/TitlebarDragArea.tsx | 6 +- ts/components/Toast.tsx | 152 +-- ts/components/ToastAlreadyGroupMember.tsx | 6 +- ts/components/ToastAlreadyRequestedToJoin.tsx | 6 +- ts/components/ToastBlocked.tsx | 4 +- ts/components/ToastBlockedGroup.tsx | 7 +- ...stCannotMixMultiAndNonMultiAttachments.tsx | 6 +- ts/components/ToastCannotOpenGiftBadge.tsx | 6 +- ts/components/ToastCannotStartGroupCall.tsx | 6 +- ts/components/ToastCaptchaFailed.tsx | 7 +- ts/components/ToastCaptchaSolved.tsx | 7 +- ts/components/ToastConversationArchived.tsx | 6 +- .../ToastConversationMarkedUnread.tsx | 6 +- ts/components/ToastConversationUnarchived.tsx | 6 +- ts/components/ToastDangerousFileType.tsx | 6 +- ts/components/ToastDebugLogError.tsx | 7 +- .../ToastDeleteForEveryoneFailed.tsx | 6 +- ts/components/ToastExpired.tsx | 4 +- .../ToastFailedToFetchPhoneNumber.tsx | 6 +- ts/components/ToastFailedToFetchUsername.tsx | 6 +- ts/components/ToastFileSaved.tsx | 6 +- ts/components/ToastFileSize.tsx | 6 +- ts/components/ToastGroupLinkCopied.tsx | 6 +- ts/components/ToastInternalError.stories.tsx | 32 +- ts/components/ToastInternalError.tsx | 4 +- ts/components/ToastInvalidConversation.tsx | 6 +- ts/components/ToastLeftGroup.tsx | 4 +- ts/components/ToastLinkCopied.tsx | 4 +- ts/components/ToastLoadingFullLogs.tsx | 6 +- ts/components/ToastManager.stories.tsx | 1 + ts/components/ToastManager.tsx | 6 +- ts/components/ToastMaxAttachments.tsx | 7 +- ts/components/ToastMessageBodyTooLong.tsx | 6 +- .../ToastOriginalMessageNotFound.tsx | 6 +- .../ToastPinnedConversationsFull.tsx | 6 +- ts/components/ToastReactionFailed.tsx | 7 +- ts/components/ToastReportedSpamAndBlocked.tsx | 6 +- .../ToastStickerPackInstallFailed.tsx | 6 +- .../ToastTapToViewExpiredIncoming.tsx | 6 +- .../ToastTapToViewExpiredOutgoing.tsx | 6 +- ts/components/ToastUnableToLoadAttachment.tsx | 6 +- .../ToastUnsupportedMultiAttachment.tsx | 6 +- ts/components/ToastVoiceNoteError.tsx | 7 +- ts/components/ToastVoiceNoteLimit.tsx | 7 +- .../ToastVoiceNoteMustBeOnlyAttachment.tsx | 6 +- ts/components/Tooltip.stories.tsx | 46 +- ts/components/Tooltip.tsx | 9 +- ts/components/WhatsNewLink.tsx | 4 +- ts/components/WhatsNewModal.stories.tsx | 6 +- ts/components/WhatsNewModal.tsx | 6 +- ts/components/conversation/About.tsx | 6 +- .../conversation/AddNewLines.stories.tsx | 20 +- .../conversation/AtMentionify.stories.tsx | 12 +- ts/components/conversation/AtMentionify.tsx | 6 +- .../conversation/AttachmentList.stories.tsx | 16 +- ts/components/conversation/AttachmentList.tsx | 6 +- .../conversation/AudioCapture.stories.tsx | 12 +- ts/components/conversation/AudioCapture.tsx | 6 +- .../CallingNotification.stories.tsx | 320 +++-- .../conversation/CallingNotification.tsx | 84 +- .../ChangeNumberNotification.stories.tsx | 36 +- .../conversation/ChangeNumberNotification.tsx | 4 +- .../ChatSessionRefreshedDialog.stories.tsx | 4 +- ...atSessionRefreshedNotification.stories.tsx | 4 +- .../conversation/ContactDetail.stories.tsx | 36 +- .../conversation/ContactModal.stories.tsx | 1 + ts/components/conversation/ContactModal.tsx | 6 +- .../conversation/ContactName.stories.tsx | 26 +- ts/components/conversation/ContactName.tsx | 6 +- .../ContactSpoofingReviewDialog.stories.tsx | 110 +- .../ContactSpoofingReviewDialog.tsx | 8 +- .../ContactSpoofingReviewDialogPerson.tsx | 15 +- .../ConversationHeader.stories.tsx | 16 +- .../conversation/ConversationHero.stories.tsx | 1 + .../conversation/ConversationHero.tsx | 6 +- .../conversation/ConversationView.tsx | 6 +- .../DeliveryIssueDialog.stories.tsx | 8 +- .../DeliveryIssueNotification.stories.tsx | 12 +- .../conversation/EmbeddedContact.tsx | 4 +- .../conversation/Emojify.stories.tsx | 48 +- .../conversation/ErrorBoundary.stories.tsx | 4 +- .../conversation/ExpireTimer.stories.tsx | 28 +- ts/components/conversation/GIF.tsx | 4 +- .../conversation/GroupDescription.stories.tsx | 86 +- .../conversation/GroupDescription.tsx | 6 +- .../GroupV1DisabledActions.stories.tsx | 4 +- .../conversation/GroupV1DisabledActions.tsx | 6 +- .../conversation/GroupV1Migration.stories.tsx | 94 +- .../conversation/GroupV2Change.stories.tsx | 100 +- .../GroupV2PendingApprovalActions.stories.tsx | 4 +- .../GroupV2PendingApprovalActions.tsx | 6 +- ts/components/conversation/Image.stories.tsx | 80 +- .../conversation/ImageGrid.stories.tsx | 36 +- ts/components/conversation/ImageGrid.tsx | 6 +- .../LastSeenIndicator.stories.tsx | 8 +- .../conversation/LastSeenIndicator.tsx | 2 +- .../conversation/LinkPreviewDate.tsx | 6 +- .../conversation/Linkify.stories.tsx | 32 +- ...MandatoryProfileSharingActions.stories.tsx | 8 +- .../MandatoryProfileSharingActions.tsx | 6 +- ts/components/conversation/MessageAudio.tsx | 12 +- .../conversation/MessageBody.stories.tsx | 40 +- .../MessageBodyReadMore.stories.tsx | 56 +- .../conversation/MessageDetail.stories.tsx | 24 +- .../conversation/MessageMetadata.tsx | 6 +- .../MessageRequestActions.stories.tsx | 16 +- .../conversation/MessageRequestActions.tsx | 6 +- .../MessageRequestActionsConfirmation.tsx | 6 +- .../MessageTextMetadataSpacer.tsx | 10 +- .../conversation/MessageTimestamp.stories.tsx | 4 +- .../ProfileChangeNotification.stories.tsx | 12 +- ts/components/conversation/Quote.stories.tsx | 47 +- .../conversation/ReactionPicker.stories.tsx | 8 +- ts/components/conversation/ReactionPicker.tsx | 4 +- .../conversation/ReactionViewer.stories.tsx | 16 +- ts/components/conversation/ReactionViewer.tsx | 4 +- .../RemoveGroupMemberConfirmationDialog.tsx | 13 +- .../ResetSessionNotification.stories.tsx | 4 +- .../conversation/ResetSessionNotification.tsx | 8 +- .../SafetyNumberNotification.stories.tsx | 12 +- .../conversation/SafetyNumberNotification.tsx | 6 +- .../conversation/ScrollDownButton.stories.tsx | 1 + .../conversation/ScrollDownButton.tsx | 6 +- .../StagedGenericAttachment.stories.tsx | 12 +- .../conversation/StagedGenericAttachment.tsx | 6 +- .../StagedLinkPreview.stories.tsx | 1 + .../conversation/StagedLinkPreview.tsx | 6 +- .../StagedPlaceholderAttachment.stories.tsx | 4 +- .../StagedPlaceholderAttachment.tsx | 24 +- ts/components/conversation/SystemMessage.tsx | 2 +- .../conversation/Timeline.stories.tsx | 52 +- ts/components/conversation/Timeline.tsx | 1 + .../TimelineFloatingHeader.stories.tsx | 8 +- .../conversation/TimelineFloatingHeader.tsx | 6 +- .../conversation/TimelineItem.stories.tsx | 16 +- .../conversation/TimelineMessage.stories.tsx | 266 ++-- .../conversation/TimelineMessage.tsx | 10 +- .../conversation/TimelineWarning.tsx | 43 +- .../conversation/TimelineWarnings.tsx | 12 +- .../TimerNotification.stories.tsx | 16 +- .../conversation/TimerNotification.tsx | 8 +- .../conversation/TypingAnimation.stories.tsx | 8 +- .../conversation/TypingAnimation.tsx | 56 +- .../conversation/TypingBubble.stories.tsx | 12 +- .../UniversalTimerNotification.stories.tsx | 70 +- .../UniversalTimerNotification.tsx | 4 +- .../UnsupportedMessage.stories.tsx | 16 +- .../conversation/UnsupportedMessage.tsx | 6 +- .../VerificationNotification.stories.tsx | 20 +- .../AddGroupMembersModal.stories.tsx | 86 +- .../AddGroupMembersModal.tsx | 7 +- .../ChooseGroupMembersModal.tsx | 7 +- .../ConfirmAdditionsModal.tsx | 8 +- .../ConversationDetails.stories.tsx | 28 +- .../ConversationDetails.tsx | 36 +- .../ConversationDetailsActions.stories.tsx | 16 +- .../ConversationDetailsActions.tsx | 6 +- .../ConversationDetailsGroups.tsx | 6 +- .../ConversationDetailsHeader.stories.tsx | 52 +- .../ConversationDetailsHeader.tsx | 6 +- .../ConversationDetailsIcon.stories.tsx | 8 +- .../ConversationDetailsIcon.tsx | 6 +- .../ConversationDetailsMediaList.stories.tsx | 4 +- .../ConversationDetailsMediaList.tsx | 6 +- ...versationDetailsMembershipList.stories.tsx | 28 +- .../ConversationDetailsMembershipList.tsx | 6 +- .../ConversationNotificationsModal.tsx | 6 +- ...versationNotificationsSettings.stories.tsx | 34 +- .../ConversationNotificationsSettings.tsx | 9 +- ...ditConversationAttributesModal.stories.tsx | 58 +- .../EditConversationAttributesModal.tsx | 8 +- .../GroupLinkManagement.stories.tsx | 20 +- .../GroupLinkManagement.tsx | 6 +- .../GroupV2Permissions.stories.tsx | 66 +- .../GroupV2Permissions.tsx | 6 +- .../conversation-details/PanelRow.stories.tsx | 16 +- .../conversation-details/PanelRow.tsx | 4 +- .../PanelSection.stories.tsx | 16 +- .../conversation-details/PanelSection.tsx | 29 +- .../PendingInvites.stories.tsx | 8 +- .../conversation-details/PendingInvites.tsx | 6 +- .../AttachmentSection.stories.tsx | 8 +- .../DocumentListItem.stories.tsx | 24 +- .../media-gallery/EmptyState.stories.tsx | 4 +- .../conversation/media-gallery/EmptyState.tsx | 6 +- .../media-gallery/LoadingIndicator.tsx | 4 +- .../media-gallery/MediaGallery.stories.tsx | 20 +- .../media-gallery/MediaGallery.tsx | 6 +- .../media-gallery/MediaGridItem.stories.tsx | 28 +- .../conversationList/GroupListItem.tsx | 6 +- .../MessageBodyHighlight.stories.tsx | 24 +- .../MessageSearchResult.stories.tsx | 56 +- .../SearchResultsLoadingFakeHeader.tsx | 7 +- .../SearchResultsLoadingFakeRow.tsx | 21 +- .../UsernameSearchResultListItem.tsx | 7 +- ts/components/emoji/Emoji.stories.tsx | 12 +- ts/components/emoji/EmojiButton.stories.tsx | 4 +- ts/components/emoji/EmojiButton.tsx | 290 ++-- ts/components/emoji/EmojiPicker.stories.tsx | 12 +- ...llScreenChoosingDeviceNameStep.stories.tsx | 26 +- .../InstallScreenLinkInProgress.stories.tsx | 6 +- .../InstallScreenLinkInProgressStep.tsx | 22 +- ...tallScreenQrCodeNotScannedStep.stories.tsx | 102 +- .../InstallScreenQrCodeNotScannedStep.tsx | 95 +- .../installScreen/InstallScreenSignalLogo.tsx | 7 +- .../stickers/StickerButton.stories.tsx | 36 +- ts/components/stickers/StickerButton.tsx | 613 +++++---- .../stickers/StickerManager.stories.tsx | 20 +- ts/components/stickers/StickerManager.tsx | 210 ++- .../stickers/StickerManagerPackRow.tsx | 4 +- .../stickers/StickerPackInstallButton.tsx | 37 +- .../stickers/StickerPicker.stories.tsx | 28 +- .../stickers/StickerPreviewModal.stories.tsx | 16 +- .../stickers/StickerPreviewModal.tsx | 4 +- ts/groups/joinViaLink.tsx | 2 + ts/model-types.d.ts | 2 - ts/mp4box.d.ts | 2 - ts/sql/Interface.ts | 1 - ts/state/ducks/conversations.ts | 2 - ts/state/smart/CompositionTextArea.tsx | 6 +- ts/state/smart/ContactName.tsx | 4 +- .../smart/ContactSpoofingReviewDialog.tsx | 8 +- ts/state/smart/EmojiPicker.tsx | 5 +- ts/state/smart/ReactionPicker.tsx | 2 +- .../helpers/FakeLeftPaneContainer.tsx | 8 +- .../jobs/JobQueueDatabaseStore_test.ts | 1 + ts/textsecure/Types.d.ts | 2 +- ts/types/Calling.ts | 4 +- ts/types/Dialogs.ts | 2 - ts/types/I18N.ts | 2 - ts/types/LinkPreview.ts | 2 +- ts/types/Message.ts | 2 - ts/types/Storage.d.ts | 2 +- ts/util/durations/duration-in-seconds.ts | 1 - ts/util/iterables.ts | 1 + ts/util/lint/exceptions.json | 294 +--- ts/util/lint/linter.ts | 13 +- ts/views/conversation_view.tsx | 1 + yarn.lock | 1088 +++++++-------- 499 files changed, 8995 insertions(+), 8494 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 147cc94227..5599c44fd2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -94,6 +94,33 @@ const rules = { // Prefer functional components with default params 'react/require-default-props': 'off', + // Empty fragments are used in adapters between backbone and react views. + 'react/jsx-no-useless-fragment': ['error', { + allowExpressions: true, + }], + + // Our code base has tons of arrow functions passed directly to components. + 'react/jsx-no-bind': 'off', + + // Does not support forwardRef + 'react/no-unused-prop-types': 'off', + + // Not useful for us as we have lots of complicated types. + 'react/destructuring-assignment': 'off', + + 'react/function-component-definition': ['error', { + namedComponents: 'function-declaration', + unnamedComponents: 'arrow-function', + }], + + 'react/display-name': 'error', + + // Allow returning values from promise executors for brevity. + 'no-promise-executor-return': 'off', + + // Redux ducks use this a lot + 'default-param-last': 'off', + 'jsx-a11y/label-has-associated-control': ['error', { assert: 'either' }], 'no-restricted-syntax': [ diff --git a/package.json b/package.json index e5e4d8d4b6..7fcee2fd1f 100644 --- a/package.json +++ b/package.json @@ -259,8 +259,8 @@ "@types/webpack-dev-server": "3.11.3", "@types/websocket": "1.0.0", "@types/yargs": "17.0.7", - "@typescript-eslint/eslint-plugin": "5.6.0", - "@typescript-eslint/parser": "5.6.0", + "@typescript-eslint/eslint-plugin": "5.43.0", + "@typescript-eslint/parser": "5.43.0", "arraybuffer-loader": "1.0.3", "asar": "3.1.0", "babel-core": "7.0.0-bridge.0", @@ -281,13 +281,13 @@ "electron-notarize": "1.2.1", "endanger": "7.0.4", "esbuild": "0.15.8", - "eslint": "7.7.0", - "eslint-config-airbnb-typescript-prettier": "4.2.0", - "eslint-config-prettier": "6.11.0", - "eslint-plugin-import": "2.22.0", - "eslint-plugin-mocha": "9.0.0", - "eslint-plugin-more": "1.0.0", - "eslint-plugin-react": "7.20.6", + "eslint": "8.27.0", + "eslint-config-airbnb-typescript-prettier": "5.0.0", + "eslint-config-prettier": "8.5.0", + "eslint-plugin-import": "2.26.0", + "eslint-plugin-mocha": "10.1.0", + "eslint-plugin-more": "1.0.5", + "eslint-plugin-react": "7.31.10", "file-loader": "4.2.0", "html-webpack-plugin": "5.3.1", "json-to-ast": "2.1.0", @@ -298,7 +298,7 @@ "nyc": "11.4.1", "patch-package": "6.4.7", "playwright": "1.17.1", - "prettier": "2.6.0", + "prettier": "2.7.1", "sass": "1.49.7", "sass-loader": "10.2.0", "sinon": "11.1.1", diff --git a/sticker-creator/app/index.tsx b/sticker-creator/app/index.tsx index dbbb16cb40..29ccb1a905 100644 --- a/sticker-creator/app/index.tsx +++ b/sticker-creator/app/index.tsx @@ -20,10 +20,10 @@ export type AppPropsType = Readonly<{ hasCustomTitleBar: boolean; }>; -export const App = ({ +export function App({ executeMenuRole, hasCustomTitleBar, -}: AppPropsType): JSX.Element => { +}: AppPropsType): JSX.Element { const i18n = useI18n(); const theme = useTheme(); @@ -57,4 +57,4 @@ export const App = ({ ); -}; +} diff --git a/sticker-creator/app/stages/AppStage.tsx b/sticker-creator/app/stages/AppStage.tsx index e95bc001e6..ee24ed5d07 100644 --- a/sticker-creator/app/stages/AppStage.tsx +++ b/sticker-creator/app/stages/AppStage.tsx @@ -35,7 +35,7 @@ const getClassName = ({ noMessage, empty }: Props) => { return styles.main; }; -export const AppStage: React.ComponentType = props => { +export function AppStage(props: Props): JSX.Element { const { children, next, @@ -101,4 +101,4 @@ export const AppStage: React.ComponentType = props => { /> ); -}; +} diff --git a/sticker-creator/app/stages/DropStage.tsx b/sticker-creator/app/stages/DropStage.tsx index e252630818..d8a04f13c2 100644 --- a/sticker-creator/app/stages/DropStage.tsx +++ b/sticker-creator/app/stages/DropStage.tsx @@ -10,7 +10,7 @@ import { StickerGrid } from '../../components/StickerGrid'; import { stickersDuck } from '../../store'; import { useI18n } from '../../util/i18n'; -export const DropStage: React.ComponentType = () => { +export function DropStage(): JSX.Element { const i18n = useI18n(); const stickerPaths = stickersDuck.useStickerOrder(); const stickersReady = stickersDuck.useStickersReady(); @@ -40,4 +40,4 @@ export const DropStage: React.ComponentType = () => { ); -}; +} diff --git a/sticker-creator/app/stages/EmojiStage.tsx b/sticker-creator/app/stages/EmojiStage.tsx index 637d5f869f..2bf635ba67 100644 --- a/sticker-creator/app/stages/EmojiStage.tsx +++ b/sticker-creator/app/stages/EmojiStage.tsx @@ -9,7 +9,7 @@ import { StickerGrid } from '../../components/StickerGrid'; import { stickersDuck } from '../../store'; import { useI18n } from '../../util/i18n'; -export const EmojiStage: React.ComponentType = () => { +export function EmojiStage(): JSX.Element { const i18n = useI18n(); const emojisReady = stickersDuck.useEmojisReady(); @@ -26,4 +26,4 @@ export const EmojiStage: React.ComponentType = () => { ); -}; +} diff --git a/sticker-creator/app/stages/MetaStage.tsx b/sticker-creator/app/stages/MetaStage.tsx index 9ee59a19cc..93d735f9dd 100644 --- a/sticker-creator/app/stages/MetaStage.tsx +++ b/sticker-creator/app/stages/MetaStage.tsx @@ -14,7 +14,7 @@ import { ConfirmModal } from '../../components/ConfirmModal'; import { stickersDuck } from '../../store'; import { useI18n } from '../../util/i18n'; -export const MetaStage: React.ComponentType = () => { +export function MetaStage(): JSX.Element { const i18n = useI18n(); const actions = stickersDuck.useStickerActions(); const valid = stickersDuck.useAllDataValid(); @@ -99,4 +99,4 @@ export const MetaStage: React.ComponentType = () => { ); -}; +} diff --git a/sticker-creator/app/stages/ShareStage.tsx b/sticker-creator/app/stages/ShareStage.tsx index e9e1853d54..00edeae3df 100644 --- a/sticker-creator/app/stages/ShareStage.tsx +++ b/sticker-creator/app/stages/ShareStage.tsx @@ -15,7 +15,7 @@ import { stickersDuck } from '../../store'; import { useI18n } from '../../util/i18n'; import { Intl } from '../../../ts/components/Intl'; -export const ShareStage: React.ComponentType = () => { +export function ShareStage(): JSX.Element { const i18n = useI18n(); const actions = stickersDuck.useStickerActions(); const title = stickersDuck.useTitle(); @@ -94,4 +94,4 @@ export const ShareStage: React.ComponentType = () => { ) : null} ); -}; +} diff --git a/sticker-creator/app/stages/UploadStage.tsx b/sticker-creator/app/stages/UploadStage.tsx index 50fbbf0c9c..b4a5824bc9 100644 --- a/sticker-creator/app/stages/UploadStage.tsx +++ b/sticker-creator/app/stages/UploadStage.tsx @@ -18,7 +18,7 @@ const handleCancel = () => { history.push('/add-meta'); }; -export const UploadStage: React.ComponentType = () => { +export function UploadStage(): JSX.Element { const i18n = useI18n(); const actions = stickersDuck.useStickerActions(); const cover = stickersDuck.useCover(); @@ -81,4 +81,4 @@ export const UploadStage: React.ComponentType = () => { ); -}; +} diff --git a/sticker-creator/components/ConfirmModal.tsx b/sticker-creator/components/ConfirmModal.tsx index 8cabd28e2e..019316c40f 100644 --- a/sticker-creator/components/ConfirmModal.tsx +++ b/sticker-creator/components/ConfirmModal.tsx @@ -9,7 +9,9 @@ import { ConfirmDialog } from '../elements/ConfirmDialog'; export type Mode = 'removable' | 'pick-emoji' | 'add'; -export const ConfirmModal = React.memo((props: Props) => { +export const ConfirmModal = React.memo(function ConfirmModalInner( + props: Props +) { const { onCancel } = props; const [popperRoot, setPopperRoot] = React.useState(); diff --git a/sticker-creator/components/ShareButtons.tsx b/sticker-creator/components/ShareButtons.tsx index f5173be489..8d6bfd7ddc 100644 --- a/sticker-creator/components/ShareButtons.tsx +++ b/sticker-creator/components/ShareButtons.tsx @@ -12,7 +12,7 @@ export type Props = { }; export const ShareButtons: React.ComponentType = React.memo( - ({ value }) => { + function ShareButtonsInner({ value }) { const i18n = useI18n(); const buttonPaths = React.useMemo< diff --git a/sticker-creator/components/StickerFrame.stories.tsx b/sticker-creator/components/StickerFrame.stories.tsx index 7c0df44a9a..5187830080 100644 --- a/sticker-creator/components/StickerFrame.stories.tsx +++ b/sticker-creator/components/StickerFrame.stories.tsx @@ -47,7 +47,7 @@ _StickerFrame.story = { name: 'StickerFrame, add sticker', }; -export const EmojiSelectMode = (): JSX.Element => { +export function EmojiSelectMode(): JSX.Element { const image = text('image url', '/fixtures/512x515-thumbs-up-lincoln.webp'); const setSkinTone = action('setSkinTone'); const onRemove = action('onRemove'); @@ -71,7 +71,7 @@ export const EmojiSelectMode = (): JSX.Element => { /> ); -}; +} EmojiSelectMode.story = { name: 'StickerFrame, emoji select mode', diff --git a/sticker-creator/components/StickerFrame.tsx b/sticker-creator/components/StickerFrame.tsx index e764c2e1bb..9ba23b2b19 100644 --- a/sticker-creator/components/StickerFrame.tsx +++ b/sticker-creator/components/StickerFrame.tsx @@ -66,243 +66,239 @@ const ImageHandle = SortableHandle((props: { src: string }) => ( Sticker )); -export const StickerFrame = React.memo( - ({ - id, - emojiData, - image, - showGuide, - mode, - onRemove, - onPickEmoji, - skinTone, - onSetSkinTone, - onDrop, - }: Props) => { - const i18n = useI18n(); - const [emojiPickerOpen, setEmojiPickerOpen] = React.useState(false); - const [emojiPopperRoot, setEmojiPopperRoot] = - React.useState(null); - const [previewActive, setPreviewActive] = React.useState(false); - const [previewPopperRoot, setPreviewPopperRoot] = - React.useState(null); - const timerRef = React.useRef(); +export const StickerFrame = React.memo(function StickerFrameInner({ + id, + emojiData, + image, + showGuide, + mode, + onRemove, + onPickEmoji, + skinTone, + onSetSkinTone, + onDrop, +}: Props) { + const i18n = useI18n(); + const [emojiPickerOpen, setEmojiPickerOpen] = React.useState(false); + const [emojiPopperRoot, setEmojiPopperRoot] = + React.useState(null); + const [previewActive, setPreviewActive] = React.useState(false); + const [previewPopperRoot, setPreviewPopperRoot] = + React.useState(null); + const timerRef = React.useRef(); - const handleToggleEmojiPicker = React.useCallback(() => { - setEmojiPickerOpen(open => !open); - }, [setEmojiPickerOpen]); + const handleToggleEmojiPicker = React.useCallback(() => { + setEmojiPickerOpen(open => !open); + }, [setEmojiPickerOpen]); - const handlePickEmoji = React.useCallback( - (emoji: EmojiPickDataType) => { - if (!id) { - return; - } - if (!onPickEmoji) { - throw new Error( - 'StickerFrame/handlePickEmoji: onPickEmoji was not provided!' - ); - } - onPickEmoji({ id, emoji }); - setEmojiPickerOpen(false); - }, - [id, onPickEmoji, setEmojiPickerOpen] - ); - - const handleRemove = React.useCallback(() => { + const handlePickEmoji = React.useCallback( + (emoji: EmojiPickDataType) => { if (!id) { return; } - if (!onRemove) { + if (!onPickEmoji) { throw new Error( - 'StickerFrame/handleRemove: onRemove was not provided!' + 'StickerFrame/handlePickEmoji: onPickEmoji was not provided!' ); } - onRemove(id); - }, [onRemove, id]); + onPickEmoji({ id, emoji }); + setEmojiPickerOpen(false); + }, + [id, onPickEmoji, setEmojiPickerOpen] + ); - const handleMouseEnter = React.useCallback(() => { - window.clearTimeout(timerRef.current); - timerRef.current = window.setTimeout(() => { - setPreviewActive(true); - }, 500); - }, [timerRef, setPreviewActive]); + const handleRemove = React.useCallback(() => { + if (!id) { + return; + } + if (!onRemove) { + throw new Error('StickerFrame/handleRemove: onRemove was not provided!'); + } + onRemove(id); + }, [onRemove, id]); - const handleMouseLeave = React.useCallback(() => { + const handleMouseEnter = React.useCallback(() => { + window.clearTimeout(timerRef.current); + timerRef.current = window.setTimeout(() => { + setPreviewActive(true); + }, 500); + }, [timerRef, setPreviewActive]); + + const handleMouseLeave = React.useCallback(() => { + clearTimeout(timerRef.current); + setPreviewActive(false); + }, [timerRef, setPreviewActive]); + + React.useEffect( + () => () => { clearTimeout(timerRef.current); - setPreviewActive(false); - }, [timerRef, setPreviewActive]); + }, + [timerRef] + ); - React.useEffect( - () => () => { - clearTimeout(timerRef.current); - }, - [timerRef] - ); + const { createRoot, removeRoot } = React.useContext(PopperRootContext); - const { createRoot, removeRoot } = React.useContext(PopperRootContext); + // Create popper root and handle outside clicks + React.useEffect(() => { + if (emojiPickerOpen) { + const root = createRoot(); + setEmojiPopperRoot(root); + const handleOutsideClick = ({ target }: MouseEvent) => { + if (!root.contains(target as Node)) { + setEmojiPickerOpen(false); + } + }; + document.addEventListener('click', handleOutsideClick); - // Create popper root and handle outside clicks - React.useEffect(() => { - if (emojiPickerOpen) { - const root = createRoot(); - setEmojiPopperRoot(root); - const handleOutsideClick = ({ target }: MouseEvent) => { - if (!root.contains(target as Node)) { - setEmojiPickerOpen(false); - } - }; - document.addEventListener('click', handleOutsideClick); + return () => { + removeRoot(root); + setEmojiPopperRoot(null); + document.removeEventListener('click', handleOutsideClick); + }; + } - return () => { - removeRoot(root); - setEmojiPopperRoot(null); - document.removeEventListener('click', handleOutsideClick); - }; - } + return noop; + }, [ + createRoot, + emojiPickerOpen, + removeRoot, + setEmojiPickerOpen, + setEmojiPopperRoot, + ]); - return noop; - }, [ - createRoot, - emojiPickerOpen, - removeRoot, - setEmojiPickerOpen, - setEmojiPopperRoot, - ]); + React.useEffect(() => { + if (mode !== 'pick-emoji' && image && previewActive) { + const root = createRoot(); + setPreviewPopperRoot(root); - React.useEffect(() => { - if (mode !== 'pick-emoji' && image && previewActive) { - const root = createRoot(); - setPreviewPopperRoot(root); + return () => { + removeRoot(root); + }; + } - return () => { - removeRoot(root); - }; - } + return noop; + }, [ + createRoot, + image, + mode, + previewActive, + removeRoot, + setPreviewPopperRoot, + ]); - return noop; - }, [ - createRoot, - image, - mode, - previewActive, - removeRoot, - setPreviewPopperRoot, - ]); + const [dragActive, setDragActive] = React.useState(false); + const containerClass = dragActive ? styles.dragActive : styles.container; - const [dragActive, setDragActive] = React.useState(false); - const containerClass = dragActive ? styles.dragActive : styles.container; - - return ( - - - {({ ref: rootRef }) => ( -
- { - // eslint-disable-next-line no-nested-ternary - mode !== 'add' ? ( - image ? ( - - ) : ( -
{spinnerSvg}
- ) - ) : null - } - {showGuide && mode !== 'add' ? ( -
- ) : null} - {mode === 'add' && onDrop ? ( - - ) : null} - {mode === 'removable' ? ( - - ) : null} - {mode === 'pick-emoji' ? ( - - - {({ ref }) => ( - - )} - - {emojiPickerOpen && emojiPopperRoot - ? createPortal( - - {({ ref, style }) => ( - - )} - , - emojiPopperRoot - ) - : null} - - ) : null} - {mode !== 'pick-emoji' && - image && - previewActive && - previewPopperRoot - ? createPortal( - + + {({ ref: rootRef }) => ( +
+ { + // eslint-disable-next-line no-nested-ternary + mode !== 'add' ? ( + image ? ( + + ) : ( +
{spinnerSvg}
+ ) + ) : null + } + {showGuide && mode !== 'add' ? ( +
+ ) : null} + {mode === 'add' && onDrop ? ( + + ) : null} + {mode === 'removable' ? ( + + ) : null} + {mode === 'pick-emoji' ? ( + + + {({ ref }) => ( +
- )} - - - ); - } -); + + )} + + {emojiPickerOpen && emojiPopperRoot + ? createPortal( + + {({ ref, style }) => ( + + )} + , + emojiPopperRoot + ) + : null} + + ) : null} + {mode !== 'pick-emoji' && + image && + previewActive && + previewPopperRoot + ? createPortal( + + {({ ref, style, arrowProps, placement }) => ( + + )} + , + previewPopperRoot + ) + : null} +
+ )} +
+ + ); +}); diff --git a/sticker-creator/components/StickerPackPreview.tsx b/sticker-creator/components/StickerPackPreview.tsx index 2adbcc20a9..3dfce5e348 100644 --- a/sticker-creator/components/StickerPackPreview.tsx +++ b/sticker-creator/components/StickerPackPreview.tsx @@ -11,27 +11,29 @@ export type Props = { author: string; }; -export const StickerPackPreview = React.memo( - ({ images, title, author }: Props) => { - const i18n = useI18n(); +export const StickerPackPreview = React.memo(function StickerPackPreviewInner({ + images, + title, + author, +}: Props) { + const i18n = useI18n(); - return ( -
-
- {i18n('StickerCreator--Preview--title')} -
-
-
- {images.map(src => ( - {src} - ))} -
-
-
-
{title}
-
{author}
+ return ( +
+
+ {i18n('StickerCreator--Preview--title')} +
+
+
+ {images.map(src => ( + {src} + ))}
- ); - } -); +
+
{title}
+
{author}
+
+
+ ); +}); diff --git a/sticker-creator/components/Toaster.tsx b/sticker-creator/components/Toaster.tsx index 2d6b312233..22afe959c4 100644 --- a/sticker-creator/components/Toaster.tsx +++ b/sticker-creator/components/Toaster.tsx @@ -12,7 +12,11 @@ export type Props = React.HTMLAttributes & { const DEFAULT_DISMISS = 1e4; -export const Toaster = React.memo(({ loaf, onDismiss, className }: Props) => { +export const Toaster = React.memo(function ToasterInner({ + loaf, + onDismiss, + className, +}: Props) { const slice = last(loaf); React.useEffect(() => { diff --git a/sticker-creator/elements/Button.tsx b/sticker-creator/elements/Button.tsx index 6e05369c79..ad5e773d62 100644 --- a/sticker-creator/elements/Button.tsx +++ b/sticker-creator/elements/Button.tsx @@ -27,11 +27,11 @@ const getClassName = ({ primary, pill }: Props) => { return styles.base; }; -export const Button: React.ComponentType = ({ +export function Button({ className, children, ...otherProps -}) => { +}: React.PropsWithChildren): JSX.Element { return ( ); -}; +} diff --git a/sticker-creator/elements/ConfirmDialog.tsx b/sticker-creator/elements/ConfirmDialog.tsx index 5e1cff7e04..7a0909c0d7 100644 --- a/sticker-creator/elements/ConfirmDialog.tsx +++ b/sticker-creator/elements/ConfirmDialog.tsx @@ -14,14 +14,14 @@ export type Props = { readonly onCancel: () => unknown; }; -export const ConfirmDialog: React.ComponentType = ({ +export function ConfirmDialog({ title, children, confirm, cancel, onConfirm, onCancel, -}) => { +}: Props): JSX.Element { const i18n = useI18n(); const cancelText = cancel || i18n('StickerCreator--ConfirmDialog--cancel'); @@ -43,4 +43,4 @@ export const ConfirmDialog: React.ComponentType = ({
); -}; +} diff --git a/sticker-creator/elements/CopyText.tsx b/sticker-creator/elements/CopyText.tsx index 5a1e338c5f..c8e437a7e2 100644 --- a/sticker-creator/elements/CopyText.tsx +++ b/sticker-creator/elements/CopyText.tsx @@ -14,7 +14,7 @@ export type Props = { }; export const CopyText: React.ComponentType = React.memo( - ({ label, onCopy, value }) => { + function CopyTextInner({ label, onCopy, value }) { const i18n = useI18n(); const handleClick = React.useCallback(() => { copy(value); diff --git a/sticker-creator/elements/DropZone.tsx b/sticker-creator/elements/DropZone.tsx index 58a0f5e562..4a5752400c 100644 --- a/sticker-creator/elements/DropZone.tsx +++ b/sticker-creator/elements/DropZone.tsx @@ -28,7 +28,7 @@ const getClassName = ({ inner }: Props, isDragActive: boolean) => { return styles.standalone; }; -export const DropZone: React.ComponentType = props => { +export function DropZone(props: Props): JSX.Element { const { inner, label, onDrop, onDragActive } = props; const i18n = useI18n(); @@ -52,7 +52,7 @@ export const DropZone: React.ComponentType = props => {
@@ -67,4 +67,4 @@ export const DropZone: React.ComponentType = props => { ) : null}
); -}; +} diff --git a/sticker-creator/elements/LabeledCheckbox.tsx b/sticker-creator/elements/LabeledCheckbox.tsx index 5607cb71c3..9fc6d29649 100644 --- a/sticker-creator/elements/LabeledCheckbox.tsx +++ b/sticker-creator/elements/LabeledCheckbox.tsx @@ -17,28 +17,30 @@ const checkSvg = ( ); -export const LabeledCheckbox = React.memo( - ({ children, value, onChange }: Props) => { - const handleChange = React.useCallback(() => { - if (onChange !== undefined) { - onChange(!value); - } - }, [onChange, value]); +export const LabeledCheckbox = React.memo(function LabeledCheckboxInner({ + children, + value, + onChange, +}: Props) { + const handleChange = React.useCallback(() => { + if (onChange !== undefined) { + onChange(!value); + } + }, [onChange, value]); - const className = value ? styles.checkboxChecked : styles.checkbox; + const className = value ? styles.checkboxChecked : styles.checkbox; - return ( - - ); - } -); + return ( + + ); +}); diff --git a/sticker-creator/elements/LabeledInput.tsx b/sticker-creator/elements/LabeledInput.tsx index 095b150b41..a034bcc58b 100644 --- a/sticker-creator/elements/LabeledInput.tsx +++ b/sticker-creator/elements/LabeledInput.tsx @@ -12,28 +12,31 @@ export type Props = { onChange?: (value: string) => unknown; }; -export const LabeledInput = React.memo( - ({ children, value, placeholder, onChange }: Props) => { - const handleChange = React.useCallback( - (e: React.ChangeEvent) => { - if (onChange !== undefined) { - onChange(e.currentTarget.value); - } - }, - [onChange] - ); +export const LabeledInput = React.memo(function LabeledInputInner({ + children, + value, + placeholder, + onChange, +}: Props) { + const handleChange = React.useCallback( + (e: React.ChangeEvent) => { + if (onChange !== undefined) { + onChange(e.currentTarget.value); + } + }, + [onChange] + ); - return ( - - ); - } -); + return ( + + ); +}); diff --git a/sticker-creator/elements/MessageBubble.tsx b/sticker-creator/elements/MessageBubble.tsx index 8697ad6f09..a75f9cff25 100644 --- a/sticker-creator/elements/MessageBubble.tsx +++ b/sticker-creator/elements/MessageBubble.tsx @@ -10,14 +10,11 @@ export type Props = Pick & { children: React.ReactNode; }; -export const MessageBubble: React.ComponentType = ({ - children, - minutesAgo, -}) => { +export function MessageBubble({ children, minutesAgo }: Props): JSX.Element { return (
{children}
); -}; +} diff --git a/sticker-creator/elements/MessageMeta.tsx b/sticker-creator/elements/MessageMeta.tsx index 74c6bfe593..da754b34f3 100644 --- a/sticker-creator/elements/MessageMeta.tsx +++ b/sticker-creator/elements/MessageMeta.tsx @@ -22,7 +22,7 @@ const getItemClass = ({ kind }: Props) => { return styles.bubble; }; -export const MessageMeta = React.memo((props: Props) => { +export const MessageMeta = React.memo(function MessageMetaInner(props: Props) { const i18n = useI18n(); const itemClass = getItemClass(props); diff --git a/sticker-creator/elements/MessageSticker.tsx b/sticker-creator/elements/MessageSticker.tsx index b3495e48c7..95a98a344a 100644 --- a/sticker-creator/elements/MessageSticker.tsx +++ b/sticker-creator/elements/MessageSticker.tsx @@ -10,15 +10,15 @@ export type Props = MessageMetaProps & { image: string; }; -export const MessageSticker: React.ComponentType = ({ +export function MessageSticker({ image, kind, minutesAgo, -}) => { +}: Props): JSX.Element { return (
Sticker
); -}; +} diff --git a/sticker-creator/elements/PageHeader.tsx b/sticker-creator/elements/PageHeader.tsx index 2a17e9e190..d1ed108cc5 100644 --- a/sticker-creator/elements/PageHeader.tsx +++ b/sticker-creator/elements/PageHeader.tsx @@ -9,6 +9,8 @@ export type Props = { children: React.ReactNode; }; -export const PageHeader = React.memo(({ children }: Props) => ( -

{children}

-)); +export const PageHeader = React.memo(function PageHeaderInner({ + children, +}: Props) { + return

{children}

; +}); diff --git a/sticker-creator/elements/ProgressBar.tsx b/sticker-creator/elements/ProgressBar.tsx index 73fd513790..ac50a07e94 100644 --- a/sticker-creator/elements/ProgressBar.tsx +++ b/sticker-creator/elements/ProgressBar.tsx @@ -11,11 +11,17 @@ export type Props = Pick, 'className'> & { readonly total: number; }; -export const ProgressBar = React.memo(({ className, count, total }: Props) => ( -
-
-
-)); +export const ProgressBar = React.memo(function ProgressBarInner({ + className, + count, + total, +}: Props) { + return ( +
+
+
+ ); +}); diff --git a/sticker-creator/elements/StoryRow.tsx b/sticker-creator/elements/StoryRow.tsx index e981fe2ba2..dfa88582b6 100644 --- a/sticker-creator/elements/StoryRow.tsx +++ b/sticker-creator/elements/StoryRow.tsx @@ -31,7 +31,9 @@ const getClassName = ({ left, right, top, bottom }: Props) => { return styles.base; }; -export const StoryRow: React.ComponentType = ({ +export function StoryRow({ children, ...props -}) =>
{children}
; +}: React.PropsWithChildren): JSX.Element { + return
{children}
; +} diff --git a/sticker-creator/elements/Toast.tsx b/sticker-creator/elements/Toast.tsx index 702e5a2f15..433270dc07 100644 --- a/sticker-creator/elements/Toast.tsx +++ b/sticker-creator/elements/Toast.tsx @@ -9,12 +9,18 @@ export type Props = React.HTMLAttributes & { children: React.ReactNode; }; -export const Toast = React.memo(({ children, className, ...rest }: Props) => ( - -)); +export const Toast = React.memo(function ToastInner({ + children, + className, + ...rest +}: Props) { + return ( + + ); +}); diff --git a/sticker-creator/elements/Typography.stories.tsx b/sticker-creator/elements/Typography.stories.tsx index 6c30cbe7be..a531fc0e9d 100644 --- a/sticker-creator/elements/Typography.stories.tsx +++ b/sticker-creator/elements/Typography.stories.tsx @@ -1,7 +1,7 @@ // Copyright 2019-2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -/* eslint-disable no-script-url, jsx-a11y/anchor-is-valid */ +/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react'; import { text } from '@storybook/addon-knobs'; @@ -13,7 +13,7 @@ export default { title: 'Sticker Creator/elements', }; -export const Typography = (): JSX.Element => { +export function Typography(): JSX.Element { const child = text('text', 'foo bar'); return ( @@ -32,11 +32,9 @@ export const Typography = (): JSX.Element => { {child} {child} {child} {child}{' '} - - Something something something dark side. - + Something something something dark side. ); -}; +} diff --git a/sticker-creator/elements/Typography.tsx b/sticker-creator/elements/Typography.tsx index d4b6643057..a89621b48a 100644 --- a/sticker-creator/elements/Typography.tsx +++ b/sticker-creator/elements/Typography.tsx @@ -18,30 +18,38 @@ export type ParagraphProps = React.HTMLAttributes & { }; export type SpanProps = React.HTMLAttributes; -export const H1 = React.memo( - ({ children, className, ...rest }: Props & HeadingProps) => ( +export const H1 = React.memo(function H1Inner({ + children, + className, + ...rest +}: Props & HeadingProps) { + return (

{children}

- ) -); + ); +}); -export const H2 = React.memo( - ({ children, className, ...rest }: Props & HeadingProps) => ( +export const H2 = React.memo(function H2Inner({ + children, + className, + ...rest +}: Props & HeadingProps) { + return (

{children}

- ) -); + ); +}); -export const Text = React.memo( - ({ - children, - className, - center, - secondary, - ...rest - }: Props & ParagraphProps) => ( +export const Text = React.memo(function TextInner({ + children, + className, + center, + secondary, + ...rest +}: Props & ParagraphProps) { + return (

{children}

- ) -); + ); +}); -export const Inline = React.memo( - ({ children, className, ...rest }: Props & SpanProps) => ( +export const Inline = React.memo(function InlineInner({ + children, + className, + ...rest +}: Props & SpanProps) { + return ( {children} - ) -); + ); +}); diff --git a/sticker-creator/elements/icons/AddEmoji.tsx b/sticker-creator/elements/icons/AddEmoji.tsx index 9e1b1fb845..5cb0cb7902 100644 --- a/sticker-creator/elements/icons/AddEmoji.tsx +++ b/sticker-creator/elements/icons/AddEmoji.tsx @@ -3,8 +3,10 @@ import * as React from 'react'; -export const AddEmoji = React.memo(() => ( - - - -)); +export const AddEmoji = React.memo(function AddEmojiInner() { + return ( + + + + ); +}); diff --git a/sticker-creator/root.tsx b/sticker-creator/root.tsx index fb4714d922..139e64bd3e 100644 --- a/sticker-creator/root.tsx +++ b/sticker-creator/root.tsx @@ -12,17 +12,19 @@ import { I18n } from './util/i18n'; const { localeMessages, SignalContext } = window; -const ColdRoot = () => ( - - - - - - - -); +function ColdRoot() { + return ( + + + + + + + + ); +} export const Root = hot(ColdRoot); diff --git a/sticker-creator/store/ducks/stickers.ts b/sticker-creator/store/ducks/stickers.ts index 29d7d1f679..dd2c26c75b 100644 --- a/sticker-creator/store/ducks/stickers.ts +++ b/sticker-creator/store/ducks/stickers.ts @@ -31,6 +31,8 @@ import type { EmojiPickDataType } from '../../../ts/components/emoji/EmojiPicker import { convertShortName } from '../../../ts/components/emoji/lib'; import { isNotNil } from '../../../ts/util/isNotNil'; +type StickerEmojiData = { id: string; emoji: EmojiPickDataType }; + export const initializeStickers = createAction>( 'stickers/initializeStickers' ); @@ -41,8 +43,7 @@ export const removeSticker = createAction('stickers/removeSticker'); export const moveSticker = createAction('stickers/moveSticker'); export const setCover = createAction('stickers/setCover'); export const resetCover = createAction('stickers/resetCover'); -export const setEmoji = - createAction<{ id: string; emoji: EmojiPickDataType }>('stickers/setEmoji'); +export const setEmoji = createAction('stickers/setEmoji'); export const setTitle = createAction('stickers/setTitle'); export const setAuthor = createAction('stickers/setAuthor'); export const setPackMeta = createAction('stickers/setPackMeta'); diff --git a/sticker-creator/util/i18n.tsx b/sticker-creator/util/i18n.tsx index 03ddf70d5f..05d5958ec2 100644 --- a/sticker-creator/util/i18n.tsx +++ b/sticker-creator/util/i18n.tsx @@ -27,11 +27,7 @@ export type I18nProps = { messages: LocaleMessagesType; }; -export const I18n = ({ - messages, - locale, - children, -}: I18nProps): JSX.Element => { +export function I18n({ messages, locale, children }: I18nProps): JSX.Element { const { icuMessages, legacyMessages } = React.useMemo(() => { return classifyMessages(messages); }, [messages]); @@ -115,6 +111,6 @@ export const I18n = ({ return ( {children} ); -}; +} export const useI18n = (): LocalizerType => React.useContext(I18nContext); diff --git a/ts/components/About.tsx b/ts/components/About.tsx index d1c559f0fa..9e49e515fd 100644 --- a/ts/components/About.tsx +++ b/ts/components/About.tsx @@ -18,14 +18,14 @@ export type PropsType = { executeMenuRole: ExecuteMenuRoleType; }; -export const About = ({ +export function About({ closeAbout, i18n, environment, version, hasCustomTitleBar, executeMenuRole, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { useEscapeHandling(closeAbout); const theme = useTheme(); @@ -63,4 +63,4 @@ export const About = ({
); -}; +} diff --git a/ts/components/AddCaptionModal.stories.tsx b/ts/components/AddCaptionModal.stories.tsx index 3cc8e95cbb..270ba795f0 100644 --- a/ts/components/AddCaptionModal.stories.tsx +++ b/ts/components/AddCaptionModal.stories.tsx @@ -37,6 +37,7 @@ export default { }, } as Meta; +// eslint-disable-next-line react/function-component-definition const Template: Story = args => ( ); diff --git a/ts/components/AddCaptionModal.tsx b/ts/components/AddCaptionModal.tsx index ce8819b3bf..71bd4614de 100644 --- a/ts/components/AddCaptionModal.tsx +++ b/ts/components/AddCaptionModal.tsx @@ -19,14 +19,14 @@ export type Props = { ) => JSX.Element; }; -export const AddCaptionModal = ({ +export function AddCaptionModal({ i18n, onClose, onSubmit, draftText, RenderCompositionTextArea, theme, -}: Props): JSX.Element => { +}: Props): JSX.Element { const [messageText, setMessageText] = React.useState(''); const [isScrolledTop, setIsScrolledTop] = React.useState(true); @@ -84,4 +84,4 @@ export const AddCaptionModal = ({ /> ); -}; +} diff --git a/ts/components/AddGroupMemberErrorDialog.stories.tsx b/ts/components/AddGroupMemberErrorDialog.stories.tsx index 0265ef13d7..64f73f5fe4 100644 --- a/ts/components/AddGroupMemberErrorDialog.stories.tsx +++ b/ts/components/AddGroupMemberErrorDialog.stories.tsx @@ -35,13 +35,15 @@ _MaximumGroupSize.story = { name: 'Maximum group size', }; -export const MaximumRecommendedGroupSize = (): JSX.Element => ( - -); +export function MaximumRecommendedGroupSize(): JSX.Element { + return ( + + ); +} MaximumRecommendedGroupSize.story = { name: 'Maximum recommended group size', diff --git a/ts/components/AddGroupMemberErrorDialog.tsx b/ts/components/AddGroupMemberErrorDialog.tsx index 52f51c61f7..673b20e2d8 100644 --- a/ts/components/AddGroupMemberErrorDialog.tsx +++ b/ts/components/AddGroupMemberErrorDialog.tsx @@ -1,7 +1,7 @@ // Copyright 2021-2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { FunctionComponent, ReactNode } from 'react'; +import type { ReactNode } from 'react'; import React from 'react'; import type { LocalizerType } from '../types/Util'; @@ -28,9 +28,7 @@ type PropsType = { onClose: () => void; } & PropsDataType; -export const AddGroupMemberErrorDialog: FunctionComponent< - PropsType -> = props => { +export function AddGroupMemberErrorDialog(props: PropsType): JSX.Element { const { i18n, onClose } = props; let title: string; @@ -57,4 +55,4 @@ export const AddGroupMemberErrorDialog: FunctionComponent< } return ; -}; +} diff --git a/ts/components/AddUserToAnotherGroupModal.stories.tsx b/ts/components/AddUserToAnotherGroupModal.stories.tsx index 7cf0c08877..b1713a8910 100644 --- a/ts/components/AddUserToAnotherGroupModal.stories.tsx +++ b/ts/components/AddUserToAnotherGroupModal.stories.tsx @@ -39,6 +39,7 @@ export default { }, } as Meta; +// eslint-disable-next-line react/function-component-definition const Template: Story = args => ( { +}: Props): JSX.Element | null { const [searchTerm, setSearchTerm] = React.useState(''); const [filteredConversations, setFilteredConversations] = React.useState( filterAndSortConversationsByRecent(candidateConversations, '', undefined) @@ -177,7 +177,6 @@ export const AddUserToAnotherGroupModal = ({ onClickArchiveButton={noop} onClickContactCheckbox={noop} onSelectConversation={setSelectedGroupId} - renderMessageSearchResult={_ => <>} showChooseGroupMembers={noop} lookupConversationWithoutUuid={async _ => undefined} showUserNotFoundModal={noop} @@ -223,4 +222,4 @@ export const AddUserToAnotherGroupModal = ({ )} ); -}; +} diff --git a/ts/components/Alert.stories.tsx b/ts/components/Alert.stories.tsx index 77bfa86455..d590dcef9f 100644 --- a/ts/components/Alert.stories.tsx +++ b/ts/components/Alert.stories.tsx @@ -23,67 +23,75 @@ const defaultProps = { const LOREM_IPSUM = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.'; -export const TitleAndBodyAreStrings = (): JSX.Element => ( - -); +export function TitleAndBodyAreStrings(): JSX.Element { + return ( + + ); +} TitleAndBodyAreStrings.story = { name: 'Title and body are strings', }; -export const BodyIsAReactNode = (): JSX.Element => ( - - Hello{' '} - world! - - } - /> -); +export function BodyIsAReactNode(): JSX.Element { + return ( + + Hello{' '} + world! + + } + /> + ); +} BodyIsAReactNode.story = { name: 'Body is a ReactNode', }; -export const LongBodyWithoutTitle = (): JSX.Element => ( - -

{LOREM_IPSUM}

-

{LOREM_IPSUM}

-

{LOREM_IPSUM}

-

{LOREM_IPSUM}

- - } - /> -); +export function LongBodyWithoutTitle(): JSX.Element { + return ( + +

{LOREM_IPSUM}

+

{LOREM_IPSUM}

+

{LOREM_IPSUM}

+

{LOREM_IPSUM}

+ + } + /> + ); +} LongBodyWithoutTitle.story = { name: 'Long body (without title)', }; -export const LongBodyWithTitle = (): JSX.Element => ( - -

{LOREM_IPSUM}

-

{LOREM_IPSUM}

-

{LOREM_IPSUM}

-

{LOREM_IPSUM}

- - } - /> -); +export function LongBodyWithTitle(): JSX.Element { + return ( + +

{LOREM_IPSUM}

+

{LOREM_IPSUM}

+

{LOREM_IPSUM}

+

{LOREM_IPSUM}

+ + } + /> + ); +} LongBodyWithTitle.story = { name: 'Long body (with title)', diff --git a/ts/components/Alert.tsx b/ts/components/Alert.tsx index 532d8d6174..33b33c3b63 100644 --- a/ts/components/Alert.tsx +++ b/ts/components/Alert.tsx @@ -1,7 +1,7 @@ // Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { FunctionComponent, ReactNode } from 'react'; +import type { ReactNode } from 'react'; import React from 'react'; import type { LocalizerType } from '../types/Util'; @@ -17,23 +17,25 @@ type PropsType = { title?: string; }; -export const Alert: FunctionComponent = ({ +export function Alert({ body, i18n, onClose, theme, title, -}) => ( - {i18n('Confirmation--confirm')} - } - modalName="Alert" - onClose={onClose} - theme={theme} - title={title} - > - {body} - -); +}: PropsType): JSX.Element { + return ( + {i18n('Confirmation--confirm')} + } + modalName="Alert" + onClose={onClose} + theme={theme} + title={title} + > + {body} + + ); +} diff --git a/ts/components/AnimatedEmojiGalore.stories.tsx b/ts/components/AnimatedEmojiGalore.stories.tsx index 67704ade9d..491e2eec03 100644 --- a/ts/components/AnimatedEmojiGalore.stories.tsx +++ b/ts/components/AnimatedEmojiGalore.stories.tsx @@ -18,6 +18,6 @@ function getDefaultProps(): PropsType { }; } -export const Hearts = (): JSX.Element => ( - -); +export function Hearts(): JSX.Element { + return ; +} diff --git a/ts/components/AnimatedEmojiGalore.tsx b/ts/components/AnimatedEmojiGalore.tsx index 24a7a4c43a..1d9a3620f7 100644 --- a/ts/components/AnimatedEmojiGalore.tsx +++ b/ts/components/AnimatedEmojiGalore.tsx @@ -34,10 +34,10 @@ function transform(y: number, scale: number, rotate: number): string { return `translateY(${y}px) scale(${scale}) rotate(${rotate}deg)`; } -export const AnimatedEmojiGalore = ({ +export function AnimatedEmojiGalore({ emoji, onAnimationEnd, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [springs] = useSprings(NUM_EMOJIS, i => ({ ...to(i, onAnimationEnd), from: from(i), @@ -69,4 +69,4 @@ export const AnimatedEmojiGalore = ({ ))} ); -}; +} diff --git a/ts/components/AnnouncementsOnlyGroupBanner.tsx b/ts/components/AnnouncementsOnlyGroupBanner.tsx index 23b8b679e7..83319f6f54 100644 --- a/ts/components/AnnouncementsOnlyGroupBanner.tsx +++ b/ts/components/AnnouncementsOnlyGroupBanner.tsx @@ -15,12 +15,12 @@ type PropsType = { theme: ThemeType; }; -export const AnnouncementsOnlyGroupBanner = ({ +export function AnnouncementsOnlyGroupBanner({ groupAdmins, i18n, openConversation, theme, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [isShowingAdmins, setIsShowingAdmins] = useState(false); return ( @@ -64,4 +64,4 @@ export const AnnouncementsOnlyGroupBanner = ({
); -}; +} diff --git a/ts/components/App.tsx b/ts/components/App.tsx index b067973216..73f0cb79b3 100644 --- a/ts/components/App.tsx +++ b/ts/components/App.tsx @@ -55,7 +55,7 @@ type PropsType = { viewStory: ViewStoryActionCreatorType; } & ComponentProps; -export const App = ({ +export function App({ appView, executeMenuAction, executeMenuRole, @@ -89,7 +89,7 @@ export const App = ({ toast, toggleStoriesView, viewStory, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { let contents; if (appView === AppViewType.Installer) { @@ -183,4 +183,4 @@ export const App = ({
); -}; +} diff --git a/ts/components/Avatar.stories.tsx b/ts/components/Avatar.stories.tsx index e0f197004b..d904c22ca9 100644 --- a/ts/components/Avatar.stories.tsx +++ b/ts/components/Avatar.stories.tsx @@ -102,6 +102,7 @@ const sizes = Object.values(AvatarSize).filter( x => typeof x === 'number' ) as Array; +// eslint-disable-next-line react/function-component-definition const Template: Story = args => ( <> {sizes.map(size => ( @@ -110,6 +111,7 @@ const Template: Story = args => ( ); +// eslint-disable-next-line react/function-component-definition const TemplateSingle: Story = args => ( ); @@ -198,7 +200,7 @@ SearchIcon.args = createProps({ searchResult: true, }); -export const Colors = (): JSX.Element => { +export function Colors(): JSX.Element { const props = createProps(); return ( @@ -208,7 +210,7 @@ export const Colors = (): JSX.Element => { ))} ); -}; +} export const BrokenColor = Template.bind({}); BrokenColor.args = createProps({ diff --git a/ts/components/Avatar.tsx b/ts/components/Avatar.tsx index 6b254a505c..8dfc9042c5 100644 --- a/ts/components/Avatar.tsx +++ b/ts/components/Avatar.tsx @@ -1,13 +1,7 @@ // Copyright 2018-2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { - CSSProperties, - FunctionComponent, - MouseEvent, - ReactChild, - ReactNode, -} from 'react'; +import type { CSSProperties, MouseEvent, ReactChild, ReactNode } from 'react'; import React, { useEffect, useState } from 'react'; import classNames from 'classnames'; import { noop } from 'lodash'; @@ -98,7 +92,7 @@ const getDefaultBlur = ( ): AvatarBlur => shouldBlurAvatar(...args) ? AvatarBlur.BlurPicture : AvatarBlur.NoBlur; -export const Avatar: FunctionComponent = ({ +export function Avatar({ acceptedMessageRequest, avatarPath, badge, @@ -126,7 +120,7 @@ export const Avatar: FunctionComponent = ({ sharedGroupNames, unblurredAvatarPath, }), -}) => { +}: Props): JSX.Element { const [imageBroken, setImageBroken] = useState(false); useEffect(() => { @@ -312,7 +306,7 @@ export const Avatar: FunctionComponent = ({ {badgeNode}
); -}; +} // This is only exported for testing. export function _getBadgeSize(avatarSize: number): undefined | number { diff --git a/ts/components/AvatarColorPicker.stories.tsx b/ts/components/AvatarColorPicker.stories.tsx index 94d23f993c..c66e745de5 100644 --- a/ts/components/AvatarColorPicker.stories.tsx +++ b/ts/components/AvatarColorPicker.stories.tsx @@ -23,14 +23,16 @@ export default { title: 'Components/AvatarColorPicker', }; -export const Default = (): JSX.Element => ( - -); +export function Default(): JSX.Element { + return ; +} -export const Selected = (): JSX.Element => ( - -); +export function Selected(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/AvatarColorPicker.tsx b/ts/components/AvatarColorPicker.tsx index 8884522814..88c0e66f40 100644 --- a/ts/components/AvatarColorPicker.tsx +++ b/ts/components/AvatarColorPicker.tsx @@ -13,11 +13,11 @@ export type PropsType = { selectedColor?: AvatarColorType; }; -export const AvatarColorPicker = ({ +export function AvatarColorPicker({ i18n, onColorSelected, selectedColor, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { return ( <>
@@ -38,4 +38,4 @@ export const AvatarColorPicker = ({
); -}; +} diff --git a/ts/components/AvatarEditor.stories.tsx b/ts/components/AvatarEditor.stories.tsx index 3cf28f0c47..f4ef76f540 100644 --- a/ts/components/AvatarEditor.stories.tsx +++ b/ts/components/AvatarEditor.stories.tsx @@ -82,28 +82,37 @@ export default { title: 'Components/AvatarEditor', }; -export const NoAvatarGroup = (): JSX.Element => ( - -); +export function NoAvatarGroup(): JSX.Element { + return ( + + ); +} NoAvatarGroup.story = { name: 'No Avatar (group)', }; -export const NoAvatarMe = (): JSX.Element => ( - -); +export function NoAvatarMe(): JSX.Element { + return ( + + ); +} NoAvatarMe.story = { name: 'No Avatar (me)', }; -export const HasAvatar = (): JSX.Element => ( - -); +export function HasAvatar(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/AvatarEditor.tsx b/ts/components/AvatarEditor.tsx index a7533bdd19..be19271ed1 100644 --- a/ts/components/AvatarEditor.tsx +++ b/ts/components/AvatarEditor.tsx @@ -44,7 +44,7 @@ enum EditMode { Text = 'Text', } -export const AvatarEditor = ({ +export function AvatarEditor({ avatarColor, avatarPath, avatarValue, @@ -58,7 +58,7 @@ export const AvatarEditor = ({ userAvatarData, replaceAvatar, saveAvatarToDisk, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [provisionalSelectedAvatar, setProvisionalSelectedAvatar] = useState< AvatarDataType | undefined >(); @@ -298,4 +298,4 @@ export const AvatarEditor = ({ } return
{content}
; -}; +} diff --git a/ts/components/AvatarIconEditor.stories.tsx b/ts/components/AvatarIconEditor.stories.tsx index e8ba8bd727..2c655c88b5 100644 --- a/ts/components/AvatarIconEditor.stories.tsx +++ b/ts/components/AvatarIconEditor.stories.tsx @@ -25,24 +25,28 @@ export default { title: 'Components/AvatarIconEditor', }; -export const PersonalIcon = (): JSX.Element => ( - -); +export function PersonalIcon(): JSX.Element { + return ( + + ); +} -export const GroupIcon = (): JSX.Element => ( - -); +export function GroupIcon(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/AvatarIconEditor.tsx b/ts/components/AvatarIconEditor.tsx index 3084600806..80f80f8850 100644 --- a/ts/components/AvatarIconEditor.tsx +++ b/ts/components/AvatarIconEditor.tsx @@ -17,11 +17,11 @@ export type PropsType = { onClose: (avatarData?: AvatarDataType) => unknown; }; -export const AvatarIconEditor = ({ +export function AvatarIconEditor({ avatarData: initialAvatarData, i18n, onClose, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [avatarBuffer, setAvatarBuffer] = useState(); const [avatarData, setAvatarData] = useState(initialAvatarData); @@ -81,4 +81,4 @@ export const AvatarIconEditor = ({ /> ); -}; +} diff --git a/ts/components/AvatarLightbox.stories.tsx b/ts/components/AvatarLightbox.stories.tsx index 5e74193129..c06b798481 100644 --- a/ts/components/AvatarLightbox.stories.tsx +++ b/ts/components/AvatarLightbox.stories.tsx @@ -32,15 +32,17 @@ export default { title: 'Components/AvatarLightbox', }; -export const Group = (): JSX.Element => ( - -); +export function Group(): JSX.Element { + return ( + + ); +} -export const Person = (): JSX.Element => { +export function Person(): JSX.Element { const conversation = getDefaultConversation(); return ( { })} /> ); -}; +} -export const Photo = (): JSX.Element => ( - -); +export function Photo(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/AvatarLightbox.tsx b/ts/components/AvatarLightbox.tsx index d1fba0cc58..ea2a7e8ab2 100644 --- a/ts/components/AvatarLightbox.tsx +++ b/ts/components/AvatarLightbox.tsx @@ -17,14 +17,14 @@ export type PropsType = { onClose: () => unknown; }; -export const AvatarLightbox = ({ +export function AvatarLightbox({ avatarColor, avatarPath, conversationTitle, i18n, isGroup, onClose, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { return ( ); -}; +} diff --git a/ts/components/AvatarModalButtons.stories.tsx b/ts/components/AvatarModalButtons.stories.tsx index 814703954a..d4488f6645 100644 --- a/ts/components/AvatarModalButtons.stories.tsx +++ b/ts/components/AvatarModalButtons.stories.tsx @@ -23,21 +23,23 @@ export default { title: 'Components/AvatarModalButtons', }; -export const HasChanges = (): JSX.Element => ( - -); +export function HasChanges(): JSX.Element { + return ( + + ); +} HasChanges.story = { name: 'Has changes', }; -export const NoChanges = (): JSX.Element => ( - -); +export function NoChanges(): JSX.Element { + return ; +} NoChanges.story = { name: 'No changes', diff --git a/ts/components/AvatarModalButtons.tsx b/ts/components/AvatarModalButtons.tsx index a7cd70a968..02d2b91878 100644 --- a/ts/components/AvatarModalButtons.tsx +++ b/ts/components/AvatarModalButtons.tsx @@ -15,12 +15,12 @@ export type PropsType = { onSave: () => unknown; }; -export const AvatarModalButtons = ({ +export function AvatarModalButtons({ hasChanges, i18n, onCancel, onSave, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [confirmDiscardAction, setConfirmDiscardAction] = useState< (() => unknown) | undefined >(undefined); @@ -51,4 +51,4 @@ export const AvatarModalButtons = ({ )} ); -}; +} diff --git a/ts/components/AvatarPopup.stories.tsx b/ts/components/AvatarPopup.stories.tsx index 6f56792c1b..7e4d68faea 100644 --- a/ts/components/AvatarPopup.stories.tsx +++ b/ts/components/AvatarPopup.stories.tsx @@ -61,54 +61,54 @@ export default { title: 'Components/Avatar Popup', }; -export const AvatarOnly = (): JSX.Element => { +export function AvatarOnly(): JSX.Element { const props = useProps(); return ; -}; +} -export const HasBadge = (): JSX.Element => { +export function HasBadge(): JSX.Element { const props = useProps({ badge: getFakeBadge(), title: 'Janet Yellen', }); return ; -}; +} HasBadge.story = { name: 'Has badge', }; -export const Title = (): JSX.Element => { +export function Title(): JSX.Element { const props = useProps({ title: 'My Great Title', }); return ; -}; +} -export const ProfileName = (): JSX.Element => { +export function ProfileName(): JSX.Element { const props = useProps({ profileName: 'Sam Neill', }); return ; -}; +} -export const PhoneNumber = (): JSX.Element => { +export function PhoneNumber(): JSX.Element { const props = useProps({ profileName: 'Sam Neill', phoneNumber: '(555) 867-5309', }); return ; -}; +} -export const UpdateAvailable = (): JSX.Element => { +export function UpdateAvailable(): JSX.Element { const props = useProps({ hasPendingUpdate: true, }); return ; -}; +} diff --git a/ts/components/AvatarPopup.tsx b/ts/components/AvatarPopup.tsx index 7191de2171..fa986bf152 100644 --- a/ts/components/AvatarPopup.tsx +++ b/ts/components/AvatarPopup.tsx @@ -28,7 +28,7 @@ export type Props = { name?: string; } & Omit; -export const AvatarPopup = (props: Props): JSX.Element => { +export function AvatarPopup(props: Props): JSX.Element { const { hasPendingUpdate, i18n, @@ -121,4 +121,4 @@ export const AvatarPopup = (props: Props): JSX.Element => { )} ); -}; +} diff --git a/ts/components/AvatarPreview.stories.tsx b/ts/components/AvatarPreview.stories.tsx index 7633d1f6f8..3868ef0c40 100644 --- a/ts/components/AvatarPreview.stories.tsx +++ b/ts/components/AvatarPreview.stories.tsx @@ -39,85 +39,97 @@ export default { title: 'Components/AvatarPreview', }; -export const NoStatePersonal = (): JSX.Element => ( - -); +export function NoStatePersonal(): JSX.Element { + return ( + + ); +} NoStatePersonal.story = { name: 'No state (personal)', }; -export const NoStateGroup = (): JSX.Element => ( - -); +export function NoStateGroup(): JSX.Element { + return ( + + ); +} NoStateGroup.story = { name: 'No state (group)', }; -export const NoStateGroupUploadMe = (): JSX.Element => ( - -); +export function NoStateGroupUploadMe(): JSX.Element { + return ( + + ); +} NoStateGroupUploadMe.story = { name: 'No state (group) + upload me', }; -export const Value = (): JSX.Element => ( - -); +export function Value(): JSX.Element { + return ; +} Value.story = { name: 'value', }; -export const Path = (): JSX.Element => ( - -); +export function Path(): JSX.Element { + return ( + + ); +} Path.story = { name: 'path', }; -export const ValuePath = (): JSX.Element => ( - -); +export function ValuePath(): JSX.Element { + return ( + + ); +} ValuePath.story = { name: 'value & path', }; -export const Style = (): JSX.Element => ( - -); +export function Style(): JSX.Element { + return ( + + ); +} Style.story = { name: 'style', diff --git a/ts/components/AvatarPreview.tsx b/ts/components/AvatarPreview.tsx index 24e099b8fa..86f55a9eb5 100644 --- a/ts/components/AvatarPreview.tsx +++ b/ts/components/AvatarPreview.tsx @@ -33,7 +33,7 @@ enum ImageStatus { HasImage = 'has-image', } -export const AvatarPreview = ({ +export function AvatarPreview({ avatarColor = AvatarColors[0], avatarPath, avatarValue, @@ -45,7 +45,7 @@ export const AvatarPreview = ({ onClear, onClick, style = {}, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [avatarPreview, setAvatarPreview] = useState(); // Loads the initial avatarPath if one is provided, but only if we're in editable mode. @@ -199,4 +199,4 @@ export const AvatarPreview = ({ ); -}; +} diff --git a/ts/components/AvatarSpacer.tsx b/ts/components/AvatarSpacer.tsx index 54f63e7757..c3b3356ee5 100644 --- a/ts/components/AvatarSpacer.tsx +++ b/ts/components/AvatarSpacer.tsx @@ -5,8 +5,8 @@ import type { ReactElement } from 'react'; import React from 'react'; import type { AvatarSize } from './Avatar'; -export const AvatarSpacer = ({ +export function AvatarSpacer({ size, -}: Readonly<{ size: AvatarSize }>): ReactElement => ( -
-); +}: Readonly<{ size: AvatarSize }>): ReactElement { + return
; +} diff --git a/ts/components/AvatarTextEditor.stories.tsx b/ts/components/AvatarTextEditor.stories.tsx index 3fc93f159f..3d113be248 100644 --- a/ts/components/AvatarTextEditor.stories.tsx +++ b/ts/components/AvatarTextEditor.stories.tsx @@ -24,35 +24,41 @@ export default { title: 'Components/AvatarTextEditor', }; -export const Empty = (): JSX.Element => ; +export function Empty(): JSX.Element { + return ; +} -export const WithData = (): JSX.Element => ( - -); +export function WithData(): JSX.Element { + return ( + + ); +} WithData.story = { name: 'with Data', }; -export const WithWideCharacters = (): JSX.Element => ( - -); +export function WithWideCharacters(): JSX.Element { + return ( + + ); +} WithWideCharacters.story = { name: 'with wide characters', diff --git a/ts/components/AvatarTextEditor.tsx b/ts/components/AvatarTextEditor.tsx index 9c970c7de5..0df2611ac6 100644 --- a/ts/components/AvatarTextEditor.tsx +++ b/ts/components/AvatarTextEditor.tsx @@ -40,12 +40,12 @@ export type PropsType = { const BUBBLE_SIZE = 120; const MAX_LENGTH = 3; -export const AvatarTextEditor = ({ +export function AvatarTextEditor({ avatarData, i18n, onCancel, onDone, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const initialText = useMemo(() => avatarData?.text || '', [avatarData]); const initialColor = useMemo( () => avatarData?.color || AvatarColors[0], @@ -194,4 +194,4 @@ export const AvatarTextEditor = ({
); -}; +} diff --git a/ts/components/AvatarUploadButton.stories.tsx b/ts/components/AvatarUploadButton.stories.tsx index 3251b20a0d..1f4aed996b 100644 --- a/ts/components/AvatarUploadButton.stories.tsx +++ b/ts/components/AvatarUploadButton.stories.tsx @@ -22,6 +22,6 @@ export default { title: 'Components/AvatarUploadButton', }; -export const Default = (): JSX.Element => ( - -); +export function Default(): JSX.Element { + return ; +} diff --git a/ts/components/AvatarUploadButton.tsx b/ts/components/AvatarUploadButton.tsx index fd18b165f4..a98d450e9f 100644 --- a/ts/components/AvatarUploadButton.tsx +++ b/ts/components/AvatarUploadButton.tsx @@ -14,11 +14,11 @@ export type PropsType = { onChange: (avatar: Uint8Array) => unknown; }; -export const AvatarUploadButton = ({ +export function AvatarUploadButton({ className, i18n, onChange, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const fileInputRef = useRef(null); const [processingFile, setProcessingFile] = useState(); @@ -84,4 +84,4 @@ export const AvatarUploadButton = ({ /> ); -}; +} diff --git a/ts/components/BackboneHost.tsx b/ts/components/BackboneHost.tsx index aae61b0ecf..d29460e6d5 100644 --- a/ts/components/BackboneHost.tsx +++ b/ts/components/BackboneHost.tsx @@ -9,7 +9,7 @@ type PropsType = { className?: string; }; -export const BackboneHost = ({ View, className }: PropsType): JSX.Element => { +export function BackboneHost({ View, className }: PropsType): JSX.Element { const hostRef = useRef(null); const viewRef = useRef(undefined); @@ -35,4 +35,4 @@ export const BackboneHost = ({ View, className }: PropsType): JSX.Element => {
); -}; +} diff --git a/ts/components/BadgeDescription.stories.tsx b/ts/components/BadgeDescription.stories.tsx index 040b3c7f05..5edb8e2d51 100644 --- a/ts/components/BadgeDescription.stories.tsx +++ b/ts/components/BadgeDescription.stories.tsx @@ -9,24 +9,28 @@ export default { title: 'Components/BadgeDescription', }; -export const NormalName = (): JSX.Element => ( - -); +export function NormalName(): JSX.Element { + return ( + + ); +} NormalName.story = { name: 'Normal name', }; -export const NameWithRtlOverrides = (): JSX.Element => ( - -); +export function NameWithRtlOverrides(): JSX.Element { + return ( + + ); +} NameWithRtlOverrides.story = { name: 'Name with RTL overrides', diff --git a/ts/components/BadgeDialog.stories.tsx b/ts/components/BadgeDialog.stories.tsx index 3a155456b2..36ff3b2dcc 100644 --- a/ts/components/BadgeDialog.stories.tsx +++ b/ts/components/BadgeDialog.stories.tsx @@ -27,108 +27,120 @@ const defaultProps: ComponentProps = { title: 'Alice Levine', }; -export const NoBadgesClosedImmediately = (): JSX.Element => ( - -); +export function NoBadgesClosedImmediately(): JSX.Element { + return ; +} NoBadgesClosedImmediately.story = { name: 'No badges (closed immediately)', }; -export const OneBadge = (): JSX.Element => ( - -); +export function OneBadge(): JSX.Element { + return ; +} OneBadge.story = { name: 'One badge', }; -export const BadgeWithNoImageShouldBeImpossible = (): JSX.Element => ( - -); +export function BadgeWithNoImageShouldBeImpossible(): JSX.Element { + return ( + + ); +} BadgeWithNoImageShouldBeImpossible.story = { name: 'Badge with no image (should be impossible)', }; -export const BadgeWithPendingImage = (): JSX.Element => ( - -); - -BadgeWithPendingImage.story = { - name: 'Badge with pending image', -}; - -export const BadgeWithOnlyOneLowDetailImage = (): JSX.Element => ( - -); + }, + ]} + /> + ); +} + +BadgeWithPendingImage.story = { + name: 'Badge with pending image', +}; + +export function BadgeWithOnlyOneLowDetailImage(): JSX.Element { + return ( + + ); +} BadgeWithOnlyOneLowDetailImage.story = { name: 'Badge with only one, low-detail image', }; -export const FiveBadges = (): JSX.Element => ( - -); +export function FiveBadges(): JSX.Element { + return ; +} FiveBadges.story = { name: 'Five badges', }; -export const ManyBadges = (): JSX.Element => ( - -); +export function ManyBadges(): JSX.Element { + return ; +} ManyBadges.story = { name: 'Many badges', }; -export const ManyBadgesUserIsASubscriber = (): JSX.Element => ( - -); +export function ManyBadgesUserIsASubscriber(): JSX.Element { + return ( + + ); +} ManyBadgesUserIsASubscriber.story = { name: 'Many badges, user is a subscriber', diff --git a/ts/components/BetterAvatar.stories.tsx b/ts/components/BetterAvatar.stories.tsx index b03d05f761..e07cae81c4 100644 --- a/ts/components/BetterAvatar.stories.tsx +++ b/ts/components/BetterAvatar.stories.tsx @@ -30,35 +30,41 @@ export default { title: 'Components/BetterAvatar', }; -export const Text = (): JSX.Element => ( - -); +export function Text(): JSX.Element { + return ( + + ); +} -export const PersonalIcon = (): JSX.Element => ( - -); +export function PersonalIcon(): JSX.Element { + return ( + + ); +} -export const GroupIcon = (): JSX.Element => ( - -); +export function GroupIcon(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/BetterAvatar.tsx b/ts/components/BetterAvatar.tsx index 6157322a59..144b7f6d54 100644 --- a/ts/components/BetterAvatar.tsx +++ b/ts/components/BetterAvatar.tsx @@ -21,14 +21,14 @@ export type PropsType = { size?: AvatarSize; }; -export const BetterAvatar = ({ +export function BetterAvatar({ avatarData, i18n, isSelected, onClick, onDelete, size = 48, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [avatarBuffer, setAvatarBuffer] = useState( avatarData.buffer ); @@ -115,4 +115,4 @@ export const BetterAvatar = ({ )} ); -}; +} diff --git a/ts/components/BetterAvatarBubble.stories.tsx b/ts/components/BetterAvatarBubble.stories.tsx index 0960937238..b4921bc95d 100644 --- a/ts/components/BetterAvatarBubble.stories.tsx +++ b/ts/components/BetterAvatarBubble.stories.tsx @@ -27,32 +27,38 @@ export default { title: 'Components/BetterAvatarBubble', }; -export const Children = (): JSX.Element => ( - HI
, - color: AvatarColors[8], - })} - /> -); +export function Children(): JSX.Element { + return ( + HI, + color: AvatarColors[8], + })} + /> + ); +} -export const Selected = (): JSX.Element => ( - -); +export function Selected(): JSX.Element { + return ( + + ); +} -export const Style = (): JSX.Element => ( - -); +export function Style(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/BetterAvatarBubble.tsx b/ts/components/BetterAvatarBubble.tsx index 296d3665c9..1bb06f3a68 100644 --- a/ts/components/BetterAvatarBubble.tsx +++ b/ts/components/BetterAvatarBubble.tsx @@ -18,7 +18,7 @@ export type PropsType = { style?: CSSProperties; }; -export const BetterAvatarBubble = ({ +export function BetterAvatarBubble({ children, color, i18n, @@ -26,7 +26,7 @@ export const BetterAvatarBubble = ({ onDelete, onSelect, style, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { return (
); -}; +} diff --git a/ts/components/Button.stories.tsx b/ts/components/Button.stories.tsx index 36446b56f1..7ad08a7f3e 100644 --- a/ts/components/Button.stories.tsx +++ b/ts/components/Button.stories.tsx @@ -10,55 +10,65 @@ export default { title: 'Components/Button', }; -export const KitchenSink = (): JSX.Element => ( - <> - {Object.values(ButtonVariant).map(variant => ( - - {[ButtonSize.Large, ButtonSize.Medium, ButtonSize.Small].map(size => ( - -

- -

-

- -

-
- ))} -
- ))} - -); +export function KitchenSink(): JSX.Element { + return ( + <> + {Object.values(ButtonVariant).map(variant => ( + + {[ButtonSize.Large, ButtonSize.Medium, ButtonSize.Small].map(size => ( + +

+ +

+

+ +

+
+ ))} +
+ ))} + + ); +} KitchenSink.story = { name: 'Kitchen sink', }; -export const AriaLabel = (): JSX.Element => ( - -); +export function CustomStyles(): JSX.Element { + return ( + + ); +} CustomStyles.story = { name: 'Custom styles', diff --git a/ts/components/Button.tsx b/ts/components/Button.tsx index fb60480818..99adbeaf20 100644 --- a/ts/components/Button.tsx +++ b/ts/components/Button.tsx @@ -100,7 +100,7 @@ const VARIANT_CLASS_NAMES = new Map([ ]); export const Button = React.forwardRef( - (props, ref) => { + function ButtonInner(props, ref) { const { children, className, diff --git a/ts/components/CallBackgroundBlur.tsx b/ts/components/CallBackgroundBlur.tsx index 63bb60d03c..2f62667f04 100644 --- a/ts/components/CallBackgroundBlur.tsx +++ b/ts/components/CallBackgroundBlur.tsx @@ -12,12 +12,12 @@ export type PropsType = { color?: AvatarColorType; }; -export const CallBackgroundBlur = ({ +export function CallBackgroundBlur({ avatarPath, children, className, color, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { return (
); -}; +} diff --git a/ts/components/CallManager.stories.tsx b/ts/components/CallManager.stories.tsx index 5504ddeccd..dbda846d6c 100644 --- a/ts/components/CallManager.stories.tsx +++ b/ts/components/CallManager.stories.tsx @@ -121,128 +121,142 @@ export default { title: 'Components/CallManager', }; -export const NoCall = (): JSX.Element => ; +export function NoCall(): JSX.Element { + return ; +} -export const OngoingDirectCall = (): JSX.Element => ( - -); +export function OngoingDirectCall(): JSX.Element { + return ( + + ); +} -export const OngoingGroupCall = (): JSX.Element => ( - (), - }, - })} - /> -); +export function OngoingGroupCall(): JSX.Element { + return ( + (), + }, + })} + /> + ); +} -export const RingingDirectCall = (): JSX.Element => ( - -); +export function RingingDirectCall(): JSX.Element { + return ( + + ); +} RingingDirectCall.story = { name: 'Ringing (direct call)', }; -export const RingingGroupCall = (): JSX.Element => ( - -); + })} + /> + ); +} RingingGroupCall.story = { name: 'Ringing (group call)', }; -export const CallRequestNeeded = (): JSX.Element => ( - -); +export function CallRequestNeeded(): JSX.Element { + return ( + + ); +} -export const GroupCallSafetyNumberChanged = (): JSX.Element => ( - (), - }, - })} - /> -); +export function GroupCallSafetyNumberChanged(): JSX.Element { + return ( + (), + }, + })} + /> + ); +} GroupCallSafetyNumberChanged.story = { name: 'Group call - Safety Number Changed', diff --git a/ts/components/CallManager.tsx b/ts/components/CallManager.tsx index 64ee7588c1..94227fc6bc 100644 --- a/ts/components/CallManager.tsx +++ b/ts/components/CallManager.tsx @@ -105,7 +105,7 @@ type ActiveCallManagerPropsType = PropsType & { activeCall: ActiveCallType; }; -const ActiveCallManager: React.FC = ({ +function ActiveCallManager({ activeCall, availableCameras, cancelCall, @@ -137,7 +137,7 @@ const ActiveCallManager: React.FC = ({ toggleScreenRecordingPermissionsDialog, toggleSettings, toggleSpeakerView, -}) => { +}: ActiveCallManagerPropsType): JSX.Element { const { conversation, hasLocalAudio, @@ -374,9 +374,9 @@ const ActiveCallManager: React.FC = ({ ) : null} ); -}; +} -export const CallManager: React.FC = props => { +export function CallManager(props: PropsType): JSX.Element | null { const { acceptCall, activeCall, @@ -449,7 +449,7 @@ export const CallManager: React.FC = props => { } return null; -}; +} function getShouldRing({ activeCall, diff --git a/ts/components/CallNeedPermissionScreen.tsx b/ts/components/CallNeedPermissionScreen.tsx index 87c5e1754a..db8f1d8105 100644 --- a/ts/components/CallNeedPermissionScreen.tsx +++ b/ts/components/CallNeedPermissionScreen.tsx @@ -29,11 +29,11 @@ type Props = { const AUTO_CLOSE_MS = 10000; -export const CallNeedPermissionScreen: React.FC = ({ +export function CallNeedPermissionScreen({ conversation, i18n, close, -}) => { +}: Props): JSX.Element { const title = conversation.title || i18n('unknownContact'); const autoCloseAtRef = useRef(Date.now() + AUTO_CLOSE_MS); @@ -79,4 +79,4 @@ export const CallNeedPermissionScreen: React.FC = ({
); -}; +} diff --git a/ts/components/CallScreen.stories.tsx b/ts/components/CallScreen.stories.tsx index e0bc727b7b..0b1d397daf 100644 --- a/ts/components/CallScreen.stories.tsx +++ b/ts/components/CallScreen.stories.tsx @@ -189,11 +189,11 @@ export default { title: 'Components/CallScreen', }; -export const Default = (): JSX.Element => { +export function Default(): JSX.Element { return ; -}; +} -export const PreRing = (): JSX.Element => { +export function PreRing(): JSX.Element { return ( { })} /> ); -}; +} PreRing.story = { name: 'Pre-Ring', @@ -241,7 +241,7 @@ export const _Ended = (): JSX.Element => { ); }; -export const HasLocalAudio = (): JSX.Element => { +export function HasLocalAudio(): JSX.Element { return ( { })} /> ); -}; +} HasLocalAudio.story = { name: 'hasLocalAudio', }; -export const HasLocalVideo = (): JSX.Element => { +export function HasLocalVideo(): JSX.Element { return ( { })} /> ); -}; +} HasLocalVideo.story = { name: 'hasLocalVideo', }; -export const HasRemoteVideo = (): JSX.Element => { +export function HasRemoteVideo(): JSX.Element { return ( { })} /> ); -}; +} HasRemoteVideo.story = { name: 'hasRemoteVideo', }; -export const GroupCall1 = (): JSX.Element => ( - -); +export function GroupCall1(): JSX.Element { + return ( + + ); +} GroupCall1.story = { name: 'Group call - 1', @@ -327,7 +329,7 @@ const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({ }), })); -export const GroupCallMany = (): JSX.Element => { +export function GroupCallMany(): JSX.Element { return ( { })} /> ); -}; +} GroupCallMany.story = { name: 'Group call - Many', }; -export const GroupCallReconnecting = (): JSX.Element => ( - -); +export function GroupCallReconnecting(): JSX.Element { + return ( + + ); +} GroupCallReconnecting.story = { name: 'Group call - reconnecting', }; -export const GroupCall0 = (): JSX.Element => ( - -); +export function GroupCall0(): JSX.Element { + return ( + + ); +} GroupCall0.story = { name: 'Group call - 0', }; -export const GroupCallSomeoneIsSharingScreen = (): JSX.Element => ( - ({ - ...participant, - presenting: index === 1, - sharingScreen: index === 1, - })), - })} - /> -); +export function GroupCallSomeoneIsSharingScreen(): JSX.Element { + return ( + ({ + ...participant, + presenting: index === 1, + sharingScreen: index === 1, + })), + })} + /> + ); +} GroupCallSomeoneIsSharingScreen.story = { name: 'Group call - someone is sharing screen', }; -export const GroupCallSomeoneIsSharingScreenAndYoureReconnecting = - (): JSX.Element => ( +export function GroupCallSomeoneIsSharingScreenAndYoureReconnecting(): JSX.Element { + return ( ); +} GroupCallSomeoneIsSharingScreenAndYoureReconnecting.story = { name: "Group call - someone is sharing screen and you're reconnecting", diff --git a/ts/components/CallScreen.tsx b/ts/components/CallScreen.tsx index dc0e70b7bd..cb2ed6c60d 100644 --- a/ts/components/CallScreen.tsx +++ b/ts/components/CallScreen.tsx @@ -119,7 +119,7 @@ function DirectCallHeaderMessage({ return null; } -export const CallScreen: React.FC = ({ +export function CallScreen({ activeCall, getGroupCallVideoFrameSource, getPresentingSources, @@ -143,7 +143,7 @@ export const CallScreen: React.FC = ({ toggleScreenRecordingPermissionsDialog, toggleSettings, toggleSpeakerView, -}) => { +}: PropsType): JSX.Element { const { conversation, hasLocalAudio, @@ -539,7 +539,7 @@ export const CallScreen: React.FC = ({
); -}; +} function getCallModeClassSuffix( callMode: CallMode.Direct | CallMode.Group diff --git a/ts/components/CallingAudioIndicator.stories.tsx b/ts/components/CallingAudioIndicator.stories.tsx index 75f992c2a4..04d38ed580 100644 --- a/ts/components/CallingAudioIndicator.stories.tsx +++ b/ts/components/CallingAudioIndicator.stories.tsx @@ -11,7 +11,7 @@ export default { title: 'Components/CallingAudioIndicator', }; -export const Extreme = (): JSX.Element => { +export function Extreme(): JSX.Element { const [audioLevel, setAudioLevel] = useState(1); useEffect(() => { @@ -30,9 +30,9 @@ export const Extreme = (): JSX.Element => { audioLevel={audioLevel} /> ); -}; +} -export const Random = (): JSX.Element => { +export function Random(): JSX.Element { const [audioLevel, setAudioLevel] = useState(1); useEffect(() => { @@ -51,4 +51,4 @@ export const Random = (): JSX.Element => { audioLevel={audioLevel} /> ); -}; +} diff --git a/ts/components/CallingButton.stories.tsx b/ts/components/CallingButton.stories.tsx index 3fc0b50494..969b6658c2 100644 --- a/ts/components/CallingButton.stories.tsx +++ b/ts/components/CallingButton.stories.tsx @@ -32,7 +32,7 @@ export default { title: 'Components/CallingButton', }; -export const KitchenSink = (): JSX.Element => { +export function KitchenSink(): JSX.Element { return ( <> {Object.keys(CallingButtonType).map(buttonType => ( @@ -43,71 +43,71 @@ export const KitchenSink = (): JSX.Element => { ))} ); -}; +} -export const AudioOn = (): JSX.Element => { +export function AudioOn(): JSX.Element { const props = createProps({ buttonType: CallingButtonType.AUDIO_ON, }); return ; -}; +} -export const AudioOff = (): JSX.Element => { +export function AudioOff(): JSX.Element { const props = createProps({ buttonType: CallingButtonType.AUDIO_OFF, }); return ; -}; +} -export const AudioDisabled = (): JSX.Element => { +export function AudioDisabled(): JSX.Element { const props = createProps({ buttonType: CallingButtonType.AUDIO_DISABLED, }); return ; -}; +} -export const VideoOn = (): JSX.Element => { +export function VideoOn(): JSX.Element { const props = createProps({ buttonType: CallingButtonType.VIDEO_ON, }); return ; -}; +} -export const VideoOff = (): JSX.Element => { +export function VideoOff(): JSX.Element { const props = createProps({ buttonType: CallingButtonType.VIDEO_OFF, }); return ; -}; +} -export const VideoDisabled = (): JSX.Element => { +export function VideoDisabled(): JSX.Element { const props = createProps({ buttonType: CallingButtonType.VIDEO_DISABLED, }); return ; -}; +} -export const TooltipRight = (): JSX.Element => { +export function TooltipRight(): JSX.Element { const props = createProps({ tooltipDirection: TooltipPlacement.Right, }); return ; -}; +} TooltipRight.story = { name: 'Tooltip right', }; -export const PresentingOn = (): JSX.Element => { +export function PresentingOn(): JSX.Element { const props = createProps({ buttonType: CallingButtonType.PRESENTING_ON, }); return ; -}; +} -export const PresentingOff = (): JSX.Element => { +export function PresentingOff(): JSX.Element { const props = createProps({ buttonType: CallingButtonType.PRESENTING_OFF, }); return ; -}; +} diff --git a/ts/components/CallingButton.tsx b/ts/components/CallingButton.tsx index 552c82f498..5d551b41a9 100644 --- a/ts/components/CallingButton.tsx +++ b/ts/components/CallingButton.tsx @@ -35,7 +35,7 @@ export type PropsType = { tooltipDirection?: TooltipPlacement; }; -export const CallingButton = ({ +export function CallingButton({ buttonType, i18n, isVisible = true, @@ -43,7 +43,7 @@ export const CallingButton = ({ onMouseEnter, onMouseLeave, tooltipDirection, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const uniqueButtonId = useMemo(() => uuid(), []); let classNameSuffix = ''; @@ -145,4 +145,4 @@ export const CallingButton = ({ ); -}; +} diff --git a/ts/components/CallingDeviceSelection.stories.tsx b/ts/components/CallingDeviceSelection.stories.tsx index bcf5422c1f..0c2935c389 100644 --- a/ts/components/CallingDeviceSelection.stories.tsx +++ b/ts/components/CallingDeviceSelection.stories.tsx @@ -41,11 +41,11 @@ export default { title: 'Components/CallingDeviceSelection', }; -export const Default = (): JSX.Element => { +export function Default(): JSX.Element { return ; -}; +} -export const SomeDevices = (): JSX.Element => { +export function SomeDevices(): JSX.Element { const availableSpeakers = [ { name: 'Default', @@ -72,9 +72,9 @@ export const SomeDevices = (): JSX.Element => { }); return ; -}; +} -export const DefaultDevices = (): JSX.Element => { +export function DefaultDevices(): JSX.Element { const availableSpeakers = [ { name: 'default (Headphones)', @@ -103,9 +103,9 @@ export const DefaultDevices = (): JSX.Element => { }); return ; -}; +} -export const AllDevices = (): JSX.Element => { +export function AllDevices(): JSX.Element { const availableSpeakers = [ { name: 'Default', @@ -179,4 +179,4 @@ export const AllDevices = (): JSX.Element => { }); return ; -}; +} diff --git a/ts/components/CallingDeviceSelection.tsx b/ts/components/CallingDeviceSelection.tsx index f79e3b9dce..9ec6da7919 100644 --- a/ts/components/CallingDeviceSelection.tsx +++ b/ts/components/CallingDeviceSelection.tsx @@ -116,7 +116,7 @@ function createCameraChangeHandler( }; } -export const CallingDeviceSelection = ({ +export function CallingDeviceSelection({ availableCameras, availableMicrophones, availableSpeakers, @@ -126,7 +126,7 @@ export const CallingDeviceSelection = ({ selectedMicrophone, selectedSpeaker, toggleSettings, -}: Props): JSX.Element => { +}: Props): JSX.Element { const selectedMicrophoneIndex = selectedMicrophone ? selectedMicrophone.index : undefined; @@ -212,4 +212,4 @@ export const CallingDeviceSelection = ({ ); -}; +} diff --git a/ts/components/CallingHeader.stories.tsx b/ts/components/CallingHeader.stories.tsx index 7dde76cb97..2146f806a7 100644 --- a/ts/components/CallingHeader.stories.tsx +++ b/ts/components/CallingHeader.stories.tsx @@ -34,61 +34,73 @@ export default { title: 'Components/CallingHeader', }; -export const Default = (): JSX.Element => ; +export function Default(): JSX.Element { + return ; +} -export const LobbyStyle = (): JSX.Element => ( - -); +export function LobbyStyle(): JSX.Element { + return ( + + ); +} LobbyStyle.story = { name: 'Lobby style', }; -export const WithParticipants = (): JSX.Element => ( - -); +export function WithParticipants(): JSX.Element { + return ( + + ); +} -export const WithParticipantsShown = (): JSX.Element => ( - -); +export function WithParticipantsShown(): JSX.Element { + return ( + + ); +} WithParticipantsShown.story = { name: 'With Participants (shown)', }; -export const LongTitle = (): JSX.Element => ( - -); +export function LongTitle(): JSX.Element { + return ( + + ); +} -export const TitleWithMessage = (): JSX.Element => ( - -); +export function TitleWithMessage(): JSX.Element { + return ( + + ); +} TitleWithMessage.story = { name: 'Title with message', diff --git a/ts/components/CallingHeader.tsx b/ts/components/CallingHeader.tsx index dd32b2a955..d7d4a6d964 100644 --- a/ts/components/CallingHeader.tsx +++ b/ts/components/CallingHeader.tsx @@ -23,7 +23,7 @@ export type PropsType = { toggleSpeakerView?: () => void; }; -export const CallingHeader = ({ +export function CallingHeader({ i18n, isInSpeakerView, isGroupCall = false, @@ -36,103 +36,110 @@ export const CallingHeader = ({ togglePip, toggleSettings, toggleSpeakerView, -}: PropsType): JSX.Element => ( -
- {title ? ( -
{title}
- ) : null} - {message ? ( -
{message}
- ) : null} -
- {isGroupCall && participantCount ? ( -
- - - -
- ) : null} -
- -
- {isGroupCall && participantCount > 2 && toggleSpeakerView && ( + + +
+ ) : null}
+ {isGroupCall && participantCount > 2 && toggleSpeakerView && ( +
+ - -
- )} - {togglePip && ( -
- -
- )} - {onCancel && ( -
- -
- )} + theme={Theme.Dark} + > +
+ )} + {togglePip && ( +
+ +
+ )} + {onCancel && ( +
+ +
+ )} + - -); + ); +} diff --git a/ts/components/CallingLobby.stories.tsx b/ts/components/CallingLobby.stories.tsx index 1714c412d1..320ba55169 100644 --- a/ts/components/CallingLobby.stories.tsx +++ b/ts/components/CallingLobby.stories.tsx @@ -94,23 +94,23 @@ export default { title: 'Components/CallingLobby', }; -export const Default = (): JSX.Element => { +export function Default(): JSX.Element { const props = createProps(); return ; -}; +} -export const NoCameraNoAvatar = (): JSX.Element => { +export function NoCameraNoAvatar(): JSX.Element { const props = createProps({ availableCameras: [], }); return ; -}; +} NoCameraNoAvatar.story = { name: 'No Camera, no avatar', }; -export const NoCameraLocalAvatar = (): JSX.Element => { +export function NoCameraLocalAvatar(): JSX.Element { const props = createProps({ availableCameras: [], me: getDefaultConversation({ @@ -121,52 +121,52 @@ export const NoCameraLocalAvatar = (): JSX.Element => { }), }); return ; -}; +} NoCameraLocalAvatar.story = { name: 'No Camera, local avatar', }; -export const LocalVideo = (): JSX.Element => { +export function LocalVideo(): JSX.Element { const props = createProps({ hasLocalVideo: true, }); return ; -}; +} -export const InitiallyMuted = (): JSX.Element => { +export function InitiallyMuted(): JSX.Element { const props = createProps({ hasLocalAudio: false, }); return ; -}; +} InitiallyMuted.story = { name: 'Initially muted', }; -export const GroupCall0PeekedParticipants = (): JSX.Element => { +export function GroupCall0PeekedParticipants(): JSX.Element { const props = createProps({ isGroupCall: true, peekedParticipants: [] }); return ; -}; +} GroupCall0PeekedParticipants.story = { name: 'Group Call - 0 peeked participants', }; -export const GroupCall1PeekedParticipant = (): JSX.Element => { +export function GroupCall1PeekedParticipant(): JSX.Element { const props = createProps({ isGroupCall: true, peekedParticipants: [{ title: 'Sam' }].map(fakePeekedParticipant), }); return ; -}; +} GroupCall1PeekedParticipant.story = { name: 'Group Call - 1 peeked participant', }; -export const GroupCall1PeekedParticipantSelf = (): JSX.Element => { +export function GroupCall1PeekedParticipantSelf(): JSX.Element { const uuid = UUID.generate().toString(); const props = createProps({ isGroupCall: true, @@ -177,13 +177,13 @@ export const GroupCall1PeekedParticipantSelf = (): JSX.Element => { peekedParticipants: [fakePeekedParticipant({ title: 'Ash', uuid })], }); return ; -}; +} GroupCall1PeekedParticipantSelf.story = { name: 'Group Call - 1 peeked participant (self)', }; -export const GroupCall4PeekedParticipants = (): JSX.Element => { +export function GroupCall4PeekedParticipants(): JSX.Element { const props = createProps({ isGroupCall: true, peekedParticipants: ['Sam', 'Cayce', 'April', 'Logan', 'Carl'].map(title => @@ -191,13 +191,13 @@ export const GroupCall4PeekedParticipants = (): JSX.Element => { ), }); return ; -}; +} GroupCall4PeekedParticipants.story = { name: 'Group Call - 4 peeked participants', }; -export const GroupCall4PeekedParticipantsParticipantsList = (): JSX.Element => { +export function GroupCall4PeekedParticipantsParticipantsList(): JSX.Element { const props = createProps({ isGroupCall: true, peekedParticipants: ['Sam', 'Cayce', 'April', 'Logan', 'Carl'].map(title => @@ -206,13 +206,13 @@ export const GroupCall4PeekedParticipantsParticipantsList = (): JSX.Element => { showParticipantsList: true, }); return ; -}; +} GroupCall4PeekedParticipantsParticipantsList.story = { name: 'Group Call - 4 peeked participants (participants list)', }; -export const GroupCallCallFull = (): JSX.Element => { +export function GroupCallCallFull(): JSX.Element { const props = createProps({ isGroupCall: true, isCallFull: true, @@ -221,19 +221,19 @@ export const GroupCallCallFull = (): JSX.Element => { ), }); return ; -}; +} GroupCallCallFull.story = { name: 'Group Call - call full', }; -export const GroupCall0PeekedParticipantsBigGroup = (): JSX.Element => { +export function GroupCall0PeekedParticipantsBigGroup(): JSX.Element { const props = createProps({ isGroupCall: true, groupMembers: times(100, () => getDefaultConversation()), }); return ; -}; +} GroupCall0PeekedParticipantsBigGroup.story = { name: 'Group Call - 0 peeked participants, big group', diff --git a/ts/components/CallingLobby.tsx b/ts/components/CallingLobby.tsx index 491ae3d0c0..2f20791740 100644 --- a/ts/components/CallingLobby.tsx +++ b/ts/components/CallingLobby.tsx @@ -63,7 +63,7 @@ export type PropsType = { toggleSettings: () => void; }; -export const CallingLobby = ({ +export function CallingLobby({ availableCameras, conversation, groupMembers, @@ -86,7 +86,7 @@ export const CallingLobby = ({ toggleParticipants, toggleSettings, outgoingRing, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [isMutedToastVisible, setIsMutedToastVisible] = React.useState( !hasLocalAudio ); @@ -303,4 +303,4 @@ export const CallingLobby = ({ ); -}; +} diff --git a/ts/components/CallingLobbyJoinButton.tsx b/ts/components/CallingLobbyJoinButton.tsx index 574f1b5294..810e67a100 100644 --- a/ts/components/CallingLobbyJoinButton.tsx +++ b/ts/components/CallingLobbyJoinButton.tsx @@ -1,7 +1,7 @@ // Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { FunctionComponent, ReactChild } from 'react'; +import type { ReactChild } from 'react'; import React, { useState } from 'react'; import { noop } from 'lodash'; @@ -19,6 +19,13 @@ export enum CallingLobbyJoinButtonVariant { Start = 'Start', } +type PropsType = { + disabled?: boolean; + i18n: LocalizerType; + onClick: () => void; + variant: CallingLobbyJoinButtonVariant; +}; + /** * This component is a little weird. Why not just render a button with some children? * @@ -29,12 +36,12 @@ export enum CallingLobbyJoinButtonVariant { * For example, we might initially render "Join call" and then render a spinner when you * click the button. The button shouldn't resize in that situation. */ -export const CallingLobbyJoinButton: FunctionComponent<{ - disabled?: boolean; - i18n: LocalizerType; - onClick: () => void; - variant: CallingLobbyJoinButtonVariant; -}> = ({ disabled, i18n, onClick, variant }) => { +export function CallingLobbyJoinButton({ + disabled, + i18n, + onClick, + variant, +}: PropsType): JSX.Element { const [width, setWidth] = useState(); const [height, setHeight] = useState(); @@ -103,4 +110,4 @@ export const CallingLobbyJoinButton: FunctionComponent<{ ); -}; +} diff --git a/ts/components/CallingParticipantsList.stories.tsx b/ts/components/CallingParticipantsList.stories.tsx index 57de5131ff..b4db4e0463 100644 --- a/ts/components/CallingParticipantsList.stories.tsx +++ b/ts/components/CallingParticipantsList.stories.tsx @@ -47,16 +47,16 @@ export default { title: 'Components/CallingParticipantsList', }; -export const NoOne = (): JSX.Element => { +export function NoOne(): JSX.Element { const props = createProps(); return ; -}; +} NoOne.story = { name: 'No one', }; -export const SoloCall = (): JSX.Element => { +export function SoloCall(): JSX.Element { const props = createProps({ participants: [ createParticipant({ @@ -65,9 +65,9 @@ export const SoloCall = (): JSX.Element => { ], }); return ; -}; +} -export const ManyParticipants = (): JSX.Element => { +export function ManyParticipants(): JSX.Element { const props = createProps({ participants: [ createParticipant({ @@ -95,13 +95,13 @@ export const ManyParticipants = (): JSX.Element => { ], }); return ; -}; +} -export const Overflow = (): JSX.Element => { +export function Overflow(): JSX.Element { const props = createProps({ participants: Array(50) .fill(null) .map(() => createParticipant({ title: 'Kirby' })), }); return ; -}; +} diff --git a/ts/components/CallingParticipantsList.tsx b/ts/components/CallingParticipantsList.tsx index 1156e1f2d3..dbe0bb499e 100644 --- a/ts/components/CallingParticipantsList.tsx +++ b/ts/components/CallingParticipantsList.tsx @@ -30,7 +30,12 @@ export type PropsType = { }; export const CallingParticipantsList = React.memo( - ({ i18n, onClose, ourUuid, participants }: PropsType) => { + function CallingParticipantsListInner({ + i18n, + onClose, + ourUuid, + participants, + }: PropsType) { const [root, setRoot] = React.useState(null); const modalContainer = useContext(ModalContainerContext) ?? document.body; diff --git a/ts/components/CallingPip.stories.tsx b/ts/components/CallingPip.stories.tsx index 00b20f7246..aefd11b2a6 100644 --- a/ts/components/CallingPip.stories.tsx +++ b/ts/components/CallingPip.stories.tsx @@ -10,7 +10,7 @@ import { AvatarColors } from '../types/Colors'; import type { ConversationType } from '../state/ducks/conversations'; import type { PropsType } from './CallingPip'; import { CallingPip } from './CallingPip'; -import type { ActiveCallType } from '../types/Calling'; +import type { ActiveDirectCallType } from '../types/Calling'; import { CallMode, CallViewMode, @@ -52,7 +52,7 @@ const getCommonActiveCallData = () => ({ showParticipantsList: false, }); -const defaultCall: ActiveCallType = { +const defaultCall: ActiveDirectCallType = { ...getCommonActiveCallData(), callMode: CallMode.Direct as CallMode.Direct, callState: CallState.Accepted, @@ -80,12 +80,12 @@ export default { title: 'Components/CallingPip', }; -export const Default = (): JSX.Element => { +export function Default(): JSX.Element { const props = createProps({}); return ; -}; +} -export const ContactWithAvatarAndNoVideo = (): JSX.Element => { +export function ContactWithAvatarAndNoVideo(): JSX.Element { const props = createProps({ activeCall: { ...defaultCall, @@ -99,13 +99,13 @@ export const ContactWithAvatarAndNoVideo = (): JSX.Element => { }, }); return ; -}; +} ContactWithAvatarAndNoVideo.story = { name: 'Contact (with avatar and no video)', }; -export const ContactNoColor = (): JSX.Element => { +export function ContactNoColor(): JSX.Element { const props = createProps({ activeCall: { ...defaultCall, @@ -116,13 +116,13 @@ export const ContactNoColor = (): JSX.Element => { }, }); return ; -}; +} ContactNoColor.story = { name: 'Contact (no color)', }; -export const GroupCall = (): JSX.Element => { +export function GroupCall(): JSX.Element { const props = createProps({ activeCall: { ...getCommonActiveCallData(), @@ -140,4 +140,4 @@ export const GroupCall = (): JSX.Element => { }, }); return ; -}; +} diff --git a/ts/components/CallingPip.tsx b/ts/components/CallingPip.tsx index 2d934a0bab..0385bd2551 100644 --- a/ts/components/CallingPip.tsx +++ b/ts/components/CallingPip.tsx @@ -70,7 +70,7 @@ const PIP_WIDTH = 120; const PIP_TOP_MARGIN = 56; const PIP_PADDING = 8; -export const CallingPip = ({ +export function CallingPip({ activeCall, getGroupCallVideoFrameSource, hangUpActiveCall, @@ -82,7 +82,7 @@ export const CallingPip = ({ switchToPresentationView, switchFromPresentationView, togglePip, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const videoContainerRef = React.useRef(null); const localVideoRef = React.useRef(null); @@ -315,4 +315,4 @@ export const CallingPip = ({ ); -}; +} diff --git a/ts/components/CallingPipRemoteVideo.tsx b/ts/components/CallingPipRemoteVideo.tsx index b377b86a86..588906d858 100644 --- a/ts/components/CallingPipRemoteVideo.tsx +++ b/ts/components/CallingPipRemoteVideo.tsx @@ -27,13 +27,13 @@ import { nonRenderedRemoteParticipant } from '../util/ringrtc/nonRenderedRemoteP // less than `MAX_FRAME_HEIGHT`. const PIP_VIDEO_HEIGHT_PX = 120; -const NoVideo = ({ +function NoVideo({ activeCall, i18n, }: { activeCall: ActiveCallType; i18n: LocalizerType; -}): JSX.Element => { +}): JSX.Element { const { acceptedMessageRequest, avatarPath, @@ -68,7 +68,7 @@ const NoVideo = ({ ); -}; +} export type PropsType = { activeCall: ActiveCallType; @@ -81,13 +81,13 @@ export type PropsType = { setRendererCanvas: (_: SetRendererCanvasType) => void; }; -export const CallingPipRemoteVideo = ({ +export function CallingPipRemoteVideo({ activeCall, getGroupCallVideoFrameSource, i18n, setGroupCallVideoRequest, setRendererCanvas, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const { conversation } = activeCall; const getGroupCallFrameBuffer = useGetCallingFrameBuffer(); @@ -177,4 +177,4 @@ export const CallingPipRemoteVideo = ({ default: throw missingCaseError(activeCall); } -}; +} diff --git a/ts/components/CallingPreCallInfo.stories.tsx b/ts/components/CallingPreCallInfo.stories.tsx index 8d1bcc5221..4297403e6b 100644 --- a/ts/components/CallingPreCallInfo.stories.tsx +++ b/ts/components/CallingPreCallInfo.stories.tsx @@ -24,230 +24,260 @@ export default { title: 'Components/CallingPreCallInfo', }; -export const DirectConversation = (): JSX.Element => ( - -); +export function DirectConversation(): JSX.Element { + return ( + + ); +} DirectConversation.story = { name: 'Direct conversation', }; -export const Ring0 = (): JSX.Element => ( - -); +export function Ring0(): JSX.Element { + return ( + + ); +} Ring0.story = { name: 'Group call: Will ring 0 people', }; -export const Ring1 = (): JSX.Element => ( - -); +export function Ring1(): JSX.Element { + return ( + + ); +} Ring1.story = { name: 'Group call: Will ring 1 person', }; -export const Ring2 = (): JSX.Element => ( - -); +export function Ring2(): JSX.Element { + return ( + + ); +} Ring2.story = { name: 'Group call: Will ring 2 people', }; -export const Ring3 = (): JSX.Element => ( - -); +export function Ring3(): JSX.Element { + return ( + + ); +} Ring3.story = { name: 'Group call: Will ring 3 people', }; -export const Ring4 = (): JSX.Element => ( - -); +export function Ring4(): JSX.Element { + return ( + + ); +} Ring3.story = { name: 'Group call: Will ring 4 people', }; -export const Notify0 = (): JSX.Element => ( - -); +export function Notify0(): JSX.Element { + return ( + + ); +} Notify0.story = { name: 'Group call: Will notify 0 people', }; -export const Notify1 = (): JSX.Element => ( - -); +export function Notify1(): JSX.Element { + return ( + + ); +} Notify1.story = { name: 'Group call: Will notify 1 person', }; -export const Notify2 = (): JSX.Element => ( - -); +export function Notify2(): JSX.Element { + return ( + + ); +} Notify2.story = { name: 'Group call: Will notify 2 people', }; -export const Notify3 = (): JSX.Element => ( - -); +export function Notify3(): JSX.Element { + return ( + + ); +} Notify3.story = { name: 'Group call: Will notify 3 people', }; -export const Notify4 = (): JSX.Element => ( - -); +export function Notify4(): JSX.Element { + return ( + + ); +} Notify4.story = { name: 'Group call: Will notify 4 people', }; -export const Peek1 = (): JSX.Element => ( - -); +export function Peek1(): JSX.Element { + return ( + + ); +} Peek1.story = { name: 'Group call: 1 participant peeked', }; -export const Peek2 = (): JSX.Element => ( - -); +export function Peek2(): JSX.Element { + return ( + + ); +} Peek2.story = { name: 'Group call: 2 participants peeked', }; -export const Peek3 = (): JSX.Element => ( - -); +export function Peek3(): JSX.Element { + return ( + + ); +} Peek3.story = { name: 'Group call: 3 participants peeked', }; -export const Peek4 = (): JSX.Element => ( - -); +export function Peek4(): JSX.Element { + return ( + + ); +} Peek4.story = { name: 'Group call: 4 participants peeked', }; -export const GroupConversationYouOnAnOtherDevice = (): JSX.Element => { +export function GroupConversationYouOnAnOtherDevice(): JSX.Element { const me = getDefaultConversation(); return ( { ringMode={RingMode.WillRing} /> ); -}; +} GroupConversationYouOnAnOtherDevice.story = { name: 'Group conversation, you on an other device', }; -export const GroupConversationCallIsFull = (): JSX.Element => ( - -); +export function GroupConversationCallIsFull(): JSX.Element { + return ( + + ); +} GroupConversationCallIsFull.story = { name: 'Group conversation, call is full', diff --git a/ts/components/CallingPreCallInfo.tsx b/ts/components/CallingPreCallInfo.tsx index 8bcf28fbb2..d70530f369 100644 --- a/ts/components/CallingPreCallInfo.tsx +++ b/ts/components/CallingPreCallInfo.tsx @@ -1,7 +1,6 @@ // Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { FunctionComponent } from 'react'; import React from 'react'; import type { ConversationType } from '../state/ducks/conversations'; import type { LocalizerType } from '../types/Util'; @@ -42,7 +41,7 @@ type PropsType = { >; }; -export const CallingPreCallInfo: FunctionComponent = ({ +export function CallingPreCallInfo({ conversation, groupMembers = [], i18n, @@ -50,7 +49,7 @@ export const CallingPreCallInfo: FunctionComponent = ({ me, peekedParticipants = [], ringMode, -}) => { +}: PropsType): JSX.Element { let subtitle: string; if (ringMode === RingMode.IsRinging) { subtitle = i18n('outgoingCallRinging'); @@ -183,4 +182,4 @@ export const CallingPreCallInfo: FunctionComponent = ({
{subtitle}
); -}; +} diff --git a/ts/components/CallingScreenSharingController.stories.tsx b/ts/components/CallingScreenSharingController.stories.tsx index 54832efacd..76211b4887 100644 --- a/ts/components/CallingScreenSharingController.stories.tsx +++ b/ts/components/CallingScreenSharingController.stories.tsx @@ -23,11 +23,11 @@ export default { title: 'Components/CallingScreenSharingController', }; -export const Controller = (): JSX.Element => { +export function Controller(): JSX.Element { return ; -}; +} -export const ReallyLongAppName = (): JSX.Element => { +export function ReallyLongAppName(): JSX.Element { return ( { })} /> ); -}; +} ReallyLongAppName.story = { name: 'Really long app name', diff --git a/ts/components/CallingScreenSharingController.tsx b/ts/components/CallingScreenSharingController.tsx index ac1cce2599..5b6f752e33 100644 --- a/ts/components/CallingScreenSharingController.tsx +++ b/ts/components/CallingScreenSharingController.tsx @@ -12,12 +12,12 @@ export type PropsType = { presentedSourceName: string; }; -export const CallingScreenSharingController = ({ +export function CallingScreenSharingController({ i18n, onCloseController, onStopSharing, presentedSourceName, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { return (
@@ -40,4 +40,4 @@ export const CallingScreenSharingController = ({
); -}; +} diff --git a/ts/components/CallingSelectPresentingSourcesModal.stories.tsx b/ts/components/CallingSelectPresentingSourcesModal.stories.tsx index 496a4f3a0e..e48a88539a 100644 --- a/ts/components/CallingSelectPresentingSourcesModal.stories.tsx +++ b/ts/components/CallingSelectPresentingSourcesModal.stories.tsx @@ -57,6 +57,6 @@ export default { title: 'Components/CallingSelectPresentingSourcesModal', }; -export const Modal = (): JSX.Element => { +export function Modal(): JSX.Element { return ; -}; +} diff --git a/ts/components/CallingSelectPresentingSourcesModal.tsx b/ts/components/CallingSelectPresentingSourcesModal.tsx index d4389983f0..acc2b7a9ab 100644 --- a/ts/components/CallingSelectPresentingSourcesModal.tsx +++ b/ts/components/CallingSelectPresentingSourcesModal.tsx @@ -16,7 +16,7 @@ export type PropsType = { setPresenting: (_?: PresentedSource) => void; }; -const Source = ({ +function Source({ onSourceClick, source, sourceToPresent, @@ -24,7 +24,7 @@ const Source = ({ onSourceClick: (source: PresentedSource) => void; source: PresentableSource; sourceToPresent?: PresentedSource; -}): JSX.Element => { +}): JSX.Element { return ( ); -}; +} -export const CallingSelectPresentingSourcesModal = ({ +export function CallingSelectPresentingSourcesModal({ i18n, presentingSourcesAvailable, setPresenting, -}: PropsType): JSX.Element | null => { +}: PropsType): JSX.Element | null { const [sourceToPresent, setSourceToPresent] = useState< PresentedSource | undefined >(undefined); @@ -137,4 +137,4 @@ export const CallingSelectPresentingSourcesModal = ({ ); -}; +} diff --git a/ts/components/CallingToast.tsx b/ts/components/CallingToast.tsx index fe82b193c5..64ad1bc6f5 100644 --- a/ts/components/CallingToast.tsx +++ b/ts/components/CallingToast.tsx @@ -1,27 +1,32 @@ // Copyright 2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { FunctionComponent } from 'react'; import React from 'react'; import classNames from 'classnames'; type PropsType = { isVisible: boolean; onClick: () => unknown; + children?: JSX.Element | string; }; export const DEFAULT_LIFETIME = 5000; -export const CallingToast: FunctionComponent = ({ +export function CallingToast({ isVisible, onClick, children, -}) => ( - -); +}: PropsType): JSX.Element { + return ( + + ); +} diff --git a/ts/components/CallingToastManager.tsx b/ts/components/CallingToastManager.tsx index 815fada48d..82e060ce98 100644 --- a/ts/components/CallingToastManager.tsx +++ b/ts/components/CallingToastManager.tsx @@ -104,7 +104,7 @@ function useScreenSharingToast({ activeCall, i18n }: PropsType): ToastType { // In the future, this component should show toasts when users join or leave. See // DESKTOP-902. -export const CallingToastManager: React.FC = props => { +export function CallingToastManager(props: PropsType): JSX.Element { const reconnectingToast = getReconnectingToast(props); const screenSharingToast = useScreenSharingToast(props); @@ -144,4 +144,4 @@ export const CallingToastManager: React.FC = props => { {toastMessage} ); -}; +} diff --git a/ts/components/ChatColorPicker.stories.tsx b/ts/components/ChatColorPicker.stories.tsx index a8f3e57510..597caa4e74 100644 --- a/ts/components/ChatColorPicker.stories.tsx +++ b/ts/components/ChatColorPicker.stories.tsx @@ -41,9 +41,9 @@ const createProps = (): PropsType => ({ ), }); -export const Default = (): JSX.Element => ( - -); +export function Default(): JSX.Element { + return ; +} const CUSTOM_COLORS = { abc: { @@ -62,14 +62,16 @@ const CUSTOM_COLORS = { }, }; -export const CustomColors = (): JSX.Element => ( - -); +export function CustomColors(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/ChatColorPicker.tsx b/ts/components/ChatColorPicker.tsx index 635e8b701b..dbd092270b 100644 --- a/ts/components/ChatColorPicker.tsx +++ b/ts/components/ChatColorPicker.tsx @@ -61,7 +61,7 @@ type PropsActionType = { export type PropsType = PropsDataType & PropsActionType; -export const ChatColorPicker = ({ +export function ChatColorPicker({ addCustomColor, colorSelected, conversationId, @@ -77,7 +77,7 @@ export const ChatColorPicker = ({ selectedColor = ConversationColors[0], selectedCustomColor, setGlobalDefaultConversationColor, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [confirmResetAll, setConfirmResetAll] = useState(false); const [confirmResetWhat, setConfirmResetWhat] = useState(false); const [customColorToEdit, setCustomColorToEdit] = useState< @@ -264,7 +264,7 @@ export const ChatColorPicker = ({ /> ); -}; +} type CustomColorBubblePropsType = { color: CustomColorType; @@ -280,7 +280,7 @@ type CustomColorBubblePropsType = { onChoose: () => unknown; }; -const CustomColorBubble = ({ +function CustomColorBubble({ color, colorId, getConversationsWithCustomColor, @@ -290,7 +290,7 @@ const CustomColorBubble = ({ onDupe, onEdit, onChoose, -}: CustomColorBubblePropsType): JSX.Element => { +}: CustomColorBubblePropsType): JSX.Element { // eslint-disable-next-line @typescript-eslint/no-explicit-any const menuRef = useRef(null); const [confirmDeleteCount, setConfirmDeleteCount] = useState< @@ -410,7 +410,7 @@ const CustomColorBubble = ({ ); -}; +} type CustomColorEditorWrapperPropsType = { customColorToEdit?: CustomColorDataType; @@ -419,12 +419,12 @@ type CustomColorEditorWrapperPropsType = { onSave: (color: CustomColorType) => unknown; }; -const CustomColorEditorWrapper = ({ +function CustomColorEditorWrapper({ customColorToEdit, i18n, onClose, onSave, -}: CustomColorEditorWrapperPropsType): JSX.Element => { +}: CustomColorEditorWrapperPropsType): JSX.Element { const editor = ( ); -}; +} diff --git a/ts/components/Checkbox.stories.tsx b/ts/components/Checkbox.stories.tsx index f7408e4403..4f0034efec 100644 --- a/ts/components/Checkbox.stories.tsx +++ b/ts/components/Checkbox.stories.tsx @@ -18,15 +18,17 @@ export default { title: 'Components/Checkbox', }; -export const Normal = (): JSX.Element => ; -export const Checked = (): JSX.Element => ( - -); +export function Normal(): JSX.Element { + return ; +} +export function Checked(): JSX.Element { + return ; +} -export const Description = (): JSX.Element => ( - -); +export function Description(): JSX.Element { + return ; +} -export const Disabled = (): JSX.Element => ( - -); +export function Disabled(): JSX.Element { + return ; +} diff --git a/ts/components/Checkbox.tsx b/ts/components/Checkbox.tsx index ccfa26fc1f..0da4c770a8 100644 --- a/ts/components/Checkbox.tsx +++ b/ts/components/Checkbox.tsx @@ -24,7 +24,7 @@ export type PropsType = { onClick?: () => unknown; }; -export const Checkbox = ({ +export function Checkbox({ checked, children, description, @@ -35,7 +35,7 @@ export const Checkbox = ({ name, onChange, onClick, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const getClassName = getClassNamesFor('Checkbox', moduleClassName); const id = useMemo(() => `${name}::${uuid()}`, [name]); @@ -76,4 +76,4 @@ export const Checkbox = ({ ); -}; +} diff --git a/ts/components/CompositionArea.stories.tsx b/ts/components/CompositionArea.stories.tsx index 943fab19ef..d153db9ed5 100644 --- a/ts/components/CompositionArea.stories.tsx +++ b/ts/components/CompositionArea.stories.tsx @@ -120,63 +120,63 @@ const useProps = (overrideProps: Partial = {}): Props => ({ isFetchingUUID: overrideProps.isFetchingUUID || false, }); -export const Default = (): JSX.Element => { +export function Default(): JSX.Element { const props = useProps(); return ; -}; +} -export const StartingText = (): JSX.Element => { +export function StartingText(): JSX.Element { const props = useProps({ draftText: "here's some starting text", }); return ; -}; +} -export const StickerButton = (): JSX.Element => { +export function StickerButton(): JSX.Element { const props = useProps({ // eslint-disable-next-line @typescript-eslint/no-explicit-any knownPacks: [{} as any], }); return ; -}; +} -export const MessageRequest = (): JSX.Element => { +export function MessageRequest(): JSX.Element { const props = useProps({ messageRequestsEnabled: true, }); return ; -}; +} -export const SmsOnlyFetchingUuid = (): JSX.Element => { +export function SmsOnlyFetchingUuid(): JSX.Element { const props = useProps({ isSMSOnly: true, isFetchingUUID: true, }); return ; -}; +} SmsOnlyFetchingUuid.story = { name: 'SMS-only fetching UUID', }; -export const SmsOnly = (): JSX.Element => { +export function SmsOnly(): JSX.Element { const props = useProps({ isSMSOnly: true, }); return ; -}; +} SmsOnly.story = { name: 'SMS-only', }; -export const Attachments = (): JSX.Element => { +export function Attachments(): JSX.Element { const props = useProps({ draftAttachments: [ fakeDraftAttachment({ @@ -187,33 +187,37 @@ export const Attachments = (): JSX.Element => { }); return ; -}; +} -export const AnnouncementsOnlyGroup = (): JSX.Element => ( - -); +export function AnnouncementsOnlyGroup(): JSX.Element { + return ( + + ); +} AnnouncementsOnlyGroup.story = { name: 'Announcements Only group', }; -export const Quote = (): JSX.Element => ( - -); +export function Quote(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/CompositionArea.tsx b/ts/components/CompositionArea.tsx index 4b11a8bafb..4af92417b8 100644 --- a/ts/components/CompositionArea.tsx +++ b/ts/components/CompositionArea.tsx @@ -168,7 +168,7 @@ export type Props = Pick< Pick & OwnProps; -export const CompositionArea = ({ +export function CompositionArea({ // Base props addAttachment, addPendingAttachment, @@ -258,7 +258,7 @@ export const CompositionArea = ({ // SMS-only contacts isSMSOnly, isFetchingUUID, -}: Props): JSX.Element => { +}: Props): JSX.Element { const [disabled, setDisabled] = useState(false); const [dirty, setDirty] = useState(false); const [large, setLarge] = useState(false); @@ -744,4 +744,4 @@ export const CompositionArea = ({ /> ); -}; +} diff --git a/ts/components/CompositionInput.stories.tsx b/ts/components/CompositionInput.stories.tsx index fcfe65f2b7..ff3c96779a 100644 --- a/ts/components/CompositionInput.stories.tsx +++ b/ts/components/CompositionInput.stories.tsx @@ -49,37 +49,37 @@ const useProps = (overrideProps: Partial = {}): Props => ({ theme: React.useContext(StorybookThemeContext), }); -export const Default = (): JSX.Element => { +export function Default(): JSX.Element { const props = useProps(); return ; -}; +} -export const Large = (): JSX.Element => { +export function Large(): JSX.Element { const props = useProps({ large: true, }); return ; -}; +} -export const Disabled = (): JSX.Element => { +export function Disabled(): JSX.Element { const props = useProps({ disabled: true, }); return ; -}; +} -export const StartingText = (): JSX.Element => { +export function StartingText(): JSX.Element { const props = useProps({ draftText: "here's some starting text", }); return ; -}; +} -export const MultilineText = (): JSX.Element => { +export function MultilineText(): JSX.Element { const props = useProps({ draftText: `here's some starting text and more on another line @@ -93,9 +93,9 @@ and we're done`, }); return ; -}; +} -export const Emojis = (): JSX.Element => { +export function Emojis(): JSX.Element { const props = useProps({ draftText: `⁣😐😐😐😐😐😐😐 😐😐😐😐😐😐😐 @@ -105,9 +105,9 @@ export const Emojis = (): JSX.Element => { }); return ; -}; +} -export const Mentions = (): JSX.Element => { +export function Mentions(): JSX.Element { const props = useProps({ sortedGroupMembers: [ getDefaultConversation({ @@ -129,4 +129,4 @@ export const Mentions = (): JSX.Element => { }); return ; -}; +} diff --git a/ts/components/CompositionTextArea.tsx b/ts/components/CompositionTextArea.tsx index a5f509d65e..bd8c5936fe 100644 --- a/ts/components/CompositionTextArea.tsx +++ b/ts/components/CompositionTextArea.tsx @@ -46,7 +46,7 @@ export type CompositionTextAreaProps = { * Meant for modals that need to collect a message or caption. It is * basically a rectangle input with an emoji selector floating at the top-right */ -export const CompositionTextArea = ({ +export function CompositionTextArea({ i18n, placeholder, maxLength, @@ -63,7 +63,7 @@ export const CompositionTextArea = ({ theme, recentEmojis, skinTone, -}: CompositionTextAreaProps): JSX.Element => { +}: CompositionTextAreaProps): JSX.Element { const inputApiRef = React.useRef(); const [characterCount, setCharacterCount] = React.useState( grapheme.count(draftText) @@ -158,4 +158,4 @@ export const CompositionTextArea = ({ )} ); -}; +} diff --git a/ts/components/CompositionUpload.tsx b/ts/components/CompositionUpload.tsx index a127b79415..59ec141547 100644 --- a/ts/components/CompositionUpload.tsx +++ b/ts/components/CompositionUpload.tsx @@ -41,7 +41,7 @@ export type PropsType = { }; export const CompositionUpload = forwardRef( - ( + function CompositionUploadInner( { addAttachment, addPendingAttachment, @@ -52,7 +52,7 @@ export const CompositionUpload = forwardRef( removeAttachment, }, ref - ) => { + ) { const [toastType, setToastType] = useState< AttachmentToastType | undefined >(); diff --git a/ts/components/ConfirmDiscardDialog.stories.tsx b/ts/components/ConfirmDiscardDialog.stories.tsx index e79253de6d..9f3bb14976 100644 --- a/ts/components/ConfirmDiscardDialog.stories.tsx +++ b/ts/components/ConfirmDiscardDialog.stories.tsx @@ -22,6 +22,6 @@ export default { title: 'Components/ConfirmDiscardDialog', }; -export const Default = (): JSX.Element => ( - -); +export function Default(): JSX.Element { + return ; +} diff --git a/ts/components/ConfirmDiscardDialog.tsx b/ts/components/ConfirmDiscardDialog.tsx index c99f6e820e..6b1f486b2f 100644 --- a/ts/components/ConfirmDiscardDialog.tsx +++ b/ts/components/ConfirmDiscardDialog.tsx @@ -11,11 +11,11 @@ export type PropsType = { onDiscard: () => unknown; }; -export const ConfirmDiscardDialog = ({ +export function ConfirmDiscardDialog({ i18n, onClose, onDiscard, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { return ( ); -}; +} diff --git a/ts/components/ConfirmationDialog.stories.tsx b/ts/components/ConfirmationDialog.stories.tsx index 902fa93455..7a3aec6b5a 100644 --- a/ts/components/ConfirmationDialog.stories.tsx +++ b/ts/components/ConfirmationDialog.stories.tsx @@ -43,7 +43,7 @@ _ConfirmationDialog.story = { name: 'ConfirmationDialog', }; -export const CustomCancelText = (): JSX.Element => { +export function CustomCancelText(): JSX.Element { return ( { Because. ); -}; +} CustomCancelText.story = { name: 'Custom cancel text', }; -export const NoDefaultCancel = (): JSX.Element => { +export function NoDefaultCancel(): JSX.Element { return ( { No default cancel! ); -}; +} diff --git a/ts/components/ConfirmationDialog.tsx b/ts/components/ConfirmationDialog.tsx index 484a21ffd6..b75786c382 100644 --- a/ts/components/ConfirmationDialog.tsx +++ b/ts/components/ConfirmationDialog.tsx @@ -57,103 +57,101 @@ function getButtonVariant( return ButtonVariant.Secondary; } -export const ConfirmationDialog = React.memo( - ({ - actions = [], - dialogName, - cancelButtonVariant, - cancelText, - children, - hasXButton, - i18n, - moduleClassName, - noMouseClose, - noDefaultCancelButton, - onCancel, - onClose, - onTopOfEverything, - theme, - title, - }: Props) => { - const { close, overlayStyles, modalStyles } = useAnimated(onClose, { - getFrom: () => ({ opacity: 0, transform: 'scale(0.25)' }), - getTo: isOpen => ({ opacity: isOpen ? 1 : 0, transform: 'scale(1)' }), - }); +export const ConfirmationDialog = React.memo(function ConfirmationDialogInner({ + actions = [], + dialogName, + cancelButtonVariant, + cancelText, + children, + hasXButton, + i18n, + moduleClassName, + noMouseClose, + noDefaultCancelButton, + onCancel, + onClose, + onTopOfEverything, + theme, + title, +}: Props) { + const { close, overlayStyles, modalStyles } = useAnimated(onClose, { + getFrom: () => ({ opacity: 0, transform: 'scale(0.25)' }), + getTo: isOpen => ({ opacity: isOpen ? 1 : 0, transform: 'scale(1)' }), + }); - const cancelAndClose = useCallback(() => { - if (onCancel) { - onCancel(); + const cancelAndClose = useCallback(() => { + if (onCancel) { + onCancel(); + } + close(); + }, [close, onCancel]); + + const handleCancel = useCallback( + (e: MouseEvent) => { + if (e.target === e.currentTarget) { + cancelAndClose(); } - close(); - }, [close, onCancel]); + }, + [cancelAndClose] + ); - const handleCancel = useCallback( - (e: MouseEvent) => { - if (e.target === e.currentTarget) { - cancelAndClose(); - } - }, - [cancelAndClose] - ); + const hasActions = Boolean(actions.length); - const hasActions = Boolean(actions.length); + const footer = ( + <> + {!noDefaultCancelButton ? ( + + ) : null} + {actions.map((action, i) => ( + + ))} + + ); - const footer = ( - <> - {!noDefaultCancelButton ? ( - - ) : null} - {actions.map((action, i) => ( - - ))} - - ); + const modalName = `ConfirmationDialog.${dialogName}`; - const modalName = `ConfirmationDialog.${dialogName}`; - - return ( - - - - {children} - - - - ); - } -); + return ( + + + + {children} + + + + ); +}); diff --git a/ts/components/ContactPill.tsx b/ts/components/ContactPill.tsx index 6a0449cf90..acd8fa0435 100644 --- a/ts/components/ContactPill.tsx +++ b/ts/components/ContactPill.tsx @@ -1,7 +1,6 @@ // Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { FunctionComponent } from 'react'; import React from 'react'; import type { ConversationType } from '../state/ducks/conversations'; @@ -28,7 +27,7 @@ export type PropsType = { | 'unblurredAvatarPath' >; -export const ContactPill: FunctionComponent = ({ +export function ContactPill({ acceptedMessageRequest, avatarPath, color, @@ -42,7 +41,7 @@ export const ContactPill: FunctionComponent = ({ title, unblurredAvatarPath, onClickRemove, -}) => { +}: PropsType): JSX.Element { const removeLabel = i18n('ContactPill--remove'); return ( @@ -80,4 +79,4 @@ export const ContactPill: FunctionComponent = ({ /> ); -}; +} diff --git a/ts/components/ContactPills.stories.tsx b/ts/components/ContactPills.stories.tsx index 3d5da94754..4f19f2bd7f 100644 --- a/ts/components/ContactPills.stories.tsx +++ b/ts/components/ContactPills.stories.tsx @@ -50,60 +50,70 @@ const contactPillProps = ( onClickRemove: action('onClickRemove'), }); -export const EmptyList = (): JSX.Element => ; +export function EmptyList(): JSX.Element { + return ; +} EmptyList.story = { name: 'Empty list', }; -export const OneContact = (): JSX.Element => ( - - - -); +export function OneContact(): JSX.Element { + return ( + + + + ); +} OneContact.story = { name: 'One contact', }; -export const ThreeContacts = (): JSX.Element => ( - - - - - -); +export function ThreeContacts(): JSX.Element { + return ( + + + + + + ); +} ThreeContacts.story = { name: 'Three contacts', }; -export const FourContactsOneWithALongName = (): JSX.Element => ( - - - - - - -); +export function FourContactsOneWithALongName(): JSX.Element { + return ( + + + + + + + ); +} FourContactsOneWithALongName.story = { name: 'Four contacts, one with a long name', }; -export const FiftyContacts = (): JSX.Element => ( - - {contacts.map(contact => ( - - ))} - -); +export function FiftyContacts(): JSX.Element { + return ( + + {contacts.map(contact => ( + + ))} + + ); +} FiftyContacts.story = { name: 'Fifty contacts', diff --git a/ts/components/ContactPills.tsx b/ts/components/ContactPills.tsx index 6d0da62b98..63d243d306 100644 --- a/ts/components/ContactPills.tsx +++ b/ts/components/ContactPills.tsx @@ -1,7 +1,7 @@ // Copyright 2021-2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { FunctionComponent, ReactNode } from 'react'; +import type { ReactNode } from 'react'; import React, { useRef, useEffect, Children } from 'react'; import classNames from 'classnames'; @@ -13,10 +13,10 @@ type PropsType = { children?: ReactNode; }; -export const ContactPills: FunctionComponent = ({ +export function ContactPills({ moduleClassName, children, -}) => { +}: PropsType): JSX.Element { const elRef = useRef(null); const childCount = Children.count(children); @@ -38,4 +38,4 @@ export const ContactPills: FunctionComponent = ({ {children} ); -}; +} diff --git a/ts/components/ContextMenu.stories.tsx b/ts/components/ContextMenu.stories.tsx index 506386632b..99f9db985d 100644 --- a/ts/components/ContextMenu.stories.tsx +++ b/ts/components/ContextMenu.stories.tsx @@ -33,6 +33,6 @@ const getDefaultProps = (): PropsType => ({ ], }); -export const Default = (): JSX.Element => { +export function Default(): JSX.Element { return Menu; -}; +} diff --git a/ts/components/ConversationList.stories.tsx b/ts/components/ConversationList.stories.tsx index d82c3d96d6..130a622c7c 100644 --- a/ts/components/ConversationList.stories.tsx +++ b/ts/components/ConversationList.stories.tsx @@ -50,10 +50,10 @@ const defaultConversations: Array = [ getDefaultConversation(), ]; -const Wrapper = ({ +function Wrapper({ rows, scrollable, -}: Readonly<{ rows: ReadonlyArray; scrollable?: boolean }>) => { +}: Readonly<{ rows: ReadonlyArray; scrollable?: boolean }>) { const theme = useContext(StorybookThemeContext); return ( @@ -95,7 +95,7 @@ const Wrapper = ({ theme={theme} /> ); -}; +} export const _ArchiveButton = (): JSX.Element => ( ( - -); + ]} + /> + ); +} ContactNoteToSelf.story = { name: 'Contact: note to self', }; -export const ContactDirect = (): JSX.Element => ( - -); +export function ContactDirect(): JSX.Element { + return ( + + ); +} ContactDirect.story = { name: 'Contact: direct', }; -export const ContactDirectWithShortAbout = (): JSX.Element => ( - -); +export function ContactDirectWithShortAbout(): JSX.Element { + return ( + + ); +} ContactDirectWithShortAbout.story = { name: 'Contact: direct with short about', }; -export const ContactDirectWithLongAbout = (): JSX.Element => ( - -); + ]} + /> + ); +} ContactDirectWithLongAbout.story = { name: 'Contact: direct with long about', }; -export const ContactGroup = (): JSX.Element => ( - -); +export function ContactGroup(): JSX.Element { + return ( + + ); +} ContactGroup.story = { name: 'Contact: group', }; -export const ContactCheckboxes = (): JSX.Element => ( - -); + { + type: RowType.ContactCheckbox, + contact: defaultConversations[1], + isChecked: false, + }, + { + type: RowType.ContactCheckbox, + contact: { + ...defaultConversations[2], + about: '😃 Hola', + }, + isChecked: true, + }, + ]} + /> + ); +} ContactCheckboxes.story = { name: 'Contact checkboxes', }; -export const ContactCheckboxesDisabled = (): JSX.Element => ( - -); +export function ContactCheckboxesDisabled(): JSX.Element { + return ( + + ); +} ContactCheckboxesDisabled.story = { name: 'Contact checkboxes: disabled', @@ -322,16 +336,18 @@ ConversationWithYourself.story = { name: 'Conversation: with yourself', }; -export const ConversationsMessageStatuses = (): JSX.Element => ( - ({ - type: RowType.Conversation, - conversation: createConversation({ - lastMessage: { text: status, status, deletedForEveryone: false }, - }), - }))} - /> -); +export function ConversationsMessageStatuses(): JSX.Element { + return ( + ({ + type: RowType.Conversation, + conversation: createConversation({ + lastMessage: { text: status, status, deletedForEveryone: false }, + }), + }))} + /> + ); +} ConversationsMessageStatuses.story = { name: 'Conversations: Message Statuses', @@ -379,21 +395,23 @@ ConversationMessageRequest.story = { name: 'Conversation: Message Request', }; -export const ConversationsUnreadCount = (): JSX.Element => ( - ({ - type: RowType.Conversation, - conversation: createConversation({ - lastMessage: { - text: 'Hey there!', - status: 'delivered', - deletedForEveryone: false, - }, - unreadCount, - }), - }))} - /> -); +export function ConversationsUnreadCount(): JSX.Element { + return ( + ({ + type: RowType.Conversation, + conversation: createConversation({ + lastMessage: { + text: 'Hey there!', + status: 'delivered', + deletedForEveryone: false, + }, + unreadCount, + }), + }))} + /> + ); +} ConversationsUnreadCount.story = { name: 'Conversations: unread count', @@ -459,7 +477,7 @@ ConversationLongName.story = { name: 'Conversation: long name', }; -export const ConversationLongMessage = (): JSX.Element => { +export function ConversationLongMessage(): JSX.Element { const messages = [ "Long line. This is a really really really long line. Really really long. Because that's just how it is", `Many lines. This is a many-line message. @@ -482,13 +500,13 @@ Line 4, well.`, }))} /> ); -}; +} ConversationLongMessage.story = { name: 'Conversation: Long Message', }; -export const ConversationsVariousTimes = (): JSX.Element => { +export function ConversationsVariousTimes(): JSX.Element { const pairs: Array<[number, string]> = [ [Date.now() - 5 * 60 * 60 * 1000, 'Five hours ago'], [Date.now() - 24 * 60 * 60 * 1000, 'One day ago'], @@ -511,33 +529,33 @@ export const ConversationsVariousTimes = (): JSX.Element => { }))} /> ); -}; +} ConversationsVariousTimes.story = { name: 'Conversations: Various Times', }; -export const ConversationMissingDate = (): JSX.Element => { +export function ConversationMissingDate(): JSX.Element { const row = { type: RowType.Conversation as const, conversation: omit(createConversation(), 'lastUpdated'), }; return ; -}; +} ConversationMissingDate.story = { name: 'Conversation: Missing Date', }; -export const ConversationMissingMessage = (): JSX.Element => { +export function ConversationMissingMessage(): JSX.Element { const row = { type: RowType.Conversation as const, conversation: omit(createConversation(), 'lastMessage'), }; return ; -}; +} ConversationMissingMessage.story = { name: 'Conversation: Missing Message', @@ -580,178 +598,188 @@ ConversationAtMention.story = { name: 'Conversation: At Mention', }; -export const Headers = (): JSX.Element => ( - -); +export function Headers(): JSX.Element { + return ( + + ); +} -export const FindByPhoneNumber = (): JSX.Element => ( - -); + { + type: RowType.StartNewConversation, + phoneNumber: { + isValid: true, + userInput: '+1(234)555', + e164: '+1234555', + }, + isFetching: false, + }, + ]} + /> + ); +} FindByPhoneNumber.story = { name: 'Find by phone number', }; -export const FindByUsername = (): JSX.Element => ( - -); +export function FindByUsername(): JSX.Element { + return ( + + ); +} FindByUsername.story = { name: 'Find by username', }; -export const SearchResultsLoadingSkeleton = (): JSX.Element => ( - ({ - type: RowType.SearchResultsLoadingFakeRow as const, - })), - ]} - /> -); +export function SearchResultsLoadingSkeleton(): JSX.Element { + return ( + ({ + type: RowType.SearchResultsLoadingFakeRow as const, + })), + ]} + /> + ); +} SearchResultsLoadingSkeleton.story = { name: 'Search results loading skeleton', }; -export const KitchenSink = (): JSX.Element => ( - -); + { + type: RowType.Header, + i18nKey: 'contactsHeader', + }, + { + type: RowType.Contact, + contact: defaultConversations[0], + }, + { + type: RowType.Header, + i18nKey: 'messagesHeader', + }, + { + type: RowType.Conversation, + conversation: defaultConversations[1], + }, + { + type: RowType.MessageSearchResult, + messageId: '123', + }, + { + type: RowType.Header, + i18nKey: 'findByUsernameHeader', + }, + { + type: RowType.UsernameSearchResult, + username: 'jowerty', + isFetchingUsername: false, + }, + { + type: RowType.ArchiveButton, + archivedConversationsCount: 123, + }, + ]} + /> + ); +} KitchenSink.story = { name: 'Kitchen sink', diff --git a/ts/components/ConversationList.tsx b/ts/components/ConversationList.tsx index aec7fe55f9..4d16ead9a1 100644 --- a/ts/components/ConversationList.tsx +++ b/ts/components/ConversationList.tsx @@ -173,7 +173,7 @@ export type PropsType = { disabledReason: undefined | ContactCheckboxDisabledReason ) => void; onSelectConversation: (conversationId: string, messageId?: string) => void; - renderMessageSearchResult: (id: string) => JSX.Element; + renderMessageSearchResult?: (id: string) => JSX.Element; showChooseGroupMembers: () => void; showConversation: ShowConversationType; } & LookupConversationWithoutUuidActionsType; @@ -182,7 +182,7 @@ const NORMAL_ROW_HEIGHT = 76; const SELECT_ROW_HEIGHT = 52; const HEADER_ROW_HEIGHT = 40; -export const ConversationList: React.FC = ({ +export function ConversationList({ dimensions, getPreferredBadge, getRow, @@ -202,7 +202,7 @@ export const ConversationList: React.FC = ({ setIsFetchingUUID, showConversation, theme, -}) => { +}: PropsType): JSX.Element | null { const calculateRowHeight = useCallback( (index: number): number => { const row = getRow(index); @@ -252,7 +252,7 @@ export const ConversationList: React.FC = ({ ); break; case RowType.Blank: - result = <>; + result = undefined; break; case RowType.Contact: { const { isClickable = true } = row; @@ -381,7 +381,7 @@ export const ConversationList: React.FC = ({ ); break; case RowType.MessageSearchResult: - result = <>{renderMessageSearchResult(row.messageId)}; + result = <>{renderMessageSearchResult?.(row.messageId)}; break; case RowType.SearchResultsLoadingFakeHeader: result = ; @@ -479,4 +479,4 @@ export const ConversationList: React.FC = ({ scrollBehavior={scrollBehavior} /> ); -}; +} diff --git a/ts/components/CustomColorEditor.stories.tsx b/ts/components/CustomColorEditor.stories.tsx index a3cc482b78..173e7cc454 100644 --- a/ts/components/CustomColorEditor.stories.tsx +++ b/ts/components/CustomColorEditor.stories.tsx @@ -22,6 +22,6 @@ const createProps = (): PropsType => ({ onSave: action('onSave'), }); -export const Default = (): JSX.Element => ( - -); +export function Default(): JSX.Element { + return ; +} diff --git a/ts/components/CustomColorEditor.tsx b/ts/components/CustomColorEditor.tsx index f50d10054f..5fbab85f8d 100644 --- a/ts/components/CustomColorEditor.tsx +++ b/ts/components/CustomColorEditor.tsx @@ -42,12 +42,12 @@ const ULTRAMARINE_ISH: CustomColorType = { deg: 180, }; -export const CustomColorEditor = ({ +export function CustomColorEditor({ customColor = ULTRAMARINE_ISH, i18n, onClose, onSave, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [color, setColor] = useState(customColor); const [selectedColorKnob, setSelectedColorKnob] = useState( KnobType.start @@ -57,135 +57,129 @@ export const CustomColorEditor = ({ color[selectedColorKnob] || ULTRAMARINE_ISH_VALUES; return ( - <> - { - if (selectedTab === TabViews.Gradient && !color.end) { - setColor({ - ...color, - end: ULTRAMARINE_ISH_VALUES, - }); - } + { + if (selectedTab === TabViews.Gradient && !color.end) { + setColor({ + ...color, + end: ULTRAMARINE_ISH_VALUES, + }); + } - if (selectedTab === TabViews.Solid && color.end) { - setColor({ - ...color, - end: undefined, - }); - } - }} - tabs={[ - { - id: TabViews.Solid, - label: i18n('CustomColorEditor__solid'), - }, - { - id: TabViews.Gradient, - label: i18n('CustomColorEditor__gradient'), - }, - ]} - > - {({ selectedTab }) => ( - <> -
- - {selectedTab === TabViews.Gradient && ( - <> - { - setColor({ - ...color, - deg, - }); - }} - onClick={knob => setSelectedColorKnob(knob)} - selectedKnob={selectedColorKnob} - /> - - )} -
-
- {i18n('CustomColorEditor__hue')} - + {({ selectedTab }) => ( + <> +
+ + {selectedTab === TabViews.Gradient && ( + { + onChange={deg => { setColor({ ...color, - [selectedColorKnob]: { - ...ULTRAMARINE_ISH_VALUES, - ...color[selectedColorKnob], - hue: getValue(percentage, MAX_HUE), - }, + deg, }); }} - value={getPercentage(hue, MAX_HUE)} + onClick={knob => setSelectedColorKnob(knob)} + selectedKnob={selectedColorKnob} /> -
-
- {i18n('CustomColorEditor__saturation')} - { - setColor({ - ...color, - [selectedColorKnob]: { - ...ULTRAMARINE_ISH_VALUES, - ...color[selectedColorKnob], - saturation: value, - }, - }); - }} - value={saturation} - /> -
-
- - -
- - )} - - + )} +
+
+ {i18n('CustomColorEditor__hue')} + { + setColor({ + ...color, + [selectedColorKnob]: { + ...ULTRAMARINE_ISH_VALUES, + ...color[selectedColorKnob], + hue: getValue(percentage, MAX_HUE), + }, + }); + }} + value={getPercentage(hue, MAX_HUE)} + /> +
+
+ {i18n('CustomColorEditor__saturation')} + { + setColor({ + ...color, + [selectedColorKnob]: { + ...ULTRAMARINE_ISH_VALUES, + ...color[selectedColorKnob], + saturation: value, + }, + }); + }} + value={saturation} + /> +
+
+ + +
+ + )} +
); -}; +} diff --git a/ts/components/CustomizingPreferredReactionsModal.stories.tsx b/ts/components/CustomizingPreferredReactionsModal.stories.tsx index 8d7256a423..62a69bc677 100644 --- a/ts/components/CustomizingPreferredReactionsModal.stories.tsx +++ b/ts/components/CustomizingPreferredReactionsModal.stories.tsx @@ -37,28 +37,30 @@ const defaultProps: ComponentProps = skinTone: 4, }; -export const Default = (): JSX.Element => ( - -); +export function Default(): JSX.Element { + return ; +} -export const DraftEmojiSelected = (): JSX.Element => ( - -); +export function DraftEmojiSelected(): JSX.Element { + return ( + + ); +} DraftEmojiSelected.story = { name: 'Draft emoji selected', }; -export const Saving = (): JSX.Element => ( - -); +export function Saving(): JSX.Element { + return ; +} -export const HadError = (): JSX.Element => ( - -); +export function HadError(): JSX.Element { + return ; +} HadError.story = { name: 'Had error', diff --git a/ts/components/DebugLogWindow.tsx b/ts/components/DebugLogWindow.tsx index dd1f19e82b..def1335f06 100644 --- a/ts/components/DebugLogWindow.tsx +++ b/ts/components/DebugLogWindow.tsx @@ -41,7 +41,7 @@ enum ToastType { Loading, } -export const DebugLogWindow = ({ +export function DebugLogWindow({ closeWindow, downloadLog, i18n, @@ -49,7 +49,7 @@ export const DebugLogWindow = ({ uploadLogs, hasCustomTitleBar, executeMenuRole, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [loadState, setLoadState] = useState(LoadState.NotStarted); const [logText, setLogText] = useState(); const [publicLogURL, setPublicLogURL] = useState(); @@ -230,4 +230,4 @@ export const DebugLogWindow = ({ ); -}; +} diff --git a/ts/components/DialogExpiredBuild.tsx b/ts/components/DialogExpiredBuild.tsx index 0ab680ee64..1deb50596f 100644 --- a/ts/components/DialogExpiredBuild.tsx +++ b/ts/components/DialogExpiredBuild.tsx @@ -15,11 +15,11 @@ type PropsType = { i18n: LocalizerType; }; -export const DialogExpiredBuild = ({ +export function DialogExpiredBuild({ containerWidthBreakpoint, hasExpired, i18n, -}: PropsType): JSX.Element | null => { +}: PropsType): JSX.Element | null { if (!hasExpired) { return null; } @@ -37,4 +37,4 @@ export const DialogExpiredBuild = ({ {i18n('expiredWarning')}{' '} ); -}; +} diff --git a/ts/components/DialogNetworkStatus.stories.tsx b/ts/components/DialogNetworkStatus.stories.tsx index 07db92a911..6c3a161ad6 100644 --- a/ts/components/DialogNetworkStatus.stories.tsx +++ b/ts/components/DialogNetworkStatus.stories.tsx @@ -29,7 +29,7 @@ export default { title: 'Components/DialogNetworkStatus', }; -export const KnobsPlayground = (args: PropsType): JSX.Element => { +export function KnobsPlayground(args: PropsType): JSX.Element { /* const socketStatus = select( 'socketStatus', @@ -48,7 +48,7 @@ export const KnobsPlayground = (args: PropsType): JSX.Element => { ); -}; +} KnobsPlayground.args = { containerWidthBreakpoint: WidthBreakpoint.Wide, hasNetworkDialog: true, @@ -56,113 +56,129 @@ KnobsPlayground.args = { socketStatus: SocketStatus.CONNECTING, }; -export const ConnectingWide = (): JSX.Element => ( - - - -); +export function ConnectingWide(): JSX.Element { + return ( + + + + ); +} ConnectingWide.story = { name: 'Connecting Wide', }; -export const ClosingWide = (): JSX.Element => ( - - - -); +export function ClosingWide(): JSX.Element { + return ( + + + + ); +} ClosingWide.story = { name: 'Closing Wide', }; -export const ClosedWide = (): JSX.Element => ( - - - -); +export function ClosedWide(): JSX.Element { + return ( + + + + ); +} ClosedWide.story = { name: 'Closed Wide', }; -export const OfflineWide = (): JSX.Element => ( - - - -); +export function OfflineWide(): JSX.Element { + return ( + + + + ); +} OfflineWide.story = { name: 'Offline Wide', }; -export const ConnectingNarrow = (): JSX.Element => ( - - - -); +export function ConnectingNarrow(): JSX.Element { + return ( + + + + ); +} ConnectingNarrow.story = { name: 'Connecting Narrow', }; -export const ClosingNarrow = (): JSX.Element => ( - - - -); +export function ClosingNarrow(): JSX.Element { + return ( + + + + ); +} ClosingNarrow.story = { name: 'Closing Narrow', }; -export const ClosedNarrow = (): JSX.Element => ( - - - -); +export function ClosedNarrow(): JSX.Element { + return ( + + + + ); +} ClosedNarrow.story = { name: 'Closed Narrow', }; -export const OfflineNarrow = (): JSX.Element => ( - - - -); +export function OfflineNarrow(): JSX.Element { + return ( + + + + ); +} OfflineNarrow.story = { name: 'Offline Narrow', diff --git a/ts/components/DialogNetworkStatus.tsx b/ts/components/DialogNetworkStatus.tsx index d4af87ad19..3eb0c2a569 100644 --- a/ts/components/DialogNetworkStatus.tsx +++ b/ts/components/DialogNetworkStatus.tsx @@ -20,14 +20,14 @@ export type PropsType = NetworkStateType & { manualReconnect: () => void; }; -export const DialogNetworkStatus = ({ +export function DialogNetworkStatus({ containerWidthBreakpoint, hasNetworkDialog, i18n, isOnline, socketStatus, manualReconnect, -}: PropsType): JSX.Element | null => { +}: PropsType): JSX.Element | null { const [isConnecting, setIsConnecting] = React.useState( socketStatus === SocketStatus.CONNECTING ); @@ -93,4 +93,4 @@ export const DialogNetworkStatus = ({ onClick={reconnect} /> ); -}; +} diff --git a/ts/components/DialogRelink.stories.tsx b/ts/components/DialogRelink.stories.tsx index 550f98eb84..edba618394 100644 --- a/ts/components/DialogRelink.stories.tsx +++ b/ts/components/DialogRelink.stories.tsx @@ -41,15 +41,15 @@ export default { title: 'Components/DialogRelink', }; -export const KnobsPlayground = (): JSX.Element => { +export function KnobsPlayground(): JSX.Element { const isRegistrationDone = boolean('isRegistrationDone', false); return ( ); -}; +} -export const Iterations = (): JSX.Element => { +export function Iterations(): JSX.Element { return ( <> {permutations.map(({ props, title }) => ( @@ -64,4 +64,4 @@ export const Iterations = (): JSX.Element => { ))} ); -}; +} diff --git a/ts/components/DialogRelink.tsx b/ts/components/DialogRelink.tsx index dd3202c98a..472b4b9a6f 100644 --- a/ts/components/DialogRelink.tsx +++ b/ts/components/DialogRelink.tsx @@ -15,12 +15,12 @@ export type PropsType = { relinkDevice: () => void; }; -export const DialogRelink = ({ +export function DialogRelink({ containerWidthBreakpoint, i18n, isRegistrationDone, relinkDevice, -}: PropsType): JSX.Element | null => { +}: PropsType): JSX.Element | null { if (isRegistrationDone) { return null; } @@ -36,4 +36,4 @@ export const DialogRelink = ({ hasAction /> ); -}; +} diff --git a/ts/components/DialogUpdate.stories.tsx b/ts/components/DialogUpdate.stories.tsx index 318f8b00dd..6c76d27b1f 100644 --- a/ts/components/DialogUpdate.stories.tsx +++ b/ts/components/DialogUpdate.stories.tsx @@ -32,7 +32,7 @@ export default { title: 'Components/DialogUpdate', }; -export const KnobsPlayground = (): JSX.Element => { +export function KnobsPlayground(): JSX.Element { const containerWidthBreakpoint = select( 'containerWidthBreakpoint', WidthBreakpoint, @@ -54,277 +54,313 @@ export const KnobsPlayground = (): JSX.Element => { /> ); -}; +} -export const UpdateWide = (): JSX.Element => ( - - - -); +export function UpdateWide(): JSX.Element { + return ( + + + + ); +} UpdateWide.story = { name: 'Update (Wide)', }; -export const DownloadReadyWide = (): JSX.Element => ( - - - -); +export function DownloadReadyWide(): JSX.Element { + return ( + + + + ); +} DownloadReadyWide.story = { name: 'DownloadReady (Wide)', }; -export const FullDownloadReadyWide = (): JSX.Element => ( - - - -); +export function FullDownloadReadyWide(): JSX.Element { + return ( + + + + ); +} FullDownloadReadyWide.story = { name: 'FullDownloadReady (Wide)', }; -export const DownloadingWide = (): JSX.Element => ( - - - -); +export function DownloadingWide(): JSX.Element { + return ( + + + + ); +} DownloadingWide.story = { name: 'Downloading (Wide)', }; -export const CannotUpdateWide = (): JSX.Element => ( - - - -); +export function CannotUpdateWide(): JSX.Element { + return ( + + + + ); +} CannotUpdateWide.story = { name: 'Cannot_Update (Wide)', }; -export const CannotUpdateBetaWide = (): JSX.Element => ( - - - -); +export function CannotUpdateBetaWide(): JSX.Element { + return ( + + + + ); +} CannotUpdateBetaWide.story = { name: 'Cannot_Update_Beta (Wide)', }; -export const CannotUpdateRequireManualWide = (): JSX.Element => ( - - - -); +export function CannotUpdateRequireManualWide(): JSX.Element { + return ( + + + + ); +} CannotUpdateRequireManualWide.story = { name: 'Cannot_Update_Require_Manual (Wide)', }; -export const CannotUpdateRequireManualBetaWide = (): JSX.Element => ( - - - -); +export function CannotUpdateRequireManualBetaWide(): JSX.Element { + return ( + + + + ); +} CannotUpdateRequireManualBetaWide.story = { name: 'Cannot_Update_Require_Manual_Beta (Wide)', }; -export const MacOSReadOnlyWide = (): JSX.Element => ( - - - -); +export function MacOSReadOnlyWide(): JSX.Element { + return ( + + + + ); +} MacOSReadOnlyWide.story = { name: 'MacOS_Read_Only (Wide)', }; -export const UpdateNarrow = (): JSX.Element => ( - - - -); +export function UpdateNarrow(): JSX.Element { + return ( + + + + ); +} UpdateNarrow.story = { name: 'Update (Narrow)', }; -export const DownloadReadyNarrow = (): JSX.Element => ( - - - -); +export function DownloadReadyNarrow(): JSX.Element { + return ( + + + + ); +} DownloadReadyNarrow.story = { name: 'DownloadReady (Narrow)', }; -export const FullDownloadReadyNarrow = (): JSX.Element => ( - - - -); +export function FullDownloadReadyNarrow(): JSX.Element { + return ( + + + + ); +} FullDownloadReadyNarrow.story = { name: 'FullDownloadReady (Narrow)', }; -export const DownloadingNarrow = (): JSX.Element => ( - - - -); +export function DownloadingNarrow(): JSX.Element { + return ( + + + + ); +} DownloadingNarrow.story = { name: 'Downloading (Narrow)', }; -export const CannotUpdateNarrow = (): JSX.Element => ( - - - -); +export function CannotUpdateNarrow(): JSX.Element { + return ( + + + + ); +} CannotUpdateNarrow.story = { name: 'Cannot Update (Narrow)', }; -export const CannotUpdateBetaNarrow = (): JSX.Element => ( - - - -); +export function CannotUpdateBetaNarrow(): JSX.Element { + return ( + + + + ); +} CannotUpdateBetaNarrow.story = { name: 'Cannot Update Beta (Narrow)', }; -export const CannotUpdateRequireManualNarrow = (): JSX.Element => ( - - - -); +export function CannotUpdateRequireManualNarrow(): JSX.Element { + return ( + + + + ); +} CannotUpdateRequireManualNarrow.story = { name: 'Cannot_Update_Require_Manual (Narrow)', }; -export const CannotUpdateRequireManualBetaNarrow = (): JSX.Element => ( - - - -); +export function CannotUpdateRequireManualBetaNarrow(): JSX.Element { + return ( + + + + ); +} CannotUpdateRequireManualBetaNarrow.story = { name: 'Cannot_Update_Require_Manual_Beta (Narrow)', }; -export const MacOSReadOnlyNarrow = (): JSX.Element => ( - - - -); +export function MacOSReadOnlyNarrow(): JSX.Element { + return ( + + + + ); +} MacOSReadOnlyNarrow.story = { name: 'MacOS_Read_Only (Narrow)', diff --git a/ts/components/DialogUpdate.tsx b/ts/components/DialogUpdate.tsx index 07877b1892..103051b409 100644 --- a/ts/components/DialogUpdate.tsx +++ b/ts/components/DialogUpdate.tsx @@ -30,7 +30,7 @@ export type PropsType = { const PRODUCTION_DOWNLOAD_URL = 'https://signal.org/download/'; const BETA_DOWNLOAD_URL = 'https://support.signal.org/beta'; -export const DialogUpdate = ({ +export function DialogUpdate({ containerWidthBreakpoint, dialogType, didSnooze, @@ -43,7 +43,7 @@ export const DialogUpdate = ({ startUpdate, version, currentVersion, -}: PropsType): JSX.Element | null => { +}: PropsType): JSX.Element | null { if (hasNetworkDialog) { return null; } @@ -237,4 +237,4 @@ export const DialogUpdate = ({ closeLabel={i18n('autoUpdateIgnoreButtonLabel')} /> ); -}; +} diff --git a/ts/components/DirectCallRemoteParticipant.tsx b/ts/components/DirectCallRemoteParticipant.tsx index 01eeba6de8..80d1145178 100644 --- a/ts/components/DirectCallRemoteParticipant.tsx +++ b/ts/components/DirectCallRemoteParticipant.tsx @@ -15,12 +15,12 @@ type PropsType = { setRendererCanvas: (_: SetRendererCanvasType) => void; }; -export const DirectCallRemoteParticipant: React.FC = ({ +export function DirectCallRemoteParticipant({ conversation, hasRemoteVideo, i18n, setRendererCanvas, -}) => { +}: PropsType): JSX.Element { const remoteVideoRef = useRef(null); useEffect(() => { @@ -38,7 +38,7 @@ export const DirectCallRemoteParticipant: React.FC = ({ ) : ( renderAvatar(i18n, conversation) ); -}; +} function renderAvatar( i18n: LocalizerType, diff --git a/ts/components/DisappearingTimeDialog.stories.tsx b/ts/components/DisappearingTimeDialog.stories.tsx index 965bc9253b..3ed55aa89a 100644 --- a/ts/components/DisappearingTimeDialog.stories.tsx +++ b/ts/components/DisappearingTimeDialog.stories.tsx @@ -16,47 +16,57 @@ export default { const i18n = setupI18n('en', enMessages); -export const Seconds = (): JSX.Element => ( - -); +export function Seconds(): JSX.Element { + return ( + + ); +} -export const Minutes = (): JSX.Element => ( - -); +export function Minutes(): JSX.Element { + return ( + + ); +} -export const Hours = (): JSX.Element => ( - -); +export function Hours(): JSX.Element { + return ( + + ); +} -export const Days = (): JSX.Element => ( - -); +export function Days(): JSX.Element { + return ( + + ); +} -export const Weeks = (): JSX.Element => ( - -); +export function Weeks(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/DisappearingTimerSelect.stories.tsx b/ts/components/DisappearingTimerSelect.stories.tsx index e8aa8fffe2..11d8973f0c 100644 --- a/ts/components/DisappearingTimerSelect.stories.tsx +++ b/ts/components/DisappearingTimerSelect.stories.tsx @@ -18,7 +18,7 @@ type Props = { initialValue: number; }; -const TimerSelectWrap: React.FC = ({ initialValue }) => { +function TimerSelectWrap({ initialValue }: Props): JSX.Element { const [value, setValue] = useState(initialValue); return ( @@ -28,19 +28,19 @@ const TimerSelectWrap: React.FC = ({ initialValue }) => { onChange={newValue => setValue(newValue)} /> ); -}; +} -export const InitialValue1Day = (): JSX.Element => ( - -); +export function InitialValue1Day(): JSX.Element { + return ; +} InitialValue1Day.story = { name: 'Initial value: 1 day', }; -export const InitialValue3DaysCustomTime = (): JSX.Element => ( - -); +export function InitialValue3DaysCustomTime(): JSX.Element { + return ; +} InitialValue3DaysCustomTime.story = { name: 'Initial value 3 days (Custom time)', diff --git a/ts/components/DisappearingTimerSelect.tsx b/ts/components/DisappearingTimerSelect.tsx index f78a1015fe..958579da01 100644 --- a/ts/components/DisappearingTimerSelect.tsx +++ b/ts/components/DisappearingTimerSelect.tsx @@ -21,7 +21,7 @@ export type Props = { onChange(value: DurationInSeconds): void; }; -export const DisappearingTimerSelect: React.FC = (props: Props) => { +export function DisappearingTimerSelect(props: Props): JSX.Element { const { i18n, value = DurationInSeconds.ZERO, onChange } = props; const [isModalOpen, setIsModalOpen] = useState(false); @@ -104,4 +104,4 @@ export const DisappearingTimerSelect: React.FC = (props: Props) => { {modalNode} ); -}; +} diff --git a/ts/components/EditUsernameModalBody.stories.tsx b/ts/components/EditUsernameModalBody.stories.tsx index 63dbc46ea8..b7205ac1cb 100644 --- a/ts/components/EditUsernameModalBody.stories.tsx +++ b/ts/components/EditUsernameModalBody.stories.tsx @@ -80,6 +80,7 @@ type ArgsType = PropsType & { reservation?: UsernameReservationType; }; +// eslint-disable-next-line react/function-component-definition const Template: Story = args => { let { reservation } = args; if (!reservation && args.discriminator) { diff --git a/ts/components/EditUsernameModalBody.tsx b/ts/components/EditUsernameModalBody.tsx index 6db309deee..431c0f7cbf 100644 --- a/ts/components/EditUsernameModalBody.tsx +++ b/ts/components/EditUsernameModalBody.tsx @@ -45,7 +45,7 @@ export type PropsType = PropsDataType & ActionPropsDataType & ExternalPropsDataType; -export const EditUsernameModalBody = ({ +export function EditUsernameModalBody({ i18n, currentUsername, reserveUsername, @@ -57,7 +57,7 @@ export const EditUsernameModalBody = ({ error, state, onClose, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const currentNickname = useMemo(() => { if (!currentUsername) { return undefined; @@ -266,4 +266,4 @@ export const EditUsernameModalBody = ({ )} ); -}; +} diff --git a/ts/components/ErrorModal.stories.tsx b/ts/components/ErrorModal.stories.tsx index a0a9f5611e..42722fd5c1 100644 --- a/ts/components/ErrorModal.stories.tsx +++ b/ts/components/ErrorModal.stories.tsx @@ -25,11 +25,11 @@ export default { title: 'Components/ErrorModal', }; -export const Normal = (): JSX.Element => { +export function Normal(): JSX.Element { return ; -}; +} -export const CustomStrings = (): JSX.Element => { +export function CustomStrings(): JSX.Element { return ( { })} /> ); -}; +} diff --git a/ts/components/ErrorModal.tsx b/ts/components/ErrorModal.tsx index 43edb586e9..5d6dcb1aa9 100644 --- a/ts/components/ErrorModal.tsx +++ b/ts/components/ErrorModal.tsx @@ -22,7 +22,7 @@ function focusRef(el: HTMLElement | null) { } } -export const ErrorModal = (props: PropsType): JSX.Element => { +export function ErrorModal(props: PropsType): JSX.Element { const { buttonText, description, i18n, onClose, title } = props; const footer = ( @@ -44,4 +44,4 @@ export const ErrorModal = (props: PropsType): JSX.Element => { ); -}; +} diff --git a/ts/components/ForwardMessageModal.stories.tsx b/ts/components/ForwardMessageModal.stories.tsx index 959669ca8a..a0a9512b8a 100644 --- a/ts/components/ForwardMessageModal.stories.tsx +++ b/ts/components/ForwardMessageModal.stories.tsx @@ -72,35 +72,35 @@ const useProps = (overrideProps: Partial = {}): PropsType => ({ regionCode: 'US', }); -export const Modal = (): JSX.Element => { +export function Modal(): JSX.Element { return ; -}; +} -export const WithText = (): JSX.Element => { +export function WithText(): JSX.Element { return ; -}; +} WithText.story = { name: 'with text', }; -export const ASticker = (): JSX.Element => { +export function ASticker(): JSX.Element { return ; -}; +} ASticker.story = { name: 'a sticker', }; -export const WithAContact = (): JSX.Element => { +export function WithAContact(): JSX.Element { return ; -}; +} WithAContact.story = { name: 'with a contact', }; -export const LinkPreview = (): JSX.Element => { +export function LinkPreview(): JSX.Element { return ( { })} /> ); -}; +} LinkPreview.story = { name: 'link preview', }; -export const MediaAttachments = (): JSX.Element => { +export function MediaAttachments(): JSX.Element { return ( { })} /> ); -}; +} MediaAttachments.story = { name: 'media attachments', }; -export const AnnouncementOnlyGroupsNonAdmin = (): JSX.Element => ( - -); +export function AnnouncementOnlyGroupsNonAdmin(): JSX.Element { + return ( + + ); +} AnnouncementOnlyGroupsNonAdmin.story = { name: 'announcement only groups non-admin', diff --git a/ts/components/ForwardMessageModal.tsx b/ts/components/ForwardMessageModal.tsx index 68792a4d29..3248fe7349 100644 --- a/ts/components/ForwardMessageModal.tsx +++ b/ts/components/ForwardMessageModal.tsx @@ -1,7 +1,6 @@ // Copyright 2021-2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { FunctionComponent } from 'react'; import React, { useCallback, useEffect, @@ -76,7 +75,7 @@ export type PropsType = DataPropsType & ActionPropsType; const MAX_FORWARD = 5; -export const ForwardMessageModal: FunctionComponent = ({ +export function ForwardMessageModal({ attachments, candidateConversations, doForwardMessage, @@ -92,7 +91,7 @@ export const ForwardMessageModal: FunctionComponent = ({ RenderCompositionTextArea, theme, regionCode, -}) => { +}: PropsType): JSX.Element { const inputRef = useRef(null); const [selectedContacts, setSelectedContacts] = useState< Array @@ -428,4 +427,4 @@ export const ForwardMessageModal: FunctionComponent = ({ ); -}; +} diff --git a/ts/components/GlobalAudioContext.tsx b/ts/components/GlobalAudioContext.tsx index cd2cfff844..2325bfdffd 100644 --- a/ts/components/GlobalAudioContext.tsx +++ b/ts/components/GlobalAudioContext.tsx @@ -183,11 +183,11 @@ export type GlobalAudioProps = { * A global context that holds Audio, AudioContext, LRU instances that are used * inside the conversation by ts/components/conversation/MessageAudio.tsx */ -export const GlobalAudioProvider: React.FC = ({ +export function GlobalAudioProvider({ conversationId, children, unloadMessageAudio, -}) => { +}: GlobalAudioProps): JSX.Element { // When moving between conversations - stop audio React.useEffect(() => { return () => { @@ -200,4 +200,4 @@ export const GlobalAudioProvider: React.FC = ({ {children} ); -}; +} diff --git a/ts/components/GlobalModalContainer.tsx b/ts/components/GlobalModalContainer.tsx index 5def11f040..1096939f0b 100644 --- a/ts/components/GlobalModalContainer.tsx +++ b/ts/components/GlobalModalContainer.tsx @@ -52,7 +52,7 @@ export type PropsType = { hideWhatsNewModal: () => unknown; }; -export const GlobalModalContainer = ({ +export function GlobalModalContainer({ i18n, // ContactModal contactModalState, @@ -85,7 +85,7 @@ export const GlobalModalContainer = ({ // WhatsNewModal hideWhatsNewModal, isWhatsNewVisible, -}: PropsType): JSX.Element | null => { +}: PropsType): JSX.Element | null { // We want the send anyway dialog to supersede most modals since this is an // immediate action the user needs to take. if (hasSafetyNumberChangeModal || safetyNumberChangedBlockingData) { @@ -159,4 +159,4 @@ export const GlobalModalContainer = ({ } return null; -}; +} diff --git a/ts/components/GradientDial.tsx b/ts/components/GradientDial.tsx index 0e7c743693..fbcfb5dacd 100644 --- a/ts/components/GradientDial.tsx +++ b/ts/components/GradientDial.tsx @@ -184,14 +184,14 @@ function getKnobCoordinates( }; } -export const GradientDial = ({ +export function GradientDial({ deg = 180, knob1Style, knob2Style, onChange, onClick, selectedKnob, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const containerRef = useRef(null); const [knobDim, setKnobDim] = useState<{ @@ -325,4 +325,4 @@ export const GradientDial = ({ )} ); -}; +} diff --git a/ts/components/GroupCallOverflowArea.stories.tsx b/ts/components/GroupCallOverflowArea.stories.tsx index 422f90b7e1..053edfe641 100644 --- a/ts/components/GroupCallOverflowArea.stories.tsx +++ b/ts/components/GroupCallOverflowArea.stories.tsx @@ -1,7 +1,6 @@ // Copyright 2021-2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { FC } from 'react'; import React from 'react'; import { memoize, times } from 'lodash'; import { number } from '@storybook/addon-knobs'; @@ -44,70 +43,80 @@ const defaultProps = { }; // This component is usually rendered on a call screen. -const Container: FC = ({ children }) => ( -
- {children} -
-); +function Container({ children }: { children: JSX.Element }): JSX.Element { + return ( +
+ {children} +
+ ); +} -export const NoOverflowedParticipants = (): JSX.Element => ( - - - -); +export function NoOverflowedParticipants(): JSX.Element { + return ( + + + + ); +} NoOverflowedParticipants.story = { name: 'No overflowed participants', }; -export const OneOverflowedParticipant = (): JSX.Element => ( - - - -); +export function OneOverflowedParticipant(): JSX.Element { + return ( + + + + ); +} OneOverflowedParticipant.story = { name: 'One overflowed participant', }; -export const ThreeOverflowedParticipants = (): JSX.Element => ( - - - -); +export function ThreeOverflowedParticipants(): JSX.Element { + return ( + + + + ); +} ThreeOverflowedParticipants.story = { name: 'Three overflowed participants', }; -export const ManyOverflowedParticipants = (): JSX.Element => ( - - - -); +export function ManyOverflowedParticipants(): JSX.Element { + return ( + + + + ); +} ManyOverflowedParticipants.story = { name: 'Many overflowed participants', diff --git a/ts/components/GroupCallOverflowArea.tsx b/ts/components/GroupCallOverflowArea.tsx index 0bff0201ed..4424c80ebe 100644 --- a/ts/components/GroupCallOverflowArea.tsx +++ b/ts/components/GroupCallOverflowArea.tsx @@ -1,7 +1,7 @@ // Copyright 2021-2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { FC, ReactElement } from 'react'; +import type { ReactElement } from 'react'; import React, { useRef, useState, useEffect } from 'react'; import classNames from 'classnames'; import type { VideoFrameSource } from 'ringrtc'; @@ -27,14 +27,14 @@ type PropsType = { remoteAudioLevels: Map; }; -export const GroupCallOverflowArea: FC = ({ +export function GroupCallOverflowArea({ getFrameBuffer, getGroupCallVideoFrameSource, i18n, onParticipantVisibilityChanged, overflowedParticipants, remoteAudioLevels, -}) => { +}: PropsType): JSX.Element | null { const overflowRef = useRef(null); const [overflowScrollTop, setOverflowScrollTop] = useState(0); @@ -147,7 +147,7 @@ export const GroupCallOverflowArea: FC = ({ /> ); -}; +} function OverflowAreaScrollMarker({ i18n, diff --git a/ts/components/GroupCallRemoteParticipant.stories.tsx b/ts/components/GroupCallRemoteParticipant.stories.tsx index 082ead69ae..6279945a57 100644 --- a/ts/components/GroupCallRemoteParticipant.stories.tsx +++ b/ts/components/GroupCallRemoteParticipant.stories.tsx @@ -67,57 +67,65 @@ export default { title: 'Components/GroupCallRemoteParticipant', }; -export const Default = (): JSX.Element => ( - -); - -export const Speaking = (): JSX.Element => ( - -); + })} + /> + ); +} -export const IsInPip = (): JSX.Element => ( - -); +export function Speaking(): JSX.Element { + return ( + + ); +} + +export function IsInPip(): JSX.Element { + return ( + + ); +} IsInPip.story = { name: 'isInPip', }; -export const Blocked = (): JSX.Element => ( - -); +export function Blocked(): JSX.Element { + return ( + + ); +} diff --git a/ts/components/GroupCallRemoteParticipant.tsx b/ts/components/GroupCallRemoteParticipant.tsx index 7f98fa3adf..085238909b 100644 --- a/ts/components/GroupCallRemoteParticipant.tsx +++ b/ts/components/GroupCallRemoteParticipant.tsx @@ -55,7 +55,7 @@ export type PropsType = BasePropsType & (InPipPropsType | InOverflowAreaPropsType | InGridPropsType); export const GroupCallRemoteParticipant: React.FC = React.memo( - props => { + function GroupCallRemoteParticipantInner(props) { const { getFrameBuffer, getGroupCallVideoFrameSource, diff --git a/ts/components/GroupCallRemoteParticipants.tsx b/ts/components/GroupCallRemoteParticipants.tsx index 50d796f652..551839c1a8 100644 --- a/ts/components/GroupCallRemoteParticipants.tsx +++ b/ts/components/GroupCallRemoteParticipants.tsx @@ -84,14 +84,14 @@ enum VideoRequestMode { // "scalar": how much can we scale these boxes up while still fitting them on the // screen? The biggest scalar wins as the "best arrangement". // 4. Lay out this arrangement on the screen. -export const GroupCallRemoteParticipants: React.FC = ({ +export function GroupCallRemoteParticipants({ getGroupCallVideoFrameSource, i18n, isInSpeakerView, remoteParticipants, setGroupCallVideoRequest, remoteAudioLevels, -}) => { +}: PropsType): JSX.Element { const [containerDimensions, setContainerDimensions] = useState({ width: 0, height: 0, @@ -443,7 +443,7 @@ export const GroupCallRemoteParticipants: React.FC = ({ )} ); -}; +} // This function is only meant for use with `useInvisibleParticipants`. It helps avoid // returning new set instances when the underlying values are equal. diff --git a/ts/components/GroupDescriptionInput.stories.tsx b/ts/components/GroupDescriptionInput.stories.tsx index 85cc3f969f..390fcdd6ee 100644 --- a/ts/components/GroupDescriptionInput.stories.tsx +++ b/ts/components/GroupDescriptionInput.stories.tsx @@ -14,13 +14,13 @@ export default { title: 'Components/GroupDescriptionInput', }; -const Wrapper = ({ +function Wrapper({ disabled, startingValue = '', }: { disabled?: boolean; startingValue?: string; -}) => { +}) { const [value, setValue] = useState(startingValue); return ( @@ -31,14 +31,18 @@ const Wrapper = ({ value={value} /> ); -}; +} -export const Default = (): JSX.Element => ; +export function Default(): JSX.Element { + return ; +} -export const Disabled = (): JSX.Element => ( - <> - -
- - -); +export function Disabled(): JSX.Element { + return ( + <> + +
+ + + ); +} diff --git a/ts/components/GroupDescriptionInput.tsx b/ts/components/GroupDescriptionInput.tsx index 4092a95661..c6860b717f 100644 --- a/ts/components/GroupDescriptionInput.tsx +++ b/ts/components/GroupDescriptionInput.tsx @@ -14,7 +14,10 @@ type PropsType = { }; export const GroupDescriptionInput = forwardRef( - ({ i18n, disabled = false, onChangeValue, value }, ref) => { + function GroupDescriptionInput( + { i18n, disabled = false, onChangeValue, value }, + ref + ) { return ( ( ); -export const GroupDescriptionText: FunctionComponent = ({ - text, -}) => ; +export function GroupDescriptionText({ text }: PropsType): JSX.Element { + return ; +} diff --git a/ts/components/GroupDialog.tsx b/ts/components/GroupDialog.tsx index 3643e754f4..d458c85ae0 100644 --- a/ts/components/GroupDialog.tsx +++ b/ts/components/GroupDialog.tsx @@ -85,11 +85,11 @@ type ParagraphPropsType = { children: ReactNode; }; -GroupDialog.Paragraph = ({ - children, -}: Readonly): JSX.Element => ( -

{children}

-); +function Paragraph({ children }: Readonly): JSX.Element { + return

{children}

; +} + +GroupDialog.Paragraph = Paragraph; type ContactsPropsType = { contacts: Array; @@ -98,38 +98,41 @@ type ContactsPropsType = { theme: ThemeType; }; -GroupDialog.Contacts = ({ +function Contacts({ contacts, getPreferredBadge, i18n, theme, -}: Readonly) => ( -
    - {contacts.map(contact => ( -
  • - - -
  • - ))} -
-); +}: Readonly): JSX.Element { + return ( +
    + {contacts.map(contact => ( +
  • + + +
  • + ))} +
+ ); +} +GroupDialog.Contacts = Contacts; function focusRef(el: HTMLElement | null) { if (el) { diff --git a/ts/components/GroupTitleInput.stories.tsx b/ts/components/GroupTitleInput.stories.tsx index d0ed4b6f43..af128f3506 100644 --- a/ts/components/GroupTitleInput.stories.tsx +++ b/ts/components/GroupTitleInput.stories.tsx @@ -14,13 +14,13 @@ export default { title: 'Components/GroupTitleInput', }; -const Wrapper = ({ +function Wrapper({ disabled, startingValue = '', }: { disabled?: boolean; startingValue?: string; -}) => { +}) { const [value, setValue] = useState(startingValue); return ( @@ -31,14 +31,18 @@ const Wrapper = ({ value={value} /> ); -}; +} -export const Default = (): JSX.Element => ; +export function Default(): JSX.Element { + return ; +} -export const Disabled = (): JSX.Element => ( - <> - -
- - -); +export function Disabled(): JSX.Element { + return ( + <> + +
+ + + ); +} diff --git a/ts/components/GroupTitleInput.tsx b/ts/components/GroupTitleInput.tsx index f200c13948..748159fab7 100644 --- a/ts/components/GroupTitleInput.tsx +++ b/ts/components/GroupTitleInput.tsx @@ -14,7 +14,10 @@ type PropsType = { }; export const GroupTitleInput = forwardRef( - ({ i18n, disabled = false, onChangeValue, value }, ref) => { + function GroupTitleInputInner( + { i18n, disabled = false, onChangeValue, value }, + ref + ) { return ( { +export function NotYetMigratedBasic(): JSX.Element { return ; -}; +} NotYetMigratedBasic.story = { name: 'Not yet migrated, basic', }; -export const MigratedBasic = (): JSX.Element => { +export function MigratedBasic(): JSX.Element { return ( { })} /> ); -}; +} MigratedBasic.story = { name: 'Migrated, basic', }; -export const MigratedYouAreInvited = (): JSX.Element => { +export function MigratedYouAreInvited(): JSX.Element { return ( { })} /> ); -}; +} MigratedYouAreInvited.story = { name: 'Migrated, you are invited', }; -export const NotYetMigratedMultipleDroppedAndInvitedMembers = - (): JSX.Element => { - return ( - - ); - }; +export function NotYetMigratedMultipleDroppedAndInvitedMembers(): JSX.Element { + return ( + + ); +} NotYetMigratedMultipleDroppedAndInvitedMembers.story = { name: 'Not yet migrated, multiple dropped and invited members', }; -export const NotYetMigratedNoMembers = (): JSX.Element => { +export function NotYetMigratedNoMembers(): JSX.Element { return ( { })} /> ); -}; +} NotYetMigratedNoMembers.story = { name: 'Not yet migrated, no members', }; -export const NotYetMigratedJustDroppedMember = (): JSX.Element => { +export function NotYetMigratedJustDroppedMember(): JSX.Element { return ( { })} /> ); -}; +} NotYetMigratedJustDroppedMember.story = { name: 'Not yet migrated, just dropped member', diff --git a/ts/components/GroupV1MigrationDialog.tsx b/ts/components/GroupV1MigrationDialog.tsx index 96ae9dabae..41623fb977 100644 --- a/ts/components/GroupV1MigrationDialog.tsx +++ b/ts/components/GroupV1MigrationDialog.tsx @@ -28,7 +28,7 @@ export type HousekeepingPropsType = { export type PropsType = DataPropsType & HousekeepingPropsType; export const GroupV1MigrationDialog: React.FunctionComponent = - React.memo((props: PropsType) => { + React.memo(function GroupV1MigrationDialogInner(props: PropsType) { const { areWeInvited, droppedMembers, diff --git a/ts/components/GroupV2JoinDialog.stories.tsx b/ts/components/GroupV2JoinDialog.stories.tsx index 5817056b65..ab05156166 100644 --- a/ts/components/GroupV2JoinDialog.stories.tsx +++ b/ts/components/GroupV2JoinDialog.stories.tsx @@ -30,11 +30,11 @@ export default { title: 'Components/GroupV2JoinDialog', }; -export const Basic = (): JSX.Element => { +export function Basic(): JSX.Element { return ; -}; +} -export const ApprovalRequired = (): JSX.Element => { +export function ApprovalRequired(): JSX.Element { return ( { })} /> ); -}; +} ApprovalRequired.story = { name: 'Approval required', }; -export const WithAvatar = (): JSX.Element => { +export function WithAvatar(): JSX.Element { return ( { })} /> ); -}; +} WithAvatar.story = { name: 'With avatar', }; -export const WithOneMember = (): JSX.Element => { +export function WithOneMember(): JSX.Element { return ( { })} /> ); -}; +} WithOneMember.story = { name: 'With one member', }; -export const AvatarLoadingState = (): JSX.Element => { +export function AvatarLoadingState(): JSX.Element { return ( { })} /> ); -}; +} AvatarLoadingState.story = { name: 'Avatar loading state', }; -export const Full = (): JSX.Element => { +export function Full(): JSX.Element { return ( { })} /> ); -}; +} diff --git a/ts/components/GroupV2JoinDialog.tsx b/ts/components/GroupV2JoinDialog.tsx index 4cba90ee59..90e5a9655a 100644 --- a/ts/components/GroupV2JoinDialog.tsx +++ b/ts/components/GroupV2JoinDialog.tsx @@ -30,7 +30,9 @@ function focusRef(el: HTMLElement | null) { } } -export const GroupV2JoinDialog = React.memo((props: PropsType) => { +export const GroupV2JoinDialog = React.memo(function GroupV2JoinDialogInner( + props: PropsType +) { const [isWorking, setIsWorking] = React.useState(false); const [isJoining, setIsJoining] = React.useState(false); const { diff --git a/ts/components/IdenticonSVG.stories.tsx b/ts/components/IdenticonSVG.stories.tsx index 61cf0bcb25..7c564b77e1 100644 --- a/ts/components/IdenticonSVG.stories.tsx +++ b/ts/components/IdenticonSVG.stories.tsx @@ -10,7 +10,7 @@ export default { title: 'Components/IdenticonSVG', }; -export const AllColors = (): JSX.Element => { +export function AllColors(): JSX.Element { const stories: Array = []; AvatarColorMap.forEach(value => @@ -24,4 +24,4 @@ export const AllColors = (): JSX.Element => { ); return <>{stories}; -}; +} diff --git a/ts/components/InContactsIcon.stories.tsx b/ts/components/InContactsIcon.stories.tsx index bfe5bc28c9..5c5acb6323 100644 --- a/ts/components/InContactsIcon.stories.tsx +++ b/ts/components/InContactsIcon.stories.tsx @@ -13,6 +13,6 @@ export default { title: 'Components/InContactsIcon', }; -export const Default = (): JSX.Element => { +export function Default(): JSX.Element { return ; -}; +} diff --git a/ts/components/InContactsIcon.tsx b/ts/components/InContactsIcon.tsx index 42e9b3e2b4..7edc918889 100644 --- a/ts/components/InContactsIcon.tsx +++ b/ts/components/InContactsIcon.tsx @@ -13,7 +13,7 @@ type PropsType = { i18n: LocalizerType; }; -export const InContactsIcon = (props: PropsType): JSX.Element => { +export function InContactsIcon(props: PropsType): JSX.Element { const { className, i18n, tooltipContainerRef } = props; /* eslint-disable jsx-a11y/no-noninteractive-tabindex */ @@ -38,4 +38,4 @@ export const InContactsIcon = (props: PropsType): JSX.Element => { ); /* eslint-enable jsx-a11y/no-noninteractive-tabindex */ -}; +} diff --git a/ts/components/Inbox.tsx b/ts/components/Inbox.tsx index d45e53fad9..cac22b2251 100644 --- a/ts/components/Inbox.tsx +++ b/ts/components/Inbox.tsx @@ -30,7 +30,7 @@ export type PropsType = { showWhatsNewModal: () => unknown; }; -export const Inbox = ({ +export function Inbox({ hasInitialLoadCompleted, i18n, isCustomizingPreferredReactions, @@ -41,7 +41,7 @@ export const Inbox = ({ selectedMessageSource, showConversation, showWhatsNewModal, -}: PropsType): JSX.Element => { +}: PropsType): JSX.Element { const [loadingMessageCount, setLoadingMessageCount] = useState(0); const [internalHasInitialLoadCompleted, setInternalHasInitialLoadCompleted] = useState(hasInitialLoadCompleted); @@ -250,4 +250,4 @@ export const Inbox = ({ {activeModal} ); -}; +} diff --git a/ts/components/IncomingCallBar.stories.tsx b/ts/components/IncomingCallBar.stories.tsx index 13808d6889..e07c364251 100644 --- a/ts/components/IncomingCallBar.stories.tsx +++ b/ts/components/IncomingCallBar.stories.tsx @@ -55,109 +55,123 @@ export default { title: 'Components/IncomingCallBar', }; -export const IncomingDirectCallVideo = (): JSX.Element => ( - -); +export function IncomingDirectCallVideo(): JSX.Element { + return ( + + ); +} IncomingDirectCallVideo.story = { name: 'Incoming direct call (video)', }; -export const IncomingDirectCallAudio = (): JSX.Element => ( - -); +export function IncomingDirectCallAudio(): JSX.Element { + return ( + + ); +} IncomingDirectCallAudio.story = { name: 'Incoming direct call (audio)', }; -export const IncomingGroupCallOnlyCallingYou = (): JSX.Element => ( - -); +export function IncomingGroupCallOnlyCallingYou(): JSX.Element { + return ( + + ); +} IncomingGroupCallOnlyCallingYou.story = { name: 'Incoming group call (only calling you)', }; -export const IncomingGroupCallCallingYouAnd1Other = (): JSX.Element => ( - -); +export function IncomingGroupCallCallingYouAnd1Other(): JSX.Element { + return ( + + ); +} IncomingGroupCallCallingYouAnd1Other.story = { name: 'Incoming group call (calling you and 1 other)', }; -export const IncomingGroupCallCallingYouAnd2Others = (): JSX.Element => ( - -); +export function IncomingGroupCallCallingYouAnd2Others(): JSX.Element { + return ( + + ); +} IncomingGroupCallCallingYouAnd2Others.story = { name: 'Incoming group call (calling you and 2 others)', }; -export const IncomingGroupCallCallingYouAnd3Others = (): JSX.Element => ( - -); +export function IncomingGroupCallCallingYouAnd3Others(): JSX.Element { + return ( + + ); +} IncomingGroupCallCallingYouAnd3Others.story = { name: 'Incoming group call (calling you and 3 others)', }; -export const IncomingGroupCallCallingYouAnd4Others = (): JSX.Element => ( - -); +export function IncomingGroupCallCallingYouAnd4Others(): JSX.Element { + return ( + + ); +} IncomingGroupCallCallingYouAnd4Others.story = { name: 'Incoming group call (calling you and 4 others)', diff --git a/ts/components/IncomingCallBar.tsx b/ts/components/IncomingCallBar.tsx index 6832c6c241..297582a607 100644 --- a/ts/components/IncomingCallBar.tsx +++ b/ts/components/IncomingCallBar.tsx @@ -61,12 +61,12 @@ type CallButtonProps = { onClick: () => void; }; -const CallButton = ({ +function CallButton({ classSuffix, onClick, tabIndex, tooltipContent, -}: CallButtonProps): JSX.Element => { +}: CallButtonProps): JSX.Element { return (