Porównaj commity

...

5 Commity

Autor SHA1 Wiadomość Data
Alex Gleason f80ac02101
Merge remote-tracking branch 'origin/develop' into chats-fixes 2022-06-13 21:22:37 -05:00
Alex Gleason 29cb50b957
ChatRoom: convert to TSX 2022-06-11 13:02:54 -05:00
Alex Gleason 8f48e35e41
Merge remote-tracking branch 'origin/develop' into chats-fixes 2022-06-11 12:37:51 -05:00
Alex Gleason 0f14bbb170
Merge remote-tracking branch 'origin/develop' into chats-fixes 2022-06-07 15:32:38 -05:00
Alex Gleason a5c0c92f39
ChatPane WIP component 2022-06-07 10:21:31 -05:00
3 zmienionych plików z 117 dodań i 95 usunięć

Wyświetl plik

@ -1,95 +0,0 @@
import { Map as ImmutableMap } from 'immutable';
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 { fetchChat, markChatRead } from 'soapbox/actions/chats';
import { Column } from 'soapbox/components/ui';
import { makeGetChat } from 'soapbox/selectors';
import { getAcct } from 'soapbox/utils/accounts';
import { displayFqn } from 'soapbox/utils/state';
import ChatBox from './components/chat_box';
const mapStateToProps = (state, { params }) => {
const getChat = makeGetChat();
const chat = state.getIn(['chats', 'items', params.chatId], ImmutableMap()).toJS();
return {
me: state.get('me'),
chat: getChat(state, chat),
displayFqn: displayFqn(state),
};
};
export default @connect(mapStateToProps)
@injectIntl
class ChatRoom extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
chat: ImmutablePropTypes.map,
displayFqn: PropTypes.bool,
me: PropTypes.node,
}
handleInputRef = (el) => {
this.inputElem = el;
this.focusInput();
};
focusInput = () => {
if (!this.inputElem) return;
this.inputElem.focus();
}
markRead = () => {
const { dispatch, chat } = this.props;
if (!chat) return;
dispatch(markChatRead(chat.get('id')));
}
componentDidMount() {
const { dispatch, params } = this.props;
dispatch(fetchChat(params.chatId));
this.markRead();
}
componentDidUpdate(prevProps) {
const markReadConditions = [
() => this.props.chat,
() => this.props.chat.get('unread') > 0,
];
if (markReadConditions.every(c => c()))
this.markRead();
}
render() {
const { chat, displayFqn } = this.props;
if (!chat) return null;
const account = chat.get('account');
return (
<Column label={`@${getAcct(account, displayFqn)}`}>
{/* <div className='chatroom__back'>
<Link to={`/@${account.get('acct')}`} className='chatroom__header'>
<Avatar account={account} size={18} />
<div className='chatroom__title'>
@{getAcct(account, displayFqn)}
</div>
</Link>
</div> */}
<ChatBox
chatId={chat.get('id')}
onSetInputRef={this.handleInputRef}
/>
</Column>
);
}
}

Wyświetl plik

@ -0,0 +1,75 @@
import { Map as ImmutableMap } from 'immutable';
import React, { useEffect, useRef } from 'react';
import { fetchChat, markChatRead } from 'soapbox/actions/chats';
import { Column } 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 './components/chat_box';
const getChat = makeGetChat();
interface IChatRoom {
params: {
chatId: string,
}
}
const ChatRoom: React.FC<IChatRoom> = ({ params }) => {
const dispatch = useAppDispatch();
const displayFqn = useAppSelector(getDisplayFqn);
const chat = useAppSelector(state => {
const chat = state.chats.items.get(params.chatId, ImmutableMap()).toJS();
return getChat(state, chat as any);
});
const inputElem = useRef<HTMLInputElement | null>(null);
const handleInputRef = (el: HTMLInputElement) => {
inputElem.current = el;
focusInput();
};
const focusInput = () => {
inputElem.current?.focus();
};
const markRead = () => {
if (chat) {
dispatch(markChatRead(chat.id));
}
};
useEffect(() => {
dispatch(fetchChat(params.chatId));
markRead();
}, []);
useEffect(() => {
const markReadConditions = [
() => chat,
() => chat ? chat.unread > 0 : false,
];
if (markReadConditions.every(c => c()))
markRead();
});
if (!chat) return null;
const { account } = chat;
return (
<Column label={`@${getAcct(account as any, displayFqn)}`}>
<ChatBox
chatId={chat.id}
onSetInputRef={handleInputRef}
/>
</Column>
);
};
export default ChatRoom;

Wyświetl plik

@ -0,0 +1,42 @@
import React from 'react';
import { IconButton } from 'soapbox/components/ui';
interface IChatPaneHeader {
onClose?: () => void,
children: React.ReactNode,
}
const ChatPaneHeader: React.FC<IChatPaneHeader> = ({ onClose, children }) => {
return (
<div className='pane__header'>
{children}
<div className='pane__close'>
<IconButton src={require('@tabler/icons/icons/x.svg')} title='Close chat' onClick={onClose} />
</div>
</div>
);
};
interface IChatPane {
header: React.ReactNode,
children: React.ReactNode,
}
/** UI for a floating desktop chat. */
const ChatPane: React.FC<IChatPane> = ({ header, children }) => {
return (
<div className='flex flex-col shadow-md rounded-t-md fixed bottom-0 right-5 w-[256px] h-[350px] z-[1000]'>
<ChatPaneHeader>
{header}
</ChatPaneHeader>
<div className='pane__content'>
{children}
</div>
</div>
);
};
export default ChatPane;