fix(files): filepicker circular dependency

This commit is contained in:
Karol Sójko
2022-08-04 17:32:49 +02:00
parent 696b82b9d3
commit 183f68c9c1
33 changed files with 64 additions and 64 deletions

View File

@@ -32,7 +32,7 @@
},
"dependencies": {
"@standardnotes/common": "^1.23.1",
"@standardnotes/services": "workspace:*",
"@standardnotes/files": "workspace:*",
"@standardnotes/utils": "workspace:*",
"@types/wicg-file-system-access": "^2020.9.5",
"reflect-metadata": "^0.1.13"

View File

@@ -1,4 +1,5 @@
import { EncryptedBytes } from './../TypedBytes'
import { EncryptedBytes } from '@standardnotes/files'
import { FileMemoryCache } from './FileMemoryCache'
describe('file memory cache', () => {

View File

@@ -1,6 +1,6 @@
import { removeFromArray } from '@standardnotes/utils'
import { Uuid } from '@standardnotes/common'
import { EncryptedBytes } from '../TypedBytes'
import { EncryptedBytes } from '@standardnotes/files'
export class FileMemoryCache {
private cache: Record<Uuid, EncryptedBytes> = {}

View File

@@ -1,70 +0,0 @@
import { ByteChunker } from './ByteChunker'
const chunkOfSize = (size: number) => {
return new TextEncoder().encode('a'.repeat(size))
}
describe('byte chunker', () => {
it('should hold back small chunks until minimum size is met', async () => {
let receivedBytes = new Uint8Array()
let numChunks = 0
const chunker = new ByteChunker(100, async (bytes) => {
numChunks++
receivedBytes = new Uint8Array([...receivedBytes, ...bytes])
})
await chunker.addBytes(chunkOfSize(50), false)
await chunker.addBytes(chunkOfSize(50), false)
await chunker.addBytes(chunkOfSize(50), false)
await chunker.addBytes(chunkOfSize(50), true)
expect(numChunks).toEqual(2)
expect(receivedBytes.length).toEqual(200)
})
it('should send back big chunks immediately', async () => {
let receivedBytes = new Uint8Array()
let numChunks = 0
const chunker = new ByteChunker(100, async (bytes) => {
numChunks++
receivedBytes = new Uint8Array([...receivedBytes, ...bytes])
})
await chunker.addBytes(chunkOfSize(150), false)
await chunker.addBytes(chunkOfSize(150), false)
await chunker.addBytes(chunkOfSize(150), false)
await chunker.addBytes(chunkOfSize(50), true)
expect(numChunks).toEqual(4)
expect(receivedBytes.length).toEqual(500)
})
it('last chunk should be popped regardless of size', async () => {
let receivedBytes = new Uint8Array()
let numChunks = 0
const chunker = new ByteChunker(100, async (bytes) => {
numChunks++
receivedBytes = new Uint8Array([...receivedBytes, ...bytes])
})
await chunker.addBytes(chunkOfSize(50), false)
await chunker.addBytes(chunkOfSize(25), true)
expect(numChunks).toEqual(1)
expect(receivedBytes.length).toEqual(75)
})
it('single chunk should be popped immediately', async () => {
let receivedBytes = new Uint8Array()
let numChunks = 0
const chunker = new ByteChunker(100, async (bytes) => {
numChunks++
receivedBytes = new Uint8Array([...receivedBytes, ...bytes])
})
await chunker.addBytes(chunkOfSize(50), true)
expect(numChunks).toEqual(1)
expect(receivedBytes.length).toEqual(50)
})
})

View File

@@ -1,35 +0,0 @@
import { OnChunkCallback } from '../types'
export class ByteChunker {
public loggingEnabled = false
private bytes = new Uint8Array()
private index = 1
constructor(private minimumChunkSize: number, private onChunk: OnChunkCallback) {}
private log(...args: any[]): void {
if (!this.loggingEnabled) {
return
}
// eslint-disable-next-line no-console
console.log(args)
}
public async addBytes(bytes: Uint8Array, isLast: boolean): Promise<void> {
this.bytes = new Uint8Array([...this.bytes, ...bytes])
this.log(`Chunker adding ${bytes.length}, total size ${this.bytes.length}`)
if (this.bytes.length >= this.minimumChunkSize || isLast) {
await this.popBytes(isLast)
}
}
private async popBytes(isLast: boolean): Promise<void> {
const maxIndex = Math.max(this.minimumChunkSize, this.bytes.length)
const chunk = this.bytes.slice(0, maxIndex)
this.bytes = new Uint8Array([...this.bytes.slice(maxIndex)])
this.log(`Chunker popping ${chunk.length}, total size in queue ${this.bytes.length}`)
await this.onChunk(chunk, this.index++, isLast)
}
}

View File

@@ -1,23 +0,0 @@
import { OrderedByteChunker } from './OrderedByteChunker'
const chunkOfSize = (size: number) => {
return new TextEncoder().encode('a'.repeat(size))
}
describe('ordered byte chunker', () => {
it('should callback multiple times if added bytes matches multiple chunk sizes', async () => {
const chunkSizes = [10, 10, 10]
let receivedBytes = new Uint8Array()
let numCallbacks = 0
const chunker = new OrderedByteChunker(chunkSizes, async (bytes) => {
numCallbacks++
receivedBytes = new Uint8Array([...receivedBytes, ...bytes])
})
await chunker.addBytes(chunkOfSize(30))
expect(numCallbacks).toEqual(3)
expect(receivedBytes.length).toEqual(30)
})
})

View File

@@ -1,40 +0,0 @@
export class OrderedByteChunker {
private bytes = new Uint8Array()
private index = 1
private remainingChunks: number[] = []
constructor(
private chunkSizes: number[],
private onChunk: (chunk: Uint8Array, index: number, isLast: boolean) => Promise<void>,
) {
this.remainingChunks = chunkSizes.slice()
}
private needsPop(): boolean {
return this.remainingChunks.length > 0 && this.bytes.length >= this.remainingChunks[0]
}
public async addBytes(bytes: Uint8Array): Promise<void> {
this.bytes = new Uint8Array([...this.bytes, ...bytes])
if (this.needsPop()) {
await this.popBytes()
}
}
private async popBytes(): Promise<void> {
const readUntil = this.remainingChunks[0]
const chunk = this.bytes.slice(0, readUntil)
this.bytes = new Uint8Array([...this.bytes.slice(readUntil)])
this.remainingChunks.shift()
await this.onChunk(chunk, this.index++, this.index === this.chunkSizes.length - 1)
if (this.needsPop()) {
await this.popBytes()
}
}
}

View File

@@ -1,5 +1,5 @@
import { ByteChunker } from './../Chunker/ByteChunker'
import { OnChunkCallback, FileSelectionResponse } from '../types'
import { ByteChunker, OnChunkCallback } from '@standardnotes/files'
import { FileSelectionResponse } from '../types'
import { readFile as utilsReadFile } from '../utils'
import { FileReaderInterface } from '../Interface/FileReader'

View File

@@ -1,4 +1,6 @@
import { OnChunkCallback, FileSelectionResponse } from '../types'
import { OnChunkCallback } from '@standardnotes/files'
import { FileSelectionResponse } from '../types'
export interface FileReaderInterface {
selectFiles(): Promise<File[]>

View File

@@ -5,7 +5,7 @@ import {
FileHandleRead,
FileSystemNoSelection,
FileSystemResult,
} from '@standardnotes/services'
} from '@standardnotes/files'
interface WebDirectoryHandle extends DirectoryHandle {
nativeHandle: FileSystemDirectoryHandle

View File

@@ -1,6 +1,7 @@
import { ByteChunker, OnChunkCallback } from '@standardnotes/files'
import { FileReaderInterface } from './../Interface/FileReader'
import { ByteChunker } from '../Chunker/ByteChunker'
import { OnChunkCallback, FileSelectionResponse } from '../types'
import { FileSelectionResponse } from '../types'
interface StreamingFileReaderInterface {
getFilesFromHandles(handles: FileSystemFileHandle[]): Promise<File[]>

View File

@@ -1,7 +0,0 @@
export type EncryptedBytes = {
encryptedBytes: Uint8Array
}
export type DecryptedBytes = {
decryptedBytes: Uint8Array
}

View File

@@ -5,7 +5,4 @@ export * from './Streaming/StreamingReader'
export * from './Streaming/StreamingSaver'
export * from './Streaming/StreamingApi'
export * from './utils'
export * from './Chunker/ByteChunker'
export * from './Chunker/OrderedByteChunker'
export * from './Cache/FileMemoryCache'
export * from './TypedBytes'

View File

@@ -1,5 +1,3 @@
export type OnChunkCallback = (chunk: Uint8Array, index: number, isLast: boolean) => Promise<void>
export type FileSelectionResponse = {
name: string
mimeType: string