forked from Shiloh/remnantchat
feat(typing-indicator): add setting to disable typing indicator
This commit is contained in:
parent
e597a667a1
commit
3413f37d8c
@ -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,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
@ -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 () => {
|
||||||
|
@ -15,5 +15,6 @@ export const SettingsContext = createContext<SettingsContextProps>({
|
|||||||
colorMode: 'dark',
|
colorMode: 'dark',
|
||||||
playSoundOnNewMessage: true,
|
playSoundOnNewMessage: true,
|
||||||
showNotificationOnNewMessage: true,
|
showNotificationOnNewMessage: true,
|
||||||
|
showActiveTypingStatus: true,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -4,4 +4,5 @@ export interface UserSettings {
|
|||||||
customUsername: string
|
customUsername: string
|
||||||
playSoundOnNewMessage: boolean
|
playSoundOnNewMessage: boolean
|
||||||
showNotificationOnNewMessage: boolean
|
showNotificationOnNewMessage: boolean
|
||||||
|
showActiveTypingStatus: boolean
|
||||||
}
|
}
|
||||||
|
@ -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,30 +99,48 @@ export const Settings = ({ userId }: SettingsProps) => {
|
|||||||
>
|
>
|
||||||
Chat
|
Chat
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>When a message is received in the background:</Typography>
|
<Paper elevation={3} sx={{ p: 2, mb: 2 }}>
|
||||||
<FormGroup>
|
<Typography>When a message is received in the background:</Typography>
|
||||||
<FormControlLabel
|
<FormGroup>
|
||||||
control={
|
<FormControlLabel
|
||||||
<Switch
|
control={
|
||||||
checked={playSoundOnNewMessage}
|
<Switch
|
||||||
onChange={handlePlaySoundOnNewMessageChange}
|
checked={playSoundOnNewMessage}
|
||||||
/>
|
onChange={handlePlaySoundOnNewMessageChange}
|
||||||
}
|
/>
|
||||||
label="Play a sound"
|
}
|
||||||
/>
|
label="Play a sound"
|
||||||
<FormControlLabel
|
/>
|
||||||
control={
|
<FormControlLabel
|
||||||
<Switch
|
control={
|
||||||
checked={
|
<Switch
|
||||||
areNotificationsAvailable && showNotificationOnNewMessage
|
checked={
|
||||||
}
|
areNotificationsAvailable && showNotificationOnNewMessage
|
||||||
onChange={handleShowNotificationOnNewMessageChange}
|
}
|
||||||
disabled={!areNotificationsAvailable}
|
onChange={handleShowNotificationOnNewMessageChange}
|
||||||
/>
|
disabled={!areNotificationsAvailable}
|
||||||
}
|
/>
|
||||||
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"
|
||||||
|
@ -12,6 +12,7 @@ export const userSettingsContextStubFactory = (
|
|||||||
colorMode: 'dark',
|
colorMode: 'dark',
|
||||||
playSoundOnNewMessage: true,
|
playSoundOnNewMessage: true,
|
||||||
showNotificationOnNewMessage: true,
|
showNotificationOnNewMessage: true,
|
||||||
|
showActiveTypingStatus: true,
|
||||||
...userSettingsOverrides,
|
...userSettingsOverrides,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user