From 6459096b58664b533c03bb27a4d127ea57042fd8 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Fri, 17 Jun 2022 14:39:53 -0500 Subject: [PATCH] ChatWindow: convert to TSX --- app/soapbox/components/hover_ref_wrapper.tsx | 2 +- .../features/chats/components/chat_window.js | 135 ------------------ .../features/chats/components/chat_window.tsx | 113 +++++++++++++++ 3 files changed, 114 insertions(+), 136 deletions(-) delete mode 100644 app/soapbox/features/chats/components/chat_window.js create mode 100644 app/soapbox/features/chats/components/chat_window.tsx diff --git a/app/soapbox/components/hover_ref_wrapper.tsx b/app/soapbox/components/hover_ref_wrapper.tsx index bf4e253f2..2090543cc 100644 --- a/app/soapbox/components/hover_ref_wrapper.tsx +++ b/app/soapbox/components/hover_ref_wrapper.tsx @@ -15,7 +15,7 @@ const showProfileHoverCard = debounce((dispatch, ref, accountId) => { interface IHoverRefWrapper { accountId: string, - inline: boolean, + inline?: boolean, className?: string, } diff --git a/app/soapbox/features/chats/components/chat_window.js b/app/soapbox/features/chats/components/chat_window.js deleted file mode 100644 index e525e3432..000000000 --- a/app/soapbox/features/chats/components/chat_window.js +++ /dev/null @@ -1,135 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { injectIntl } from 'react-intl'; -import { connect } from 'react-redux'; -import { Link } from 'react-router-dom'; - -import { - closeChat, - toggleChat, -} from 'soapbox/actions/chats'; -import Avatar from 'soapbox/components/avatar'; -import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper'; -import IconButton from 'soapbox/components/icon_button'; -import { Counter } from 'soapbox/components/ui'; -import { makeGetChat } from 'soapbox/selectors'; -import { getAcct } from 'soapbox/utils/accounts'; -import { displayFqn } from 'soapbox/utils/state'; - -import ChatBox from './chat_box'; - -const makeMapStateToProps = () => { - const getChat = makeGetChat(); - - const mapStateToProps = (state, { chatId }) => { - const chat = state.getIn(['chats', 'items', chatId]); - - return { - me: state.get('me'), - chat: chat ? getChat(state, chat.toJS()) : undefined, - displayFqn: displayFqn(state), - }; - }; - - return mapStateToProps; -}; - -export default @connect(makeMapStateToProps) -@injectIntl -class ChatWindow extends ImmutablePureComponent { - - static propTypes = { - dispatch: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, - chatId: PropTypes.string.isRequired, - windowState: PropTypes.string.isRequired, - idx: PropTypes.number, - chat: ImmutablePropTypes.record, - me: PropTypes.node, - displayFqn: PropTypes.bool, - } - - state = { - content: '', - } - - handleChatClose = (chatId) => { - return (e) => { - this.props.dispatch(closeChat(chatId)); - }; - } - - handleChatToggle = (chatId) => { - return (e) => { - this.props.dispatch(toggleChat(chatId)); - }; - } - - handleContentChange = (e) => { - this.setState({ content: e.target.value }); - } - - handleInputRef = (el) => { - this.inputElem = el; - this.focusInput(); - }; - - focusInput = () => { - if (!this.inputElem) return; - this.inputElem.focus(); - } - - componentDidUpdate(prevProps) { - const oldState = prevProps.windowState; - const newState = this.props.windowState; - - if (oldState !== newState && newState === 'open') - this.focusInput(); - } - - render() { - const { windowState, idx, chat, displayFqn } = this.props; - if (!chat) return null; - const account = chat.get('account'); - - const right = (285 * (idx + 1)) + 20; - const unreadCount = chat.get('unread'); - - const unreadIcon = ( -
- -
- ); - - const avatar = ( - - - - - - ); - - return ( -
-
- {unreadCount > 0 ? unreadIcon : avatar } - -
- -
-
-
- -
-
- ); - } - -} diff --git a/app/soapbox/features/chats/components/chat_window.tsx b/app/soapbox/features/chats/components/chat_window.tsx new file mode 100644 index 000000000..aecdca180 --- /dev/null +++ b/app/soapbox/features/chats/components/chat_window.tsx @@ -0,0 +1,113 @@ +import React, { useEffect, useRef } from 'react'; +import { Link } from 'react-router-dom'; + +import { + closeChat, + toggleChat, +} from 'soapbox/actions/chats'; +import Avatar from 'soapbox/components/avatar'; +import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper'; +import IconButton from 'soapbox/components/icon_button'; +import { Counter } from 'soapbox/components/ui'; +import { useAppSelector, useAppDispatch } from 'soapbox/hooks'; +import { makeGetChat } from 'soapbox/selectors'; +import { getAcct } from 'soapbox/utils/accounts'; +import { displayFqn as getDisplayFqn } from 'soapbox/utils/state'; + +import ChatBox from './chat_box'; + +import type { Account as AccountEntity } from 'soapbox/types/entities'; + +type WindowState = 'open' | 'minimized'; + +const getChat = makeGetChat(); + +interface IChatWindow { + /** Position of the chat window on the screen, where 0 is rightmost. */ + idx: number, + /** ID of the chat entity. */ + chatId: string, + /** Whether the window is open or minimized. */ + windowState: WindowState, +} + +/** Floating desktop chat window. */ +const ChatWindow: React.FC = ({ idx, chatId, windowState }) => { + const dispatch = useAppDispatch(); + + const displayFqn = useAppSelector(getDisplayFqn); + + const chat = useAppSelector(state => { + const chat = state.chats.items.get(chatId); + return chat ? getChat(state, chat.toJS() as any) : undefined; + }); + + const inputElem = useRef(null); + + const handleChatClose = (chatId: string) => { + return () => { + dispatch(closeChat(chatId)); + }; + }; + + const handleChatToggle = (chatId: string) => { + return () => { + dispatch(toggleChat(chatId)); + }; + }; + + const handleInputRef = (el: HTMLTextAreaElement) => { + inputElem.current = el; + focusInput(); + }; + + const focusInput = () => { + inputElem.current?.focus(); + }; + + useEffect(() => { + focusInput(); + }, [windowState === 'open']); + + if (!chat) return null; + const account = chat.account as unknown as AccountEntity; + + const right = (285 * (idx + 1)) + 20; + const unreadCount = chat.unread; + + const unreadIcon = ( +
+ +
+ ); + + const avatar = ( + + + + + + ); + + return ( +
+
+ {unreadCount > 0 ? unreadIcon : avatar } + +
+ +
+
+
+ +
+
+ ); +}; + +export default ChatWindow;