* feat(ui): present mic volume icon
* feat(ui): improve mic volume display
* refactor(ui): nest mic audio as a channel
* fix(ui): prevent volume control from reappearing for returning peers
* refactor(audio): update specific audio channel states
* refactor(audio): use enum for audio channel name
* refactor(types): improve audio type names
* feat(audio): wire up screen share audio
* refactor(networking): always provide stream metadata
* fix(audio): remove screen audio when stream ends
* fix(audio): stop audio when removing it
* feat(audio): show appropriate icon for channel
* fix(audio): clean up audio for leaving peers consistently
* fix(audio): use up-to-date peerAudios reference
* refactor(audio): simplify audio state updating
* refactor(audio): use functional setState to update peer list
* refactor(variables): rename peerAudios to peerAudioChannels
* refactor(types): consolidate stream types
* refactor(types): require stream type metadata
* chore(vite): use vite
* fix(vite): alias lib directory
* chore(vite): set type: module
* chore: update vite and MUI
* fix(vite): make MUI components load
* fix: use node path resolution
* chore(vite): add svg support
* fix(vite): polyfill global
* fix(vite): use import.meta
* fix(vite): use correct svg module resolution
* chore(vite): migrate to vitest
* fix(vite): remove PUBLIC_URL
* fix(tests): mock audio service
* chore(deps): upgrade to react test library 14
* refactor(tests): simplify room test setup
* refactor(tests): make Date.now() mockable
* refactor(vite): remove bootstrap shim
* chore(deps): drop react-scripts
* chore(deps): remove source-map-explorer
Source maps do not currently work with MUI and Vite:
https://github.com/vitejs/vite/issues/15012
Because of this, source map utilities are currently removed.
* refactor(vite): use TypeScript for Vite config
* chore(actions): update actions config for new paths
* fix(service-worker): use VITE_HOMEPAGE for service worker resolution
* fix(vercel): use quotes for build command
* fix(vite): use import.meta.env.MODE
* fix(service-worker): use correct definition for publicUrl
* feat(vite): use vite-plugin-pwa
* fix(pwa): make update prompt work
* fix(types): use vite/client types
* docs(readme): update building instructions
* refactor(vite): simplify theme loading workaround
* refactor(vite): use manifest object
* docs(readme): update tool references
* chore(deps): run `npm audit fix`
* fix(vite): make syntax highlighter work consistently
See: https://github.com/react-syntax-highlighter/react-syntax-highlighter/issues/513
* fix(pwa): remove manifest.json references
* refactor(deps): remove jest references
* refactor(types): remove react-scripts reference
* chore(deps): use TypeScript 5
* refactor(tests): improve persisted storage mocking
* refactor(Notification): use instance methods
* refactor(Audio): move to lib layer
* refactor(EncryptionService): rename instance to encryption
* refactor(ConnectionTest): move to lib
* refactor(FileTransfer): move to lib
* refactor(PeerRoom): move to lib
* refactor(sleep): move to lib
* refactor(type-guards): move to lib
* refactor(SerializationService): use standard instance name
* refactor(SettingsService): use standard instance name
* refactor(bootstrap): add BootstrapShim
* feat(security): [#209] generate public/private keys
* refactor(encryption): move encryption utils to a service
* feat(encryption): [wip] implement convertCryptoKeyToString
* fix(user-settings): serialize crypto keys to strings
* feat(user-settings): deserialize user settings from IndexedDB
* feat(user-settings): upgrade persisted settings on boot
* feat(user-settings): automatically migrate persisted user settings
* refactor(encryption): simplify CryptoKey stringification
* refactor(encryption): DRY up EncryptionService
* feat(verification): send public key to new peers
* refactor(encryption): use class instance
* refactor(serialization): use class instance
* refactor(verification): [wip] create usePeerVerification hook
* feat(verification): encrypt verification token
* feat(verification): send encrypted token to peer
* feat(verification): verify peer
* refactor(verification): use enum for verification state
* feat(verification): expire verification requests
* fix(updatePeer): update with fresh state data
* feat(verification): display verification state
* refactor(usePeerVerification): store verification timer in Peer
* feat(verification): present tooltips explaining verification state
* feat(ui): show full page loading indicator
* feat(init): present bootup failure reasons
* refactor(init): move init to its own file
* feat(verification): show errors upon verification failure
* refactor(verification): move workaround to usePeerVerification
* feat(verification): present peer public keys
* refactor(verification): move peer public key rendering to its own component
* refactor(verification): only pass publicKey into renderer
* feat(verification): show user's own public key
* refactor(naming): rename Username to UserInfo
* refactor(loading): encapsulate height styling
* feat(verification): improve user messaging
* refactor(style): improve formatting and variable names
* feat(verification): add user info tooltip
* docs(verification): explain verification