Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(files): set bucket root after each file operation #3071

Merged
merged 1 commit into from
May 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions components/views/files/controls/Controls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export default Vue.extend({
const sameNameResults: File[] = emptyFileResults.filter((file) => {
return !this.$FileSystem.currentDirectory.hasChild(file.name)
})
const files: Promise<{ file: File; nsfw: boolean }>[] =
const files: { file: File; nsfw: boolean }[] = await Promise.all(
sameNameResults.map(async (file: File) => {
// convert heic to jpg for scan. return original heic if sfw
if (await isHeic(file)) {
Expand All @@ -160,9 +160,10 @@ export default Vue.extend({
}

return { file, nsfw }
})
}),
)

for await (const file of files) {
for (const file of files) {
try {
this.$store.commit(
'ui/setFilesUploadStatus',
Expand Down
68 changes: 38 additions & 30 deletions libraries/Files/remote/textile/Bucket.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import { Buckets, RemovePathResponse, Root } from '@textile/buckets'
import { Buckets, Root } from '@textile/buckets'
import { createWriteStream } from 'streamsaver'
import { Config } from '~/config'
import {
FileSystemExport,
FILESYSTEM_TYPE,
} from '~/libraries/Files/types/filesystem'
import { TextileInitializationData } from '~/types/textile/manager'
import { RFM } from '../abstracts/RFM.abstract'
import { RFMInterface } from '../interface/RFM.interface'
import { RFM } from '~/libraries/Files/remote/abstracts/RFM.abstract'
import { RFMInterface } from '~/libraries/Files/remote/interface/RFM.interface'

export class Bucket extends RFM implements RFMInterface {
private _textile: TextileInitializationData
private _index: FileSystemExport | null = null
private buckets: Buckets | null
private key: Root['key'] | null
private _buckets: Buckets | null
private _key: Root['key'] | null
private _root: Root | Root['path'] = ''

constructor(textile: TextileInitializationData) {
super()
this._textile = textile
this.buckets = null
this.key = null
this._buckets = null
this._key = null
}

/**
Expand All @@ -41,19 +42,20 @@ export class Bucket extends RFM implements RFMInterface {
throw new Error('Textile key not found')
}

this.buckets = await Buckets.withKeyInfo({ key: Config.textile.key })
await this.buckets.getToken(this._textile.identity)
this._buckets = await Buckets.withKeyInfo({ key: Config.textile.key })
await this._buckets.getToken(this._textile.identity)

const result = await this.buckets.getOrCreate(name, { encrypted: true })
const result = await this._buckets.getOrCreate(name, { encrypted: true })

if (!result.root) throw new Error(`failed to open bucket ${name}`)

this.key = result.root.key
this._key = result.root.key
this._root = result.root

try {
const data = []
for await (const bytes of this.buckets.pullPath(
this.key,
for await (const bytes of this._buckets.pullPath(
this._key,
Config.textile.fsTable,
)) {
data.push(bytes)
Expand Down Expand Up @@ -82,26 +84,28 @@ export class Bucket extends RFM implements RFMInterface {
* @description sets file system import data
*/
async updateIndex(index: FileSystemExport) {
if (!this.buckets || !this.key) {
if (!this._buckets || !this._key) {
throw new Error('Bucket or bucket key not found')
}
this._index = index
await this.buckets.pushPath(
this.key,
const res = await this._buckets.pushPath(
this._key,
Config.textile.fsTable,
Buffer.from(JSON.stringify(index)),
{ root: this._root },
)
this._root = res.root
}

/**
* @method ipnsLink
* @returns {Promise<string>} ipns bucket link
*/
async ipnsLink(): Promise<string> {
if (!this.buckets || !this.key) {
if (!this._buckets || !this._key) {
throw new Error('Bucket or bucket key not found')
}
return (await this.buckets.links(this.key)).ipns
return (await this._buckets.links(this._key)).ipns
}

/**
Expand All @@ -113,12 +117,12 @@ export class Bucket extends RFM implements RFMInterface {
* @param {Function} progressCallback used to show progress meter in componment that calls this method
*/
async pushFile(file: File, path: string, progressCallback: Function) {
if (!this.buckets || !this.key) {
if (!this._buckets || !this._key) {
throw new Error('Bucket or bucket key not found')
}

await this.buckets.pushPath(
this.key,
const res = await this._buckets.pushPath(
this._key,
path,
{
path,
Expand All @@ -128,8 +132,10 @@ export class Bucket extends RFM implements RFMInterface {
progress: (num) => {
progressCallback(num, file.size, file.name)
},
root: this._root,
},
)
this._root = res.root
}

private _getStream(file: File) {
Expand All @@ -155,23 +161,22 @@ export class Bucket extends RFM implements RFMInterface {
}

/**
* @method pullFile
* @method pullFileStream
* @description fetch encrypted file from bucket
* @param {string} id file path in bucket
* @param {string} name file name
* @param {number} size file size to show progress in browser
* @returns Promise of File
*/
async pullFileStream(id: string, name: string, size: number) {
if (!this.buckets || !this.key) {
if (!this._buckets || !this._key) {
throw new Error('Bucket or bucket key not found')
}
const fileStream = createWriteStream(name, { size })
const writer = fileStream.getWriter()

window.onunload = () => writer.abort()

for await (const bytes of this.buckets.pullPath(this.key, id)) {
for await (const bytes of this._buckets.pullPath(this._key, id)) {
writer.write(bytes)
}
writer.close()
Expand All @@ -181,13 +186,16 @@ export class Bucket extends RFM implements RFMInterface {
* @method removeFile
* @description Remove file from bucket
* @param {string} name file name
* @returns Promise whether it was removed or not
*
*/
async removeFile(name: string): Promise<RemovePathResponse> {
if (!this.buckets || !this.key) {
async removeFile(name: string) {
if (!this._buckets || !this._key) {
throw new Error('Bucket or bucket key not found')
}
return await this.buckets.removePath(this.key, name)
const res = await this._buckets.removePath(this._key, name, {
root: this._root,
})
if (res.root) {
this._root = res.root
}
}
}