Require authentication to participate in chat (#4762)
* feat(chat): require authentication to participate in chat * fix: it's pretty much impossible to bypass the auth requirement, addressing review feedback anyway * feat(chat): render chat text input as disabled if chat auth is required * Commit updated API documentation --------- Co-authored-by: Owncast <owncast@owncast.online>
This commit is contained in:
@@ -618,6 +618,22 @@ export const ChatDisabled = {
|
||||
},
|
||||
};
|
||||
|
||||
export const AuthenticationRequired = {
|
||||
render: Template,
|
||||
|
||||
args: {
|
||||
loading: false,
|
||||
messages,
|
||||
usernameToHighlight: 'testuser',
|
||||
chatUserId: 'testuser',
|
||||
isModerator: false,
|
||||
showInput: true,
|
||||
chatAvailable: true,
|
||||
inputEnabled: false,
|
||||
inputDisabledPlaceholder: 'Authenticate to chat',
|
||||
},
|
||||
};
|
||||
|
||||
export const SingleMessage = {
|
||||
render: Template,
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ export type ChatContainerProps = {
|
||||
focusInput?: boolean;
|
||||
desktop?: boolean;
|
||||
readonly?: boolean;
|
||||
inputEnabled?: boolean;
|
||||
inputDisabledPlaceholder?: string;
|
||||
};
|
||||
|
||||
let resizeWindowCallback: () => void;
|
||||
@@ -82,11 +84,15 @@ export const ChatContainer: FC<ChatContainerProps> = ({
|
||||
isModerator,
|
||||
showInput = true,
|
||||
height = 'auto',
|
||||
chatAvailable: chatEnabled,
|
||||
chatAvailable,
|
||||
desktop,
|
||||
focusInput = true,
|
||||
readonly = false,
|
||||
inputEnabled,
|
||||
inputDisabledPlaceholder,
|
||||
}) => {
|
||||
// If inputEnabled is explicitly set, use that; otherwise fall back to chatAvailable
|
||||
const chatInputEnabled = inputEnabled !== undefined ? inputEnabled : chatAvailable;
|
||||
const [showScrollToBottomButton, setShowScrollToBottomButton] = useState(false);
|
||||
const [isAtBottom, setIsAtBottom] = useState(false);
|
||||
|
||||
@@ -366,7 +372,11 @@ export const ChatContainer: FC<ChatContainerProps> = ({
|
||||
{MessagesTable}
|
||||
{showInput && (
|
||||
<div className={styles.chatTextField}>
|
||||
<ChatTextField enabled={chatEnabled} focusInput={focusInput} />
|
||||
<ChatTextField
|
||||
enabled={chatInputEnabled}
|
||||
focusInput={focusInput}
|
||||
disabledPlaceholder={inputDisabledPlaceholder}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{desktop && (
|
||||
|
||||
@@ -30,6 +30,7 @@ export type ChatTextFieldProps = {
|
||||
defaultText?: string;
|
||||
enabled: boolean;
|
||||
focusInput: boolean;
|
||||
disabledPlaceholder?: string;
|
||||
};
|
||||
|
||||
const characterLimit = 300;
|
||||
@@ -119,7 +120,12 @@ const getTextContent = node => {
|
||||
return text;
|
||||
};
|
||||
|
||||
export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText, enabled, focusInput }) => {
|
||||
export const ChatTextField: FC<ChatTextFieldProps> = ({
|
||||
defaultText,
|
||||
enabled,
|
||||
focusInput,
|
||||
disabledPlaceholder,
|
||||
}) => {
|
||||
const [inputDraft, setInputDraft] = useRecoilState(chatInputDraftAtom);
|
||||
const [characterCount, setCharacterCount] = useState(defaultText?.length);
|
||||
const websocketService = useRecoilValue<WebsocketService>(websocketServiceAtom);
|
||||
@@ -276,7 +282,9 @@ export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText, enabled, fo
|
||||
<ContentEditable
|
||||
id="chat-input-content-editable"
|
||||
html={defaultText || ''}
|
||||
placeholder={enabled ? 'Send a message to chat' : 'Chat is disabled'}
|
||||
placeholder={
|
||||
enabled ? 'Send a message to chat' : disabledPlaceholder || 'Chat is disabled'
|
||||
}
|
||||
disabled={!enabled}
|
||||
onKeyDown={onKeyDown}
|
||||
onContentChange={handleChange}
|
||||
|
||||
Reference in New Issue
Block a user