0

Add support for disabled chat state in the chat input field. Closes #2761

This commit is contained in:
Gabe Kangas 2023-03-01 16:19:02 -08:00
parent de71984d46
commit 4a0476b237
No known key found for this signature in database
GPG Key ID: 4345B2060657F330
9 changed files with 76 additions and 22 deletions

View File

@ -593,6 +593,18 @@ Example.args = {
chatUserId: 'testuser', chatUserId: 'testuser',
isModerator: true, isModerator: true,
showInput: true, showInput: true,
chatAvailable: true,
};
export const ChatDisabled = Template.bind({});
ChatDisabled.args = {
loading: false,
messages,
usernameToHighlight: 'testuser',
chatUserId: 'testuser',
isModerator: true,
showInput: true,
chatAvailable: false,
}; };
export const SingleMessage = Template.bind({}); export const SingleMessage = Template.bind({});
@ -603,4 +615,5 @@ SingleMessage.args = {
chatUserId: 'testuser', chatUserId: 'testuser',
isModerator: true, isModerator: true,
showInput: true, showInput: true,
chatAvailable: true,
}; };

View File

@ -25,6 +25,7 @@ export type ChatContainerProps = {
isModerator: boolean; isModerator: boolean;
showInput?: boolean; showInput?: boolean;
height?: string; height?: string;
chatAvailable: boolean;
}; };
function shouldCollapseMessages( function shouldCollapseMessages(
@ -92,6 +93,7 @@ export const ChatContainer: FC<ChatContainerProps> = ({
isModerator, isModerator,
showInput, showInput,
height, height,
chatAvailable: chatEnabled,
}) => { }) => {
const [showScrollToBottomButton, setShowScrollToBottomButton] = useState(false); const [showScrollToBottomButton, setShowScrollToBottomButton] = useState(false);
const [isAtBottom, setIsAtBottom] = useState(false); const [isAtBottom, setIsAtBottom] = useState(false);
@ -284,7 +286,7 @@ export const ChatContainer: FC<ChatContainerProps> = ({
{MessagesTable} {MessagesTable}
{showInput && ( {showInput && (
<div className={styles.chatTextField}> <div className={styles.chatTextField}>
<ChatTextField /> <ChatTextField enabled={chatEnabled} />
</div> </div>
)} )}
</div> </div>

View File

@ -58,9 +58,13 @@ const Template: ComponentStory<typeof ChatTextField> = args => (
); );
export const Example = Template.bind({}); export const Example = Template.bind({});
Example.args = {
enabled: true,
};
export const LongerMessage = Template.bind({}); export const LongerMessage = Template.bind({});
LongerMessage.args = { LongerMessage.args = {
enabled: true,
defaultText: defaultText:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
}; };
@ -72,3 +76,16 @@ LongerMessage.parameters = {
}, },
}, },
}; };
export const DisabledChat = Template.bind({});
DisabledChat.args = {
enabled: false,
};
DisabledChat.parameters = {
docs: {
description: {
story: 'Should not allow you to type anything and should state that chat is disabled.',
},
},
};

View File

@ -122,11 +122,12 @@ const getCharacterCount = node => {
export type ChatTextFieldProps = { export type ChatTextFieldProps = {
defaultText?: string; defaultText?: string;
enabled: boolean;
}; };
const characterLimit = 300; const characterLimit = 300;
export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText }) => { export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText, enabled }) => {
const [showEmojis, setShowEmojis] = useState(false); const [showEmojis, setShowEmojis] = useState(false);
const [characterCount, setCharacterCount] = useState(defaultText?.length); const [characterCount, setCharacterCount] = useState(defaultText?.length);
const websocketService = useRecoilValue<WebsocketService>(websocketServiceAtom); const websocketService = useRecoilValue<WebsocketService>(websocketServiceAtom);
@ -241,8 +242,10 @@ export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText }) => {
className="chat-text-input" className="chat-text-input"
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
onPaste={onPaste} onPaste={onPaste}
disabled={!enabled}
readOnly={!enabled}
renderElement={renderElement} renderElement={renderElement}
placeholder="Send a message to chat" placeholder={enabled ? 'Send a message to chat' : 'Chat is currently unavailable.'}
style={{ width: '100%' }} style={{ width: '100%' }}
role="textbox" role="textbox"
aria-label="Chat text input" aria-label="Chat text input"
@ -262,6 +265,7 @@ export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText }) => {
/> />
</Slate> </Slate>
{enabled && (
<div style={{ display: 'flex', paddingLeft: '5px' }}> <div style={{ display: 'flex', paddingLeft: '5px' }}>
<button <button
type="button" type="button"
@ -280,6 +284,7 @@ export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText }) => {
<SendOutlined /> <SendOutlined />
</button> </button>
</div> </div>
)}
</div> </div>
</div> </div>
); );

View File

