* feat(typing-indicator): wire up handleMessageChange
* feat(typing-indicator): send typing: true status
* feat(typing-indicator): expire typing state
* feat(typing-indicator): update typing state received from peers
* refactor(shell): add updatePeer utility
* feat(typing-indicator): display peer typing status
* feat(typing-indicator): reset typing status when a message is sent
* feat(typing-indicator): move indicator below message form
* feat(typing-indicator): keep status text to one line
* feat: add Username component
* feat: set custom username state
* feat: update custom username on input blur
* feat: inform peers of username updates
* feat: display username for peers
* feat: show static name in parentheses
* feat: use display name in message notification
* feat: remove username display from Shell Drawer
* feat: persist customUsername
* refactor: pass inline media upload data to useRoom
* feat: render inline media
* fix: don't rescind inline media file offers
* refactor: send file offer metadata object
* fix: enable re-seeding of inline media files
* feat: show loading indicator for inline media
* feat: rescind any evicted inline media
* feat: display media rendering failure message
* feat: prevent user from uploading file if message is sending
* feat: [#21] stand up file sharing controls UI
* feat: [#21] implement basic file transfer
* feat: [#21] save transferred file
* feat: [#21] transfer file via WebTorrent
* fix: use external streamsaver assets
* feat: [#21] initiate download by receiver click
* fix: enable re-downloading of shared files
* feat: [#21] implement sharing of multiple files
* chore: enable offline development
* feat: cache torrents in IndexedDB
* feat: show alert when download is aborted
* feat: [#21] clean up torrent data when principal offerer rescinds it
* feat: clean up cached torrents on page unload
* feat: show file transfer progress
* fix: download files sequentially
* feat: clean up file transfers when leaving the room
* feat: clean up broken downloads upon leaving the page
* fix: allow download animation to complete
* feat: show tooltip for download button
* feat: make file transfers work in browser private modes
* feat: disable file share controls while creating offer
* refactor: nest ChatTranscript
* feat: set up video controls
* feat: show self video
* feat: show peer video
* feat: improve audio/video controls display
* feat: flip self video
* feat: improve device selection labels
* feat: [#6] show notification when message is received
* feat: [#6] add setting for enabling/disabling notifications
* refactor: [#6] decouple PeerNameDisplay from funAnimalName
* feat: [#6] disable notifications setting when notifications are unavailable
* feat: [#7] Play a sound on new message
* fix: [#7] Since this mock is a no-op, I think we can omit the argument to mockImplementation
Co-authored-by: Jeremy Kahn <jeremyckahn@gmail.com>
* fix: [#7] lazy initialization of this state
Co-authored-by: Jeremy Kahn <jeremyckahn@gmail.com>
* fix: [#7] More accurate error message
Co-authored-by: Jeremy Kahn <jeremyckahn@gmail.com>
* fix: [#7] Replace then with await
* [closes#24] Settings UI (#26)
* feat: [#24] wire up settings page
* feat: [#24] stand up settings UI
* feat: [#24] implement storage deletion
* feat: [#24] confirm deletion of settings data
* feat: [#7] Add play sound switch in settings
* feat: [#7] avoid typescript warning
Co-authored-by: Jeremy Kahn <jeremyckahn@gmail.com>
* feat: [#7] more straighforward wording
Co-authored-by: Jeremy Kahn <jeremyckahn@gmail.com>
* feat: [#7] remove useless usestate
* feat: [#7] avoid new settings to be undefined in persisted storage
* feat: [#7] creating a chat section in settings
Co-authored-by: Jeremy Kahn <jeremyckahn@gmail.com>