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:
Jeremy Kahn 2024-01-28 20:46:59 -06:00 committed by GitHub
parent 4d6d1482f2
commit 94a4b2fb2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
46 changed files with 129 additions and 151 deletions

View File

@ -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}
/>
)

View File

@ -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),

View File

@ -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(),

View File

@ -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>>

View File

@ -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])

View File

@ -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,

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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)

View File

@ -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`
)
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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()

View File

@ -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'

View File

@ -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

View File

@ -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,
}),
})

View File

@ -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

View File

@ -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
View File

@ -0,0 +1,4 @@
export const sleep = (milliseconds: number): Promise<void> =>
new Promise<void>(res => {
setTimeout(res, milliseconds)
})

View File

@ -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' &&

View File

@ -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'))

View File

@ -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(() => {

View File

@ -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">

View File

@ -110,4 +110,4 @@ export class EncryptionService {
}
}
export const encryptionService = new EncryptionService()
export const encryption = new EncryptionService()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -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,
}
}

View File

@ -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,
}),
}

View File

@ -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,
}
}