feat: persistent text input
This commit is contained in:
parent
5486103d78
commit
0a657c02d7
|
@ -1,10 +1,14 @@
|
|||
import './chat--messages.scss';
|
||||
|
||||
import React, {useRef, useState} from 'react';
|
||||
import React, {useRef} from 'react';
|
||||
import {useDispatch, useSelector} from 'react-redux';
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
|
||||
import {submitMessage} from '~/common/state/chat';
|
||||
import {
|
||||
inputChannelSelector,
|
||||
inputText,
|
||||
submitMessage,
|
||||
} from '~/common/state/chat';
|
||||
import {userSelector} from '~/common/state/user';
|
||||
|
||||
import useChannel from '~/client/hooks/useChannel';
|
||||
|
@ -14,7 +18,8 @@ export default function ChatSubmitMessage() {
|
|||
const dispatch = useDispatch();
|
||||
const $form = useRef(null);
|
||||
const user = useSelector(userSelector);
|
||||
const [text, setText] = useState('');
|
||||
const text = useSelector((state) => inputChannelSelector(state, channel));
|
||||
const setText = (text) => dispatch(inputText({channel, text}));
|
||||
return (
|
||||
<div className="chat--messageSubmit">
|
||||
<form
|
||||
|
@ -42,16 +47,14 @@ export default function ChatSubmitMessage() {
|
|||
className="chat--messagesTextarea"
|
||||
name="message"
|
||||
type="textarea"
|
||||
onChange={(event) => {
|
||||
setText(event.target.value);
|
||||
}}
|
||||
onChange={(event) => setText(event.target.value)}
|
||||
onKeyDown={(event) => {
|
||||
if ('Enter' === event.key && !event.shiftKey) {
|
||||
$form.current?.dispatchEvent(new Event('submit', {cancelable: true}));
|
||||
event.preventDefault();
|
||||
}
|
||||
}}
|
||||
value={text}
|
||||
value={text || ''}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -5,8 +5,14 @@ import {
|
|||
} from '@reduxjs/toolkit';
|
||||
|
||||
import hydration from './hydration';
|
||||
import storage from './storage';
|
||||
|
||||
export const channelsSelector = (state) => state.chat.channels;
|
||||
export const chatSelector = (state) => state.chat;
|
||||
|
||||
export const channelsSelector = createSelector(
|
||||
chatSelector,
|
||||
(chat) => chat.channels,
|
||||
);
|
||||
|
||||
export const channelSelector = createSelector(
|
||||
[channelsSelector, (_, channel) => channel],
|
||||
|
@ -18,7 +24,20 @@ export const channelUsersSelector = createSelector(
|
|||
(channel) => (channel ? channel.users : []),
|
||||
);
|
||||
|
||||
export const messagesSelector = (state) => state.chat.messages;
|
||||
export const inputSelector = createSelector(
|
||||
chatSelector,
|
||||
(chat) => chat.input,
|
||||
);
|
||||
|
||||
export const inputChannelSelector = createSelector(
|
||||
[inputSelector, (_, channel) => channel],
|
||||
(input, channel) => input[channel],
|
||||
);
|
||||
|
||||
export const messagesSelector = createSelector(
|
||||
chatSelector,
|
||||
(chat) => chat.messages,
|
||||
);
|
||||
|
||||
export const channelMessagesSelector = createSelector(
|
||||
[channelSelector, messagesSelector],
|
||||
|
@ -29,8 +48,10 @@ const slice = createSlice({
|
|||
name: 'chat',
|
||||
initialState: {
|
||||
channels: {},
|
||||
input: {},
|
||||
messages: {},
|
||||
...(hydration('chat') || {}),
|
||||
...(storage(chatSelector) || {}),
|
||||
},
|
||||
reducers: {
|
||||
addMessage: ({
|
||||
|
@ -56,6 +77,14 @@ const slice = createSlice({
|
|||
editMessage: ({messages}, {payload: {uuid, message}}) => {
|
||||
messages[uuid].message = message;
|
||||
},
|
||||
inputText: ({input}, {payload: {channel, text}}) => {
|
||||
if (!text) {
|
||||
delete input[channel];
|
||||
}
|
||||
else {
|
||||
input[channel] = text;
|
||||
}
|
||||
},
|
||||
join: ({channels, messages}, {payload: {channel, messages: channelMessages, users}}) => {
|
||||
channelMessages.forEach((message) => {
|
||||
messages[message.uuid] = message;
|
||||
|
@ -94,6 +123,7 @@ export const {
|
|||
addMessage,
|
||||
confirmMessage,
|
||||
editMessage,
|
||||
inputText,
|
||||
join,
|
||||
joined,
|
||||
leave,
|
||||
|
|
Loading…
Reference in New Issue
Block a user