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
This commit is contained in:
parent
4d6d1482f2
commit
94a4b2fb2e
@ -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<BootstrapProps> = {}) => {
|
||||
<Bootstrap
|
||||
persistedStorage={mockPersistedStorage as any as typeof localforage}
|
||||
initialUserSettings={userSettingsStub}
|
||||
serializationService={mockSerializationService}
|
||||
serializationService={mockSerialization}
|
||||
{...overrides}
|
||||
/>
|
||||
)
|
||||
|
@ -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),
|
||||
|
@ -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(),
|
||||
|
@ -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<ReturnType<typeof fileTransfer.download>>
|
||||
|
@ -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])
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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`
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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<UserSettings>) => Promise<void>
|
||||
@ -17,7 +17,7 @@ export const SettingsContext = createContext<SettingsContextProps>({
|
||||
playSoundOnNewMessage: true,
|
||||
showNotificationOnNewMessage: true,
|
||||
showActiveTypingStatus: true,
|
||||
publicKey: encryptionService.cryptoKeyStub,
|
||||
privateKey: encryptionService.cryptoKeyStub,
|
||||
publicKey: encryption.cryptoKeyStub,
|
||||
privateKey: encryption.cryptoKeyStub,
|
||||
}),
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
4
src/lib/sleep.ts
Normal file
4
src/lib/sleep.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export const sleep = (milliseconds: number): Promise<void> =>
|
||||
new Promise<void>(res => {
|
||||
setTimeout(res, milliseconds)
|
||||
})
|
@ -1,8 +1,3 @@
|
||||
export const sleep = (milliseconds: number): Promise<void> =>
|
||||
new Promise<void>(res => {
|
||||
setTimeout(res, milliseconds)
|
||||
})
|
||||
|
||||
export const isRecord = (variable: any): variable is Record<string, any> => {
|
||||
return (
|
||||
typeof variable === 'object' &&
|
@ -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'))
|
||||
|
@ -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(() => {
|
||||
|
@ -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 (
|
||||
<Box className="max-w-3xl mx-auto p-4">
|
||||
|
@ -110,4 +110,4 @@ export class EncryptionService {
|
||||
}
|
||||
}
|
||||
|
||||
export const encryptionService = new EncryptionService()
|
||||
export const encryption = new EncryptionService()
|
||||
|
@ -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()
|
||||
|
@ -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<UserSettings, 'publicKey' | 'privateKey'> {
|
||||
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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<UserSettings> = {}
|
||||
@ -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,
|
||||
}),
|
||||
}
|
||||
|
@ -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<UserSettings> = {}
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user