@ -293,6 +293,7 @@ export const Content: FC = () => {
notifyItemSelected={() => setShowNotifyModal(true)} notifyItemSelected={() => setShowNotifyModal(true)}
followItemSelected={() => setShowFollowModal(true)} followItemSelected={() => setShowFollowModal(true)}
externalActionSelected={externalActionSelected} externalActionSelected={externalActionSelected}
chatEnabled={isChatAvailable}
/> />
) : ( ) : (
<DesktopContent <DesktopContent

View File

@ -25,6 +25,7 @@ export type MobileContentProps = {
messages: ChatMessage[]; messages: ChatMessage[];
currentUser: CurrentUser; currentUser: CurrentUser;
showChat: boolean; showChat: boolean;
chatEnabled: boolean;
actions: ExternalAction[]; actions: ExternalAction[];
externalActionSelected: (action: ExternalAction) => void; externalActionSelected: (action: ExternalAction) => void;
supportsBrowserNotifications: boolean; supportsBrowserNotifications: boolean;
@ -62,6 +63,7 @@ export const MobileContent: FC<MobileContentProps> = ({
messages, messages,
currentUser, currentUser,
showChat, showChat,
chatEnabled,
actions, actions,
setExternalActionToDisplay, setExternalActionToDisplay,
setShowNotifyPopup, setShowNotifyPopup,
@ -80,6 +82,7 @@ export const MobileContent: FC<MobileContentProps> = ({
usernameToHighlight={displayName} usernameToHighlight={displayName}
chatUserId={id} chatUserId={id}
isModerator={false} isModerator={false}
chatAvailable={chatEnabled}
/> />
); );

View File

@ -5,7 +5,11 @@ import dynamic from 'next/dynamic';
import { ChatMessage } from '../../../interfaces/chat-message.model'; import { ChatMessage } from '../../../interfaces/chat-message.model';
import styles from './Sidebar.module.scss'; import styles from './Sidebar.module.scss';
import { currentUserAtom, visibleChatMessagesSelector } from '../../stores/ClientConfigStore'; import {
currentUserAtom,
visibleChatMessagesSelector,
isChatAvailableSelector,
} from '../../stores/ClientConfigStore';
// Lazy loaded components // Lazy loaded components
const ChatContainer = dynamic( const ChatContainer = dynamic(
@ -18,6 +22,8 @@ const ChatContainer = dynamic(
export const Sidebar: FC = () => { export const Sidebar: FC = () => {
const currentUser = useRecoilValue(currentUserAtom); const currentUser = useRecoilValue(currentUserAtom);
const messages = useRecoilValue<ChatMessage[]>(visibleChatMessagesSelector); const messages = useRecoilValue<ChatMessage[]>(visibleChatMessagesSelector);
const isChatAvailable = useRecoilValue(isChatAvailableSelector);
if (!currentUser) { if (!currentUser) {
return <Sider className={styles.root} collapsedWidth={0} width={320} />; return <Sider className={styles.root} collapsedWidth={0} width={320} />;
} }
@ -30,6 +36,7 @@ export const Sidebar: FC = () => {
usernameToHighlight={displayName} usernameToHighlight={displayName}
chatUserId={id} chatUserId={id}
isModerator={isModerator} isModerator={isModerator}
chatAvailable={isChatAvailable}
/> />
</Sider> </Sider>
); );

View File

@ -5,11 +5,13 @@ import {
ClientConfigStore, ClientConfigStore,
currentUserAtom, currentUserAtom,
visibleChatMessagesSelector, visibleChatMessagesSelector,
isChatAvailableSelector,
} from '../../../../components/stores/ClientConfigStore'; } from '../../../../components/stores/ClientConfigStore';
export default function ReadOnlyChatEmbed() { export default function ReadOnlyChatEmbed() {
const currentUser = useRecoilValue(currentUserAtom); const currentUser = useRecoilValue(currentUserAtom);
const messages = useRecoilValue<ChatMessage[]>(visibleChatMessagesSelector); const messages = useRecoilValue<ChatMessage[]>(visibleChatMessagesSelector);
const isChatAvailable = useRecoilValue(isChatAvailableSelector);
return ( return (
<div> <div>
@ -22,6 +24,7 @@ export default function ReadOnlyChatEmbed() {
isModerator={false} isModerator={false}
showInput={false} showInput={false}
height="100vh" height="100vh"
chatAvailable={isChatAvailable}
/> />
)} )}
</div> </div>

View File

@ -8,6 +8,7 @@ import {
clientConfigStateAtom, clientConfigStateAtom,
appStateAtom, appStateAtom,
serverStatusState, serverStatusState,
isChatAvailableSelector,
} from '../../../../components/stores/ClientConfigStore'; } from '../../../../components/stores/ClientConfigStore';
import Header from '../../../../components/ui/Header/Header'; import Header from '../../../../components/ui/Header/Header';
import { ClientConfig } from '../../../../interfaces/client-config.model'; import { ClientConfig } from '../../../../interfaces/client-config.model';
@ -21,6 +22,7 @@ export default function ReadWriteChatEmbed() {
const clientStatus = useRecoilValue<ServerStatus>(serverStatusState); const clientStatus = useRecoilValue<ServerStatus>(serverStatusState);
const appState = useRecoilValue<AppStateOptions>(appStateAtom); const appState = useRecoilValue<AppStateOptions>(appStateAtom);
const isChatAvailable = useRecoilValue(isChatAvailableSelector);
const { name, chatDisabled } = clientConfig; const { name, chatDisabled } = clientConfig;
const { videoAvailable } = appState; const { videoAvailable } = appState;
@ -41,6 +43,7 @@ export default function ReadWriteChatEmbed() {
isModerator={currentUser.isModerator} isModerator={currentUser.isModerator}
showInput showInput
height="80vh" height="80vh"
chatAvailable={isChatAvailable}
/> />
</div> </div>
)} )}