From 94a4b2fb2e2ffad7b2fb04a78257a6dac4e7095a Mon Sep 17 00:00:00 2001 From: Jeremy Kahn Date: Sun, 28 Jan 2024 20:46:59 -0600 Subject: [PATCH] refactor(services): Standardize `services` and `lib` organization (#226) * 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 --- src/Bootstrap.test.tsx | 4 +-- src/Bootstrap.tsx | 9 +++---- src/Init.tsx | 5 ++-- src/components/Message/InlineMedia.tsx | 2 +- src/components/PublicKey/PublicKey.tsx | 4 +-- src/components/Room/Room.tsx | 6 ++--- src/components/Room/RoomAudioControls.tsx | 2 +- .../Room/RoomFileUploadControls.tsx | 2 +- .../Room/RoomScreenShareControls.tsx | 2 +- src/components/Room/RoomVideoControls.tsx | 2 +- src/components/Room/usePeerVerification.ts | 8 +++--- src/components/Room/useRoom.ts | 25 +++++++----------- src/components/Room/useRoomAudio.ts | 2 +- src/components/Room/useRoomFileShare.ts | 7 +++-- src/components/Room/useRoomScreenShare.ts | 4 +-- src/components/Room/useRoomVideo.ts | 5 ++-- .../Shell/ConnectionTestResults.tsx | 2 +- .../Shell/PeerDownloadFileButton.tsx | 4 +-- src/components/Shell/PeerList.tsx | 4 +-- src/components/Shell/PeerListItem.tsx | 2 +- src/components/Shell/RoomShareDialog.tsx | 9 +++---- src/components/Shell/Shell.tsx | 3 +-- src/components/Shell/useConnectionTest.ts | 5 ++-- src/contexts/SettingsContext.ts | 6 ++--- src/contexts/ShellContext.ts | 4 +-- src/{services => lib}/Audio/Audio.ts | 0 src/{services => lib}/Audio/index.ts | 0 .../ConnectionTest/ConnectionTest.ts | 0 src/{services => lib}/ConnectionTest/index.ts | 0 .../FileTransfer/FileTransfer.ts | 0 src/{services => lib}/FileTransfer/index.ts | 0 src/{services => lib}/PeerRoom/PeerRoom.ts | 26 +++++++++---------- src/{services => lib}/PeerRoom/index.ts | 0 src/lib/sleep.ts | 4 +++ src/{utils.ts => lib/type-guards.ts} | 5 ---- src/pages/PrivateRoom/PrivateRoom.tsx | 8 +++--- src/pages/PublicRoom/PublicRoom.tsx | 4 +-- src/pages/Settings/Settings.tsx | 14 +++++----- src/services/Encryption/Encryption.ts | 2 +- src/services/Notification/Notification.tsx | 17 ++++++------ src/services/Serialization/Serialization.ts | 16 +++++------- src/services/Settings/Settings.ts | 17 ++++++------ src/test-utils/mocks/mockEncryptionService.ts | 10 +++---- .../mocks/mockSerializationService.ts | 17 +++++------- src/test-utils/stubs/settingsContext.ts | 6 ++--- src/test-utils/stubs/userSettings.ts | 6 ++--- 46 files changed, 129 insertions(+), 151 deletions(-) rename src/{services => lib}/Audio/Audio.ts (100%) rename src/{services => lib}/Audio/index.ts (100%) rename src/{services => lib}/ConnectionTest/ConnectionTest.ts (100%) rename src/{services => lib}/ConnectionTest/index.ts (100%) rename src/{services => lib}/FileTransfer/FileTransfer.ts (100%) rename src/{services => lib}/FileTransfer/index.ts (100%) rename src/{services => lib}/PeerRoom/PeerRoom.ts (99%) rename src/{services => lib}/PeerRoom/index.ts (100%) create mode 100644 src/lib/sleep.ts rename src/{utils.ts => lib/type-guards.ts} (77%) diff --git a/src/Bootstrap.test.tsx b/src/Bootstrap.test.tsx index 3a053c8..e64f662 100644 --- a/src/Bootstrap.test.tsx +++ b/src/Bootstrap.test.tsx @@ -3,7 +3,7 @@ import localforage from 'localforage' import { PersistedStorageKeys } from 'models/storage' import { - mockSerializationService, + mockSerialization, mockSerializedPrivateKey, mockSerializedPublicKey, } from 'test-utils/mocks/mockSerializationService' @@ -34,7 +34,7 @@ const renderBootstrap = async (overrides: Partial = {}) => { ) diff --git a/src/Bootstrap.tsx b/src/Bootstrap.tsx index 8fe87df..38eaeaf 100644 --- a/src/Bootstrap.tsx +++ b/src/Bootstrap.tsx @@ -27,15 +27,12 @@ import { PostMessageEvent, PostMessageEventName, } from 'models/sdk' -import { - serializationService as serializationServiceInstance, - SerializedUserSettings, -} from 'services/Serialization' +import { serialization, SerializedUserSettings } from 'services/Serialization' export interface BootstrapProps { persistedStorage?: typeof localforage initialUserSettings: UserSettings - serializationService?: typeof serializationServiceInstance + serializationService?: typeof serialization } const configListenerTimeout = 3000 @@ -82,7 +79,7 @@ const Bootstrap = ({ description: 'Persisted settings data for chitchatter', }), initialUserSettings, - serializationService = serializationServiceInstance, + serializationService = serialization, }: BootstrapProps) => { const queryParams = useMemo( () => new URLSearchParams(window.location.search), diff --git a/src/Init.tsx b/src/Init.tsx index 101db55..44cc872 100644 --- a/src/Init.tsx +++ b/src/Init.tsx @@ -3,7 +3,7 @@ import Box from '@mui/material/Box' import Typography from '@mui/material/Typography' import { v4 as uuid } from 'uuid' -import { encryptionService } from 'services/Encryption' +import { encryption } from 'services/Encryption' import { EnvironmentUnsupportedDialog, isEnvironmentSupported, @@ -32,8 +32,7 @@ const Init = ({ getUuid = uuid, ...props }: InitProps) => { if (userSettings !== null) return try { - const { publicKey, privateKey } = - await encryptionService.generateKeyPair() + const { publicKey, privateKey } = await encryption.generateKeyPair() setUserSettings({ userId: getUuid(), diff --git a/src/components/Message/InlineMedia.tsx b/src/components/Message/InlineMedia.tsx index 7d92d48..54851b2 100644 --- a/src/components/Message/InlineMedia.tsx +++ b/src/components/Message/InlineMedia.tsx @@ -3,7 +3,7 @@ import { TorrentFile } from 'webtorrent' import CircularProgress from '@mui/material/CircularProgress' import Typography from '@mui/material/Typography' -import { fileTransfer } from 'services/FileTransfer' +import { fileTransfer } from 'lib/FileTransfer' import { ShellContext } from 'contexts/ShellContext' type TorrentFiles = Awaited> diff --git a/src/components/PublicKey/PublicKey.tsx b/src/components/PublicKey/PublicKey.tsx index 318ee6e..94a58a4 100644 --- a/src/components/PublicKey/PublicKey.tsx +++ b/src/components/PublicKey/PublicKey.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react' import { materialDark } from 'react-syntax-highlighter/dist/esm/styles/prism' import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter' import { CopyableBlock } from 'components/CopyableBlock/CopyableBlock' -import { encryptionService } from 'services/Encryption/Encryption' +import { encryption } from 'services/Encryption/Encryption' interface PeerPublicKeyProps { publicKey: CryptoKey @@ -13,7 +13,7 @@ export const PublicKey = ({ publicKey }: PeerPublicKeyProps) => { useEffect(() => { ;(async () => { - setPublicKeyString(await encryptionService.stringifyCryptoKey(publicKey)) + setPublicKeyString(await encryption.stringifyCryptoKey(publicKey)) })() }, [publicKey]) diff --git a/src/components/Room/Room.tsx b/src/components/Room/Room.tsx index ee46ff1..e583acb 100644 --- a/src/components/Room/Room.tsx +++ b/src/components/Room/Room.tsx @@ -12,7 +12,7 @@ import { RoomContext } from 'contexts/RoomContext' import { ShellContext } from 'contexts/ShellContext' import { MessageForm } from 'components/MessageForm' import { ChatTranscript } from 'components/ChatTranscript' -import { encryptionService as encryptionServiceInstance } from 'services/Encryption' +import { encryption } from 'services/Encryption' import { SettingsContext } from 'contexts/SettingsContext' import { useRoom } from './useRoom' @@ -30,13 +30,13 @@ export interface RoomProps { password?: string roomId: string userId: string - encryptionService?: typeof encryptionServiceInstance + encryptionService?: typeof encryption } export function Room({ appId = `${encodeURI(window.location.origin)}_${process.env.REACT_APP_NAME}`, getUuid = uuid, - encryptionService = encryptionServiceInstance, + encryptionService = encryption, roomId, password, userId, diff --git a/src/components/Room/RoomAudioControls.tsx b/src/components/Room/RoomAudioControls.tsx index 4573fc8..9869401 100644 --- a/src/components/Room/RoomAudioControls.tsx +++ b/src/components/Room/RoomAudioControls.tsx @@ -9,7 +9,7 @@ import Menu from '@mui/material/Menu' import MenuItem from '@mui/material/MenuItem' import Tooltip from '@mui/material/Tooltip' -import { PeerRoom } from 'services/PeerRoom/PeerRoom' +import { PeerRoom } from 'lib/PeerRoom' import { useRoomAudio } from './useRoomAudio' import { MediaButton } from './MediaButton' diff --git a/src/components/Room/RoomFileUploadControls.tsx b/src/components/Room/RoomFileUploadControls.tsx index e2d38be..443376c 100644 --- a/src/components/Room/RoomFileUploadControls.tsx +++ b/src/components/Room/RoomFileUploadControls.tsx @@ -6,7 +6,7 @@ import Tooltip from '@mui/material/Tooltip' import CircularProgress from '@mui/material/CircularProgress' import { RoomContext } from 'contexts/RoomContext' -import { PeerRoom } from 'services/PeerRoom/PeerRoom' +import { PeerRoom } from 'lib/PeerRoom' import { useRoomFileShare } from './useRoomFileShare' import { MediaButton } from './MediaButton' diff --git a/src/components/Room/RoomScreenShareControls.tsx b/src/components/Room/RoomScreenShareControls.tsx index c3068ab..8848440 100644 --- a/src/components/Room/RoomScreenShareControls.tsx +++ b/src/components/Room/RoomScreenShareControls.tsx @@ -3,7 +3,7 @@ import ScreenShare from '@mui/icons-material/ScreenShare' import StopScreenShare from '@mui/icons-material/StopScreenShare' import Tooltip from '@mui/material/Tooltip' -import { PeerRoom } from 'services/PeerRoom/PeerRoom' +import { PeerRoom } from 'lib/PeerRoom' import { useRoomScreenShare } from './useRoomScreenShare' import { MediaButton } from './MediaButton' diff --git a/src/components/Room/RoomVideoControls.tsx b/src/components/Room/RoomVideoControls.tsx index 5cfacb0..2b1faef 100644 --- a/src/components/Room/RoomVideoControls.tsx +++ b/src/components/Room/RoomVideoControls.tsx @@ -9,7 +9,7 @@ import Menu from '@mui/material/Menu' import MenuItem from '@mui/material/MenuItem' import Tooltip from '@mui/material/Tooltip' -import { PeerRoom } from 'services/PeerRoom/PeerRoom' +import { PeerRoom } from 'lib/PeerRoom' import { useRoomVideo } from './useRoomVideo' import { MediaButton } from './MediaButton' diff --git a/src/components/Room/usePeerVerification.ts b/src/components/Room/usePeerVerification.ts index 4b3e1e3..b557d06 100644 --- a/src/components/Room/usePeerVerification.ts +++ b/src/components/Room/usePeerVerification.ts @@ -1,8 +1,8 @@ import { useCallback, useContext, useEffect, useState } from 'react' import { ShellContext } from 'contexts/ShellContext' import { Peer, PeerVerificationState } from 'models/chat' -import { encryptionService as encryptionServiceInstance } from 'services/Encryption' -import { PeerRoom } from 'services/PeerRoom' +import { encryption } from 'services/Encryption' +import { PeerRoom } from 'lib/PeerRoom' import { PeerActions } from 'models/network' import { verificationTimeout } from 'config/messaging' import { usePeerNameDisplay } from 'components/PeerNameDisplay' @@ -10,13 +10,13 @@ import { usePeerNameDisplay } from 'components/PeerNameDisplay' interface UserPeerVerificationProps { peerRoom: PeerRoom privateKey: CryptoKey - encryptionService?: typeof encryptionServiceInstance + encryptionService?: typeof encryption } export const usePeerVerification = ({ peerRoom, privateKey, - encryptionService = encryptionServiceInstance, + encryptionService = encryption, }: UserPeerVerificationProps) => { const { updatePeer, peerList, showAlert } = useContext(ShellContext) diff --git a/src/components/Room/useRoom.ts b/src/components/Room/useRoom.ts index 7ce20a2..550690b 100644 --- a/src/components/Room/useRoom.ts +++ b/src/components/Room/useRoom.ts @@ -25,14 +25,11 @@ import { PeerVerificationState, } from 'models/chat' import { getPeerName, usePeerNameDisplay } from 'components/PeerNameDisplay' -import { NotificationService } from 'services/Notification' -import { Audio as AudioService } from 'services/Audio' -import { PeerRoom, PeerHookType } from 'services/PeerRoom' -import { fileTransfer } from 'services/FileTransfer' -import { - AllowedKeyType, - encryptionService as encryptionServiceInstance, -} from 'services/Encryption' +import { Audio } from 'lib/Audio' +import { notification } from 'services/Notification' +import { PeerRoom, PeerHookType } from 'lib/PeerRoom' +import { fileTransfer } from 'lib/FileTransfer' +import { AllowedKeyType, encryption } from 'services/Encryption' import { messageTranscriptSizeLimit } from 'config/messaging' @@ -43,7 +40,7 @@ interface UseRoomConfig { userId: string publicKey: CryptoKey getUuid?: typeof uuid - encryptionService?: typeof encryptionServiceInstance + encryptionService?: typeof encryption } interface UserMetadata { @@ -59,7 +56,7 @@ export function useRoom( userId, publicKey, getUuid = uuid, - encryptionService = encryptionServiceInstance, + encryptionService = encryption, }: UseRoomConfig ) { const isPrivate = password !== undefined @@ -87,7 +84,7 @@ export function useRoom( [] ) const [newMessageAudio] = useState( - () => new AudioService(process.env.PUBLIC_URL + '/sounds/new-message.aac') + () => new Audio(process.env.PUBLIC_URL + '/sounds/new-message.aac') ) const { getDisplayUsername } = usePeerNameDisplay() @@ -323,9 +320,7 @@ export function useRoom( if (userSettings.showNotificationOnNewMessage) { const displayUsername = getDisplayUsername(message.authorId) - NotificationService.showNotification( - `${displayUsername}: ${message.text}` - ) + notification.showNotification(`${displayUsername}: ${message.text}`) } } @@ -433,7 +428,7 @@ export function useRoom( } if (userSettings.showNotificationOnNewMessage) { - NotificationService.showNotification( + notification.showNotification( `${getDisplayUsername(inlineMedia.authorId)} shared media` ) } diff --git a/src/components/Room/useRoomAudio.ts b/src/components/Room/useRoomAudio.ts index 7bf276e..1949278 100644 --- a/src/components/Room/useRoomAudio.ts +++ b/src/components/Room/useRoomAudio.ts @@ -3,7 +3,7 @@ import { useContext, useEffect, useCallback, useState } from 'react' import { ShellContext } from 'contexts/ShellContext' import { PeerActions } from 'models/network' import { AudioState, Peer } from 'models/chat' -import { PeerRoom, PeerHookType, PeerStreamType } from 'services/PeerRoom' +import { PeerRoom, PeerHookType, PeerStreamType } from 'lib/PeerRoom' interface UseRoomAudioConfig { peerRoom: PeerRoom diff --git a/src/components/Room/useRoomFileShare.ts b/src/components/Room/useRoomFileShare.ts index 06cff7d..888ba6f 100644 --- a/src/components/Room/useRoomFileShare.ts +++ b/src/components/Room/useRoomFileShare.ts @@ -1,13 +1,12 @@ import { useContext, useEffect, useState } from 'react' -import { sleep } from 'utils' +import { sleep } from 'lib/sleep' import { RoomContext } from 'contexts/RoomContext' import { ShellContext } from 'contexts/ShellContext' import { PeerActions } from 'models/network' import { FileOfferMetadata, Peer } from 'models/chat' -import { PeerRoom, PeerHookType } from 'services/PeerRoom' - -import { fileTransfer } from 'services/FileTransfer/index' +import { PeerRoom, PeerHookType } from 'lib/PeerRoom' +import { fileTransfer } from 'lib/FileTransfer' interface UseRoomFileShareConfig { onInlineMediaUpload: (files: File[]) => void diff --git a/src/components/Room/useRoomScreenShare.ts b/src/components/Room/useRoomScreenShare.ts index 7ae5798..476aa4f 100644 --- a/src/components/Room/useRoomScreenShare.ts +++ b/src/components/Room/useRoomScreenShare.ts @@ -1,11 +1,11 @@ import { useContext, useEffect, useCallback, useState } from 'react' -import { isRecord } from 'utils' +import { isRecord } from 'lib/type-guards' import { RoomContext } from 'contexts/RoomContext' import { ShellContext } from 'contexts/ShellContext' import { PeerActions } from 'models/network' import { ScreenShareState, Peer, VideoStreamType } from 'models/chat' -import { PeerRoom, PeerHookType, PeerStreamType } from 'services/PeerRoom' +import { PeerRoom, PeerHookType, PeerStreamType } from 'lib/PeerRoom' interface UseRoomScreenShareConfig { peerRoom: PeerRoom diff --git a/src/components/Room/useRoomVideo.ts b/src/components/Room/useRoomVideo.ts index ed6c941..a87f715 100644 --- a/src/components/Room/useRoomVideo.ts +++ b/src/components/Room/useRoomVideo.ts @@ -4,9 +4,8 @@ import { RoomContext } from 'contexts/RoomContext' import { ShellContext } from 'contexts/ShellContext' import { PeerActions } from 'models/network' import { VideoState, Peer, VideoStreamType } from 'models/chat' -import { PeerRoom, PeerHookType, PeerStreamType } from 'services/PeerRoom' - -import { isRecord } from 'utils' +import { PeerRoom, PeerHookType, PeerStreamType } from 'lib/PeerRoom' +import { isRecord } from 'lib/type-guards' interface UseRoomVideoConfig { peerRoom: PeerRoom diff --git a/src/components/Shell/ConnectionTestResults.tsx b/src/components/Shell/ConnectionTestResults.tsx index c3dab4a..9c40221 100644 --- a/src/components/Shell/ConnectionTestResults.tsx +++ b/src/components/Shell/ConnectionTestResults.tsx @@ -6,7 +6,7 @@ import Circle from '@mui/icons-material/FiberManualRecord' import { Box } from '@mui/system' import ReportIcon from '@mui/icons-material/Report' -import { TrackerConnection } from 'services/ConnectionTest/ConnectionTest' +import { TrackerConnection } from 'lib/ConnectionTest' import { ShellContext } from 'contexts/ShellContext' import { ConnectionTestResults as IConnectionTestResults } from './useConnectionTest' diff --git a/src/components/Shell/PeerDownloadFileButton.tsx b/src/components/Shell/PeerDownloadFileButton.tsx index 9259952..5332e5e 100644 --- a/src/components/Shell/PeerDownloadFileButton.tsx +++ b/src/components/Shell/PeerDownloadFileButton.tsx @@ -5,8 +5,8 @@ import Tooltip from '@mui/material/Tooltip' import Download from '@mui/icons-material/Download' import CircularProgress from '@mui/material/CircularProgress' -import { isError } from 'utils' -import { fileTransfer } from 'services/FileTransfer/index' +import { isError } from 'lib/type-guards' +import { fileTransfer } from 'lib/FileTransfer' import { Peer } from 'models/chat' import { ShellContext } from 'contexts/ShellContext' diff --git a/src/components/Shell/PeerList.tsx b/src/components/Shell/PeerList.tsx index d663a24..5cd61db 100644 --- a/src/components/Shell/PeerList.tsx +++ b/src/components/Shell/PeerList.tsx @@ -10,8 +10,8 @@ import CircularProgress from '@mui/material/CircularProgress' import { UserInfo } from 'components/UserInfo' import { AudioState, Peer } from 'models/chat' -import { PeerConnectionType } from 'services/PeerRoom' -import { TrackerConnection } from 'services/ConnectionTest' +import { PeerConnectionType } from 'lib/PeerRoom' +import { TrackerConnection } from 'lib/ConnectionTest' import { PeerListHeader } from './PeerListHeader' import { PeerListItem } from './PeerListItem' diff --git a/src/components/Shell/PeerListItem.tsx b/src/components/Shell/PeerListItem.tsx index 11fda68..6f24d66 100644 --- a/src/components/Shell/PeerListItem.tsx +++ b/src/components/Shell/PeerListItem.tsx @@ -19,7 +19,7 @@ import { AudioVolume } from 'components/AudioVolume' import { PeerNameDisplay } from 'components/PeerNameDisplay' import { PublicKey } from 'components/PublicKey' import { Peer, PeerVerificationState } from 'models/chat' -import { PeerConnectionType } from 'services/PeerRoom/PeerRoom' +import { PeerConnectionType } from 'lib/PeerRoom' import { PeerDownloadFileButton } from './PeerDownloadFileButton' diff --git a/src/components/Shell/RoomShareDialog.tsx b/src/components/Shell/RoomShareDialog.tsx index fa9166d..f29c59c 100644 --- a/src/components/Shell/RoomShareDialog.tsx +++ b/src/components/Shell/RoomShareDialog.tsx @@ -14,8 +14,8 @@ import CloseIcon from '@mui/icons-material/Close' import { AlertOptions } from 'models/shell' import { useEffect, useState, SyntheticEvent } from 'react' -import { sleep } from 'utils' -import { encryptionService } from 'services/Encryption' +import { sleep } from 'lib/sleep' +import { encryption } from 'services/Encryption' export interface RoomShareDialogProps { isOpen: boolean @@ -51,10 +51,7 @@ export function RoomShareDialog(props: RoomShareDialogProps) { const url = window.location.href.split('#')[0] const copyWithPass = async () => { - const encoded = await encryptionService.encodePassword( - props.roomId, - password - ) + const encoded = await encryption.encodePassword(props.roomId, password) if (encoded === props.password) { const params = new URLSearchParams() diff --git a/src/components/Shell/Shell.tsx b/src/components/Shell/Shell.tsx index 4df37df..7074a1a 100644 --- a/src/components/Shell/Shell.tsx +++ b/src/components/Shell/Shell.tsx @@ -21,8 +21,7 @@ import { SettingsContext } from 'contexts/SettingsContext' import { AlertOptions, QueryParamKeys } from 'models/shell' import { AudioState, ScreenShareState, VideoState, Peer } from 'models/chat' import { ErrorBoundary } from 'components/ErrorBoundary' - -import { PeerConnectionType } from 'services/PeerRoom/PeerRoom' +import { PeerConnectionType } from 'lib/PeerRoom' import { Drawer } from './Drawer' import { UpgradeDialog } from './UpgradeDialog' diff --git a/src/components/Shell/useConnectionTest.ts b/src/components/Shell/useConnectionTest.ts index 80e16c2..dcf5a43 100644 --- a/src/components/Shell/useConnectionTest.ts +++ b/src/components/Shell/useConnectionTest.ts @@ -1,11 +1,12 @@ import { useEffect, useState } from 'react' -import { sleep } from 'utils' + +import { sleep } from 'lib/sleep' import { ConnectionTest, ConnectionTestEvent, ConnectionTestEvents, TrackerConnection, -} from 'services/ConnectionTest/ConnectionTest' +} from 'lib/ConnectionTest' export interface ConnectionTestResults { hasHost: boolean diff --git a/src/contexts/SettingsContext.ts b/src/contexts/SettingsContext.ts index 2db8307..542829f 100644 --- a/src/contexts/SettingsContext.ts +++ b/src/contexts/SettingsContext.ts @@ -1,7 +1,7 @@ import { createContext } from 'react' import { ColorMode, UserSettings } from 'models/settings' -import { encryptionService } from 'services/Encryption' +import { encryption } from 'services/Encryption' export interface SettingsContextProps { updateUserSettings: (settings: Partial) => Promise @@ -17,7 +17,7 @@ export const SettingsContext = createContext({ playSoundOnNewMessage: true, showNotificationOnNewMessage: true, showActiveTypingStatus: true, - publicKey: encryptionService.cryptoKeyStub, - privateKey: encryptionService.cryptoKeyStub, + publicKey: encryption.cryptoKeyStub, + privateKey: encryption.cryptoKeyStub, }), }) diff --git a/src/contexts/ShellContext.ts b/src/contexts/ShellContext.ts index e11654f..df74937 100644 --- a/src/contexts/ShellContext.ts +++ b/src/contexts/ShellContext.ts @@ -2,9 +2,9 @@ import { createContext, Dispatch, SetStateAction } from 'react' import { AlertOptions } from 'models/shell' import { AudioState, ScreenShareState, VideoState, Peer } from 'models/chat' -import { PeerConnectionType } from 'services/PeerRoom/PeerRoom' +import { PeerConnectionType } from 'lib/PeerRoom' import { ConnectionTestResults } from 'components/Shell/useConnectionTest' -import { TrackerConnection } from 'services/ConnectionTest/ConnectionTest' +import { TrackerConnection } from 'lib/ConnectionTest' interface ShellContextProps { isEmbedded: boolean diff --git a/src/services/Audio/Audio.ts b/src/lib/Audio/Audio.ts similarity index 100% rename from src/services/Audio/Audio.ts rename to src/lib/Audio/Audio.ts diff --git a/src/services/Audio/index.ts b/src/lib/Audio/index.ts similarity index 100% rename from src/services/Audio/index.ts rename to src/lib/Audio/index.ts diff --git a/src/services/ConnectionTest/ConnectionTest.ts b/src/lib/ConnectionTest/ConnectionTest.ts similarity index 100% rename from src/services/ConnectionTest/ConnectionTest.ts rename to src/lib/ConnectionTest/ConnectionTest.ts diff --git a/src/services/ConnectionTest/index.ts b/src/lib/ConnectionTest/index.ts similarity index 100% rename from src/services/ConnectionTest/index.ts rename to src/lib/ConnectionTest/index.ts diff --git a/src/services/FileTransfer/FileTransfer.ts b/src/lib/FileTransfer/FileTransfer.ts similarity index 100% rename from src/services/FileTransfer/FileTransfer.ts rename to src/lib/FileTransfer/FileTransfer.ts diff --git a/src/services/FileTransfer/index.ts b/src/lib/FileTransfer/index.ts similarity index 100% rename from src/services/FileTransfer/index.ts rename to src/lib/FileTransfer/index.ts diff --git a/src/services/PeerRoom/PeerRoom.ts b/src/lib/PeerRoom/PeerRoom.ts similarity index 99% rename from src/services/PeerRoom/PeerRoom.ts rename to src/lib/PeerRoom/PeerRoom.ts index 19c937a..ed06ec5 100644 --- a/src/services/PeerRoom/PeerRoom.ts +++ b/src/lib/PeerRoom/PeerRoom.ts @@ -1,7 +1,7 @@ import { joinRoom, Room, BaseRoomConfig } from 'trystero' import { TorrentRoomConfig } from 'trystero/torrent' -import { sleep } from 'utils' +import { sleep } from 'lib/sleep' export enum PeerHookType { NEW_PEER = 'NEW_PEER', @@ -48,6 +48,18 @@ export class PeerRoom { private isProcessingPendingStreams = false + private processPendingStreams = async () => { + if (this.isProcessingPendingStreams) return + + this.isProcessingPendingStreams = true + + while (this.streamQueue.length > 0) { + await this.streamQueue.shift()?.() + } + + this.isProcessingPendingStreams = false + } + constructor(config: TorrentRoomConfig & BaseRoomConfig, roomId: string) { this.roomConfig = config this.room = joinRoom(this.roomConfig, roomId) @@ -171,18 +183,6 @@ export class PeerRoom { this.processPendingStreams() } - private processPendingStreams = async () => { - if (this.isProcessingPendingStreams) return - - this.isProcessingPendingStreams = true - - while (this.streamQueue.length > 0) { - await this.streamQueue.shift()?.() - } - - this.isProcessingPendingStreams = false - } - removeStream: Room['removeStream'] = (stream, targetPeers) => { return this.room.removeStream(stream, targetPeers) } diff --git a/src/services/PeerRoom/index.ts b/src/lib/PeerRoom/index.ts similarity index 100% rename from src/services/PeerRoom/index.ts rename to src/lib/PeerRoom/index.ts diff --git a/src/lib/sleep.ts b/src/lib/sleep.ts new file mode 100644 index 0000000..fb9adf6 --- /dev/null +++ b/src/lib/sleep.ts @@ -0,0 +1,4 @@ +export const sleep = (milliseconds: number): Promise => + new Promise(res => { + setTimeout(res, milliseconds) + }) diff --git a/src/utils.ts b/src/lib/type-guards.ts similarity index 77% rename from src/utils.ts rename to src/lib/type-guards.ts index 57114dc..015bc87 100644 --- a/src/utils.ts +++ b/src/lib/type-guards.ts @@ -1,8 +1,3 @@ -export const sleep = (milliseconds: number): Promise => - new Promise(res => { - setTimeout(res, milliseconds) - }) - export const isRecord = (variable: any): variable is Record => { return ( typeof variable === 'object' && diff --git a/src/pages/PrivateRoom/PrivateRoom.tsx b/src/pages/PrivateRoom/PrivateRoom.tsx index 275b3ba..149dc99 100644 --- a/src/pages/PrivateRoom/PrivateRoom.tsx +++ b/src/pages/PrivateRoom/PrivateRoom.tsx @@ -3,9 +3,9 @@ import { Room } from 'components/Room' import { useParams } from 'react-router-dom' import { ShellContext } from 'contexts/ShellContext' -import { NotificationService } from 'services/Notification' +import { notification } from 'services/Notification' import { PasswordPrompt } from 'components/PasswordPrompt' -import { encryptionService } from 'services/Encryption' +import { encryption } from 'services/Encryption' interface PublicRoomProps { userId: string @@ -22,7 +22,7 @@ export function PrivateRoom({ userId }: PublicRoomProps) { const [secret, setSecret] = useState(urlParams.get('secret') ?? '') useEffect(() => { - NotificationService.requestPermission() + notification.requestPermission() }, []) useEffect(() => { @@ -31,7 +31,7 @@ export function PrivateRoom({ userId }: PublicRoomProps) { const handlePasswordEntered = async (password: string) => { if (password.length !== 0) - setSecret(await encryptionService.encodePassword(roomId, password)) + setSecret(await encryption.encodePassword(roomId, password)) } if (urlParams.has('pwd') && !urlParams.has('secret')) diff --git a/src/pages/PublicRoom/PublicRoom.tsx b/src/pages/PublicRoom/PublicRoom.tsx index 34da391..61b1c18 100644 --- a/src/pages/PublicRoom/PublicRoom.tsx +++ b/src/pages/PublicRoom/PublicRoom.tsx @@ -3,7 +3,7 @@ import { Room } from 'components/Room' import { useParams } from 'react-router-dom' import { ShellContext } from 'contexts/ShellContext' -import { NotificationService } from 'services/Notification' +import { notification } from 'services/Notification' interface PublicRoomProps { userId: string @@ -14,7 +14,7 @@ export function PublicRoom({ userId }: PublicRoomProps) { const { setTitle } = useContext(ShellContext) useEffect(() => { - NotificationService.requestPermission() + notification.requestPermission() }, []) useEffect(() => { diff --git a/src/pages/Settings/Settings.tsx b/src/pages/Settings/Settings.tsx index cfee265..4e934a9 100644 --- a/src/pages/Settings/Settings.tsx +++ b/src/pages/Settings/Settings.tsx @@ -10,15 +10,15 @@ import FormControlLabel from '@mui/material/FormControlLabel' import Paper from '@mui/material/Paper' import useTheme from '@mui/material/styles/useTheme' -import { settingsService } from 'services/Settings' -import { NotificationService } from 'services/Notification' +import { settings } from 'services/Settings' +import { notification } from 'services/Notification' import { ShellContext } from 'contexts/ShellContext' import { StorageContext } from 'contexts/StorageContext' import { SettingsContext } from 'contexts/SettingsContext' import { PeerNameDisplay } from 'components/PeerNameDisplay' import { ConfirmDialog } from 'components/ConfirmDialog' -import { isErrorWithMessage } from '../../utils' +import { isErrorWithMessage } from '../../lib/type-guards' interface SettingsProps { userId: string @@ -45,7 +45,7 @@ export const Settings = ({ userId }: SettingsProps) => { useEffect(() => { ;(async () => { - await NotificationService.requestPermission() + await notification.requestPermission() // This state needs to be set to cause a rerender so that // areNotificationsAvailable is up-to-date. @@ -93,7 +93,7 @@ export const Settings = ({ userId }: SettingsProps) => { const handleExportSettingsClick = async () => { try { - await settingsService.exportSettings(getUserSettings()) + await settings.exportSettings(getUserSettings()) } catch (e) { if (isErrorWithMessage(e)) { showAlert(e.message, { severity: 'error' }) @@ -103,7 +103,7 @@ export const Settings = ({ userId }: SettingsProps) => { const handleImportSettingsClick = async ([[, file]]: Result[]) => { try { - const userSettings = await settingsService.importSettings(file) + const userSettings = await settings.importSettings(file) updateUserSettings(userSettings) @@ -115,7 +115,7 @@ export const Settings = ({ userId }: SettingsProps) => { } } - const areNotificationsAvailable = NotificationService.permission === 'granted' + const areNotificationsAvailable = notification.permission === 'granted' return ( diff --git a/src/services/Encryption/Encryption.ts b/src/services/Encryption/Encryption.ts index 0a4e9be..c160559 100644 --- a/src/services/Encryption/Encryption.ts +++ b/src/services/Encryption/Encryption.ts @@ -110,4 +110,4 @@ export class EncryptionService { } } -export const encryptionService = new EncryptionService() +export const encryption = new EncryptionService() diff --git a/src/services/Notification/Notification.tsx b/src/services/Notification/Notification.tsx index b927026..53ef11f 100644 --- a/src/services/Notification/Notification.tsx +++ b/src/services/Notification/Notification.tsx @@ -1,18 +1,17 @@ export class NotificationService { - static permission: NotificationPermission + permission: NotificationPermission = 'default' - static requestPermission = async () => { - if (NotificationService.permission === 'granted') return + requestPermission = async () => { + if (this.permission === 'granted') return - NotificationService.permission = await Notification.requestPermission() + this.permission = await Notification.requestPermission() } - static showNotification = ( - message: string, - options?: NotificationOptions - ) => { - if (NotificationService.permission !== 'granted') return + showNotification = (message: string, options?: NotificationOptions) => { + if (this.permission !== 'granted') return new Notification(message, options) } } + +export const notification = new NotificationService() diff --git a/src/services/Serialization/Serialization.ts b/src/services/Serialization/Serialization.ts index 8d3a25b..a3eb979 100644 --- a/src/services/Serialization/Serialization.ts +++ b/src/services/Serialization/Serialization.ts @@ -1,5 +1,5 @@ import { ColorMode, UserSettings } from 'models/settings' -import { AllowedKeyType, encryptionService } from 'services/Encryption' +import { AllowedKeyType, encryption } from 'services/Encryption' export interface SerializedUserSettings extends Omit { @@ -42,13 +42,9 @@ export class SerializationService { ...userSettingsRest } = userSettings - const publicKey = await encryptionService.stringifyCryptoKey( - publicCryptoKey - ) + const publicKey = await encryption.stringifyCryptoKey(publicCryptoKey) - const privateKey = await encryptionService.stringifyCryptoKey( - privateCryptoKey - ) + const privateKey = await encryption.stringifyCryptoKey(privateCryptoKey) return { ...userSettingsRest, @@ -66,11 +62,11 @@ export class SerializationService { ...userSettingsForIndexedDbRest } = serializedUserSettings - const publicKey = await encryptionService.parseCryptoKeyString( + const publicKey = await encryption.parseCryptoKeyString( publicCryptoKeyString, AllowedKeyType.PUBLIC ) - const privateKey = await encryptionService.parseCryptoKeyString( + const privateKey = await encryption.parseCryptoKeyString( privateCryptoKeyString, AllowedKeyType.PRIVATE ) @@ -83,4 +79,4 @@ export class SerializationService { } } -export const serializationService = new SerializationService() +export const serialization = new SerializationService() diff --git a/src/services/Settings/Settings.ts b/src/services/Settings/Settings.ts index 62da5dc..2ad9de9 100644 --- a/src/services/Settings/Settings.ts +++ b/src/services/Settings/Settings.ts @@ -1,10 +1,10 @@ import { saveAs } from 'file-saver' import { UserSettings } from 'models/settings' -import { encryptionService } from 'services/Encryption' +import { encryption } from 'services/Encryption' import { isSerializedUserSettings, - serializationService, + serialization, } from 'services/Serialization/Serialization' class InvalidFileError extends Error { @@ -15,8 +15,9 @@ const encryptionTestTarget = 'chitchatter' export class SettingsService { exportSettings = async (userSettings: UserSettings) => { - const serializedUserSettings = - await serializationService.serializeUserSettings(userSettings) + const serializedUserSettings = await serialization.serializeUserSettings( + userSettings + ) const blob = new Blob([JSON.stringify(serializedUserSettings)], { type: 'application/json;charset=utf-8', @@ -44,14 +45,14 @@ export class SettingsService { } const deserializedUserSettings = - await serializationService.deserializeUserSettings(parsedFileResult) + await serialization.deserializeUserSettings(parsedFileResult) - const encryptedString = await encryptionService.encryptString( + const encryptedString = await encryption.encryptString( deserializedUserSettings.publicKey, encryptionTestTarget ) - const decryptedString = await encryptionService.decryptString( + const decryptedString = await encryption.decryptString( deserializedUserSettings.privateKey, encryptedString ) @@ -77,4 +78,4 @@ export class SettingsService { } } -export const settingsService = new SettingsService() +export const settings = new SettingsService() diff --git a/src/test-utils/mocks/mockEncryptionService.ts b/src/test-utils/mocks/mockEncryptionService.ts index a869b5e..a15dcc7 100644 --- a/src/test-utils/mocks/mockEncryptionService.ts +++ b/src/test-utils/mocks/mockEncryptionService.ts @@ -1,10 +1,10 @@ -import { encryptionService } from 'services/Encryption' +import { encryption } from 'services/Encryption' -export const mockEncryptionService = encryptionService +export const mockEncryptionService = encryption mockEncryptionService.generateKeyPair = jest.fn(async () => ({ - publicKey: encryptionService.cryptoKeyStub, - privateKey: encryptionService.cryptoKeyStub, + publicKey: encryption.cryptoKeyStub, + privateKey: encryption.cryptoKeyStub, })) mockEncryptionService.encodePassword = async () => '' @@ -12,4 +12,4 @@ mockEncryptionService.encodePassword = async () => '' mockEncryptionService.stringifyCryptoKey = async () => '' mockEncryptionService.parseCryptoKeyString = async () => - encryptionService.cryptoKeyStub + encryption.cryptoKeyStub diff --git a/src/test-utils/mocks/mockSerializationService.ts b/src/test-utils/mocks/mockSerializationService.ts index aae6354..9c8942c 100644 --- a/src/test-utils/mocks/mockSerializationService.ts +++ b/src/test-utils/mocks/mockSerializationService.ts @@ -1,16 +1,13 @@ import { UserSettings } from 'models/settings' -import { encryptionService } from 'services/Encryption' -import { - serializationService, - SerializedUserSettings, -} from 'services/Serialization' +import { encryption } from 'services/Encryption' +import { serialization, SerializedUserSettings } from 'services/Serialization' export const mockSerializedPublicKey = 'public key' export const mockSerializedPrivateKey = 'private key' -export const mockSerializationService = serializationService +export const mockSerialization = serialization -mockSerializationService.serializeUserSettings = async ( +mockSerialization.serializeUserSettings = async ( userSettings: UserSettings ) => { const { publicKey, privateKey, ...userSettingsRest } = userSettings @@ -22,14 +19,14 @@ mockSerializationService.serializeUserSettings = async ( } } -mockSerializationService.deserializeUserSettings = async ( +mockSerialization.deserializeUserSettings = async ( serializedUserSettings: SerializedUserSettings ) => { const { publicKey, privateKey, ...userSettingsRest } = serializedUserSettings return { - publicKey: encryptionService.cryptoKeyStub, - privateKey: encryptionService.cryptoKeyStub, + publicKey: encryption.cryptoKeyStub, + privateKey: encryption.cryptoKeyStub, ...userSettingsRest, } } diff --git a/src/test-utils/stubs/settingsContext.ts b/src/test-utils/stubs/settingsContext.ts index d9615c1..2be0f55 100644 --- a/src/test-utils/stubs/settingsContext.ts +++ b/src/test-utils/stubs/settingsContext.ts @@ -1,6 +1,6 @@ import { SettingsContextProps } from 'contexts/SettingsContext' import { ColorMode, UserSettings } from 'models/settings' -import { encryptionService } from 'services/Encryption' +import { encryption } from 'services/Encryption' export const userSettingsContextStubFactory = ( userSettingsOverrides: Partial = {} @@ -14,8 +14,8 @@ export const userSettingsContextStubFactory = ( playSoundOnNewMessage: true, showNotificationOnNewMessage: true, showActiveTypingStatus: true, - publicKey: encryptionService.cryptoKeyStub, - privateKey: encryptionService.cryptoKeyStub, + publicKey: encryption.cryptoKeyStub, + privateKey: encryption.cryptoKeyStub, ...userSettingsOverrides, }), } diff --git a/src/test-utils/stubs/userSettings.ts b/src/test-utils/stubs/userSettings.ts index 9b094f9..349a17b 100644 --- a/src/test-utils/stubs/userSettings.ts +++ b/src/test-utils/stubs/userSettings.ts @@ -1,5 +1,5 @@ import { ColorMode, UserSettings } from 'models/settings' -import { encryptionService } from 'services/Encryption' +import { encryption } from 'services/Encryption' export const userSettingsStubFactory = ( overrides: Partial = {} @@ -11,8 +11,8 @@ export const userSettingsStubFactory = ( playSoundOnNewMessage: true, showNotificationOnNewMessage: true, showActiveTypingStatus: true, - publicKey: encryptionService.cryptoKeyStub, - privateKey: encryptionService.cryptoKeyStub, + publicKey: encryption.cryptoKeyStub, + privateKey: encryption.cryptoKeyStub, ...overrides, } }