feat(typing-indicator): add setting to disable typing indicator

This commit is contained in:
Jeremy Kahn 2023-07-28 09:50:03 -05:00
parent e597a667a1
commit 3413f37d8c
9 changed files with 81 additions and 32 deletions

View File

@ -57,6 +57,7 @@ test('persists user settings if none were already persisted', async () => {
customUsername: '', customUsername: '',
playSoundOnNewMessage: true, playSoundOnNewMessage: true,
showNotificationOnNewMessage: true, showNotificationOnNewMessage: true,
showActiveTypingStatus: true,
}) })
}) })

View File

@ -43,6 +43,7 @@ function Bootstrap({
colorMode: 'dark', colorMode: 'dark',
playSoundOnNewMessage: true, playSoundOnNewMessage: true,
showNotificationOnNewMessage: true, showNotificationOnNewMessage: true,
showActiveTypingStatus: true,
}) })
const { userId } = userSettings const { userId } = userSettings

View File

@ -1,6 +1,7 @@
import { import {
KeyboardEvent, KeyboardEvent,
SyntheticEvent, SyntheticEvent,
useContext,
useEffect, useEffect,
useRef, useRef,
useState, useState,
@ -12,6 +13,8 @@ import Fab from '@mui/material/Fab'
import ArrowUpward from '@mui/icons-material/ArrowUpward' import ArrowUpward from '@mui/icons-material/ArrowUpward'
import { messageCharacterSizeLimit } from 'config/messaging' import { messageCharacterSizeLimit } from 'config/messaging'
import { SettingsContext } from 'contexts/SettingsContext'
import classNames from 'classnames'
interface MessageFormProps { interface MessageFormProps {
onMessageSubmit: (message: string) => void onMessageSubmit: (message: string) => void
@ -24,6 +27,8 @@ export const MessageForm = ({
onMessageChange, onMessageChange,
isMessageSending, isMessageSending,
}: MessageFormProps) => { }: MessageFormProps) => {
const settingsContext = useContext(SettingsContext)
const { showActiveTypingStatus } = settingsContext.getUserSettings()
const textFieldRef = useRef<HTMLInputElement>(null) const textFieldRef = useRef<HTMLInputElement>(null)
const [textMessage, setTextMessage] = useState('') const [textMessage, setTextMessage] = useState('')
@ -71,7 +76,13 @@ export const MessageForm = ({
} }
return ( return (
<form onSubmit={handleMessageSubmit} className="pt-4 px-4"> <form
onSubmit={handleMessageSubmit}
className={classNames({
'pt-4 px-4': showActiveTypingStatus,
'p-4': !showActiveTypingStatus,
})}
>
<Stack direction="row" spacing={2}> <Stack direction="row" spacing={2}>
<FormControl fullWidth> <FormControl fullWidth>
<TextField <TextField

View File

@ -1,10 +1,7 @@
import { useContext } from 'react' import { useContext } from 'react'
import { useWindowSize } from '@react-hook/window-size' import { useWindowSize } from '@react-hook/window-size'
import Collapse from '@mui/material/Collapse' import Collapse from '@mui/material/Collapse'
import Zoom from '@mui/material/Zoom' import Zoom from '@mui/material/Zoom'
import Box from '@mui/material/Box' import Box from '@mui/material/Box'
import Divider from '@mui/material/Divider' import Divider from '@mui/material/Divider'
import { v4 as uuid } from 'uuid' import { v4 as uuid } from 'uuid'
@ -16,6 +13,8 @@ import { ShellContext } from 'contexts/ShellContext'
import { MessageForm } from 'components/MessageForm' import { MessageForm } from 'components/MessageForm'
import { ChatTranscript } from 'components/ChatTranscript' import { ChatTranscript } from 'components/ChatTranscript'
import { SettingsContext } from 'contexts/SettingsContext'
import { useRoom } from './useRoom' import { useRoom } from './useRoom'
import { RoomAudioControls } from './RoomAudioControls' import { RoomAudioControls } from './RoomAudioControls'
import { RoomVideoControls } from './RoomVideoControls' import { RoomVideoControls } from './RoomVideoControls'
@ -41,6 +40,8 @@ export function Room({
password, password,
userId, userId,
}: RoomProps) { }: RoomProps) {
const settingsContext = useContext(SettingsContext)
const { showActiveTypingStatus } = settingsContext.getUserSettings()
const { const {
isMessageSending, isMessageSending,
handleInlineMediaUpload, handleInlineMediaUpload,
@ -158,7 +159,7 @@ export function Room({
isMessageSending={isMessageSending} isMessageSending={isMessageSending}
onMessageChange={handleMessageChange} onMessageChange={handleMessageChange}
/> />
<TypingStatusBar /> {showActiveTypingStatus ? <TypingStatusBar /> : null}
</Box> </Box>
</Box> </Box>
)} )}

View File

@ -66,6 +66,7 @@ export function useRoom(
} = useContext(ShellContext) } = useContext(ShellContext)
const settingsContext = useContext(SettingsContext) const settingsContext = useContext(SettingsContext)
const { showActiveTypingStatus } = settingsContext.getUserSettings()
const [isMessageSending, setIsMessageSending] = useState(false) const [isMessageSending, setIsMessageSending] = useState(false)
const [messageLog, _setMessageLog] = useState<Array<Message | InlineMedia>>( const [messageLog, _setMessageLog] = useState<Array<Message | InlineMedia>>(
[] []
@ -164,8 +165,10 @@ export function useRoom(
) )
useEffect(() => { useEffect(() => {
if (!showActiveTypingStatus) return
sendTypingStatusChange({ isTyping }) sendTypingStatusChange({ isTyping })
}, [isTyping, sendTypingStatusChange]) }, [isTyping, sendTypingStatusChange, showActiveTypingStatus])
useEffect(() => { useEffect(() => {
return () => { return () => {

View File

@ -15,5 +15,6 @@ export const SettingsContext = createContext<SettingsContextProps>({
colorMode: 'dark', colorMode: 'dark',
playSoundOnNewMessage: true, playSoundOnNewMessage: true,
showNotificationOnNewMessage: true, showNotificationOnNewMessage: true,
showActiveTypingStatus: true,
}), }),
}) })

View File

@ -4,4 +4,5 @@ export interface UserSettings {
customUsername: string customUsername: string
playSoundOnNewMessage: boolean playSoundOnNewMessage: boolean
showNotificationOnNewMessage: boolean showNotificationOnNewMessage: boolean
showActiveTypingStatus: boolean
} }

View File

@ -6,6 +6,7 @@ import Divider from '@mui/material/Divider'
import Switch from '@mui/material/Switch' import Switch from '@mui/material/Switch'
import FormGroup from '@mui/material/FormGroup' import FormGroup from '@mui/material/FormGroup'
import FormControlLabel from '@mui/material/FormControlLabel' import FormControlLabel from '@mui/material/FormControlLabel'
import Paper from '@mui/material/Paper'
import { NotificationService } from 'services/Notification' import { NotificationService } from 'services/Notification'
import { ShellContext } from 'contexts/ShellContext' import { ShellContext } from 'contexts/ShellContext'
@ -28,8 +29,11 @@ export const Settings = ({ userId }: SettingsProps) => {
setIsDeleteSettingsConfirmDiaglogOpen, setIsDeleteSettingsConfirmDiaglogOpen,
] = useState(false) ] = useState(false)
const [, setIsNotificationPermissionDetermined] = useState(false) const [, setIsNotificationPermissionDetermined] = useState(false)
const { playSoundOnNewMessage, showNotificationOnNewMessage } = const {
getUserSettings() playSoundOnNewMessage,
showNotificationOnNewMessage,
showActiveTypingStatus,
} = getUserSettings()
const persistedStorage = getPersistedStorage() const persistedStorage = getPersistedStorage()
@ -61,6 +65,13 @@ export const Settings = ({ userId }: SettingsProps) => {
updateUserSettings({ showNotificationOnNewMessage }) updateUserSettings({ showNotificationOnNewMessage })
} }
const handleShowActiveTypingStatusChange = (
_event: ChangeEvent,
showActiveTypingStatus: boolean
) => {
updateUserSettings({ showActiveTypingStatus })
}
const handleDeleteSettingsClick = () => { const handleDeleteSettingsClick = () => {
setIsDeleteSettingsConfirmDiaglogOpen(true) setIsDeleteSettingsConfirmDiaglogOpen(true)
} }
@ -88,6 +99,7 @@ export const Settings = ({ userId }: SettingsProps) => {
> >
Chat Chat
</Typography> </Typography>
<Paper elevation={3} sx={{ p: 2, mb: 2 }}>
<Typography>When a message is received in the background:</Typography> <Typography>When a message is received in the background:</Typography>
<FormGroup> <FormGroup>
<FormControlLabel <FormControlLabel
@ -112,6 +124,23 @@ export const Settings = ({ userId }: SettingsProps) => {
label="Show a notification" label="Show a notification"
/> />
</FormGroup> </FormGroup>
</Paper>
<Paper elevation={3} sx={{ p: 2, mb: 2 }}>
<FormGroup>
<FormControlLabel
control={
<Switch
checked={showActiveTypingStatus}
onChange={handleShowActiveTypingStatusChange}
/>
}
label="Show active typing indicators"
/>
</FormGroup>
<Typography variant="subtitle2" sx={_theme => ({})}>
Disabling this will also hide your active typing status from others.
</Typography>
</Paper>
<Divider sx={{ my: 2 }} /> <Divider sx={{ my: 2 }} />
<Typography <Typography
variant="h2" variant="h2"

View File

@ -12,6 +12,7 @@ export const userSettingsContextStubFactory = (
colorMode: 'dark', colorMode: 'dark',
playSoundOnNewMessage: true, playSoundOnNewMessage: true,
showNotificationOnNewMessage: true, showNotificationOnNewMessage: true,
showActiveTypingStatus: true,
...userSettingsOverrides, ...userSettingsOverrides,
}), }),
} }