Skip to content

Commit

Permalink
feat: simplify destination handling
Browse files Browse the repository at this point in the history
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
  • Loading branch information
skjnldsv committed Aug 17, 2023
1 parent f914ded commit ad2ac74
Show file tree
Hide file tree
Showing 5 changed files with 313 additions and 154 deletions.
45 changes: 8 additions & 37 deletions lib/components/UploadPicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
class="upload-picker"
data-upload-picker>
<!-- New button -->
<NcButton v-if="newFileMenuEntries.length === 0"
<NcButton v-if="newFileMenuEntries && newFileMenuEntries.length === 0"
:disabled="disabled"
data-upload-picker-add
@click="onClick">
Expand Down Expand Up @@ -72,7 +72,7 @@
</template>

<script>
import { getNewFileMenuEntries } from '@nextcloud/files'
import { getNewFileMenuEntries, Folder } from '@nextcloud/files'
import { getUploader } from '../index.js'
import makeEta from 'simple-eta'
Expand Down Expand Up @@ -118,17 +118,9 @@ export default {
default: false,
},
destination: {
type: String,
type: Folder,
default: null,
},
root: {
type: String,
default: null,
},
context: {
type: Object,
default: undefined,
},
},
data() {
Expand All @@ -140,7 +132,7 @@ export default {
eta: null,
timeLeft: '',
newFileMenuEntries: getNewFileMenuEntries(this.context),
newFileMenuEntries: this.destination ? getNewFileMenuEntries(this.destination) : [],
uploadManager: getUploader(),
}
},
Expand Down Expand Up @@ -176,12 +168,12 @@ export default {
watch: {
/**
* If the context change, we need to refresh the menu
* If the destination change, we need to refresh the menu
*
* @param {FileInfo} context the current NewFileMenu context
* @param {FileInfo} destination the current NewFileMenu destination
*/
context(context) {
this.setContext(context)
destination(destination) {
this.setDestination(destination)
},
totalQueueSize(size) {
Expand All @@ -194,14 +186,6 @@ export default {
this.updateStatus()
},
destination(destination) {
this.setDestination(destination)
},
root(path) {
this.setRoot(path)
},
queue(queue, oldQueue) {
if (queue.length < oldQueue.length) {
this.$emit('uploaded', oldQueue.filter(upload => !queue.includes(upload)))
Expand All @@ -225,9 +209,6 @@ export default {
beforeMount() {
this.setDestination(this.destination)
this.setRoot(this.root)
this.setContext(this.context)
logger.debug('UploadPicker initialised')
},
Expand Down Expand Up @@ -290,16 +271,6 @@ export default {
logger.debug(`Destination path set to ${destination}`)
this.uploadManager.destination = destination
},
setRoot(path) {
logger.debug(`Root path set to ${path}`)
this.uploadManager.root = path
},
setContext(context) {
logger.debug('Context changed to', context)
this.newFileMenuEntries = getNewFileMenuEntries(context)
},
},
}
</script>
Expand Down
25 changes: 14 additions & 11 deletions lib/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,33 @@ export enum Status {
}
export class Upload {

private _path: string
private _source: string
private _isChunked: boolean
private _chunks: number

private _size: number
private _uploaded: number = 0
private _startTime: number = 0
private _uploaded = 0
private _startTime = 0

private _status: Status = Status.INITIALIZED
private _controller: AbortController
private _response: AxiosResponse|null = null

constructor(path: string, chunked: boolean = false, size: number) {
constructor(source: string, chunked = false, size: number) {
const chunks = getMaxChunksSize() > 0 ? Math.ceil(size / getMaxChunksSize()) : 1
this._path = path
this._source = source
this._isChunked = chunked && getMaxChunksSize() > 0 && chunks > 1
this._chunks = this._isChunked ? chunks : 1
this._size = size
this._controller = new AbortController()
}

get path(): string {
return this._path
return this._source
}

get source(): string {
return this._source

Check warning on line 40 in lib/upload.ts

View check run for this annotation

Codecov / codecov/patch

lib/upload.ts#L40

Added line #L40 was not covered by tests
}

get isChunked(): boolean {
Expand All @@ -48,10 +52,6 @@ export class Upload {
return this._size
}

get uploaded(): number {
return this._uploaded
}

get startTime(): number {
return this._startTime
}
Expand All @@ -60,11 +60,14 @@ export class Upload {
this._response = response
}


get response(): AxiosResponse|null {
return this._response
}

get uploaded(): number {
return this._uploaded
}

/**
* Update the uploaded bytes of this upload
*/
Expand Down
73 changes: 29 additions & 44 deletions lib/uploader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CanceledError } from 'axios'
import { generateRemoteUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { Folder, Permission } from '@nextcloud/files'
import axios from '@nextcloud/axios'
import PCancelable from 'p-cancelable'
import PQueue from 'p-queue'
Expand All @@ -19,9 +20,7 @@ export enum Status {
export class Uploader {

// Initialized via setter in the constructor
private rootFolder!: string
private destinationFolder!: string

private _destinationFolder!: Folder

Check warning on line 23 in lib/uploader.ts

View check run for this annotation

Codecov / codecov/patch

lib/uploader.ts#L23

Added line #L23 was not covered by tests
private _isPublic: boolean

// Global upload queue
Expand All @@ -35,16 +34,28 @@ export class Uploader {
* Initialize uploader
*
* @param {boolean} isPublic are we in public mode ?
* @param {string} rootFolder the operation root folder
* @param {string} destinationFolder the context folder to operate, relative to the root folder
* @param {Folder} destinationFolder the context folder to operate, relative to the root folder
*/
constructor(
isPublic = false,
rootFolder = `dav/files/${getCurrentUser()?.uid}`,
destinationFolder = '/'
destinationFolder?: Folder,
) {
this._isPublic = isPublic
this.root = rootFolder

if (!destinationFolder) {
const owner = getCurrentUser()?.uid
const source = generateRemoteUrl(`dav/files/${owner}`)

Check warning on line 47 in lib/uploader.ts

View check run for this annotation

Codecov / codecov/patch

lib/uploader.ts#L47

Added line #L47 was not covered by tests
if (!owner) {
throw new Error('User is not logged in')

Check warning on line 49 in lib/uploader.ts

View check run for this annotation

Codecov / codecov/patch

lib/uploader.ts#L49

Added line #L49 was not covered by tests
}
destinationFolder = new Folder({

Check warning on line 51 in lib/uploader.ts

View check run for this annotation

Codecov / codecov/patch

lib/uploader.ts#L51

Added line #L51 was not covered by tests
id: 0,
owner,
permissions: Permission.ALL,
root: `/files/${owner}`,
source,
})
}
this.destination = destinationFolder

logger.debug('Upload workspace initialized', {
Expand All @@ -58,52 +69,25 @@ export class Uploader {
/**
* Get the upload destination path relative to the root folder
*/
get destination() {
return this.destinationFolder
get destination(): Folder {
return this._destinationFolder

Check warning on line 73 in lib/uploader.ts

View check run for this annotation

Codecov / codecov/patch

lib/uploader.ts#L73

Added line #L73 was not covered by tests
}

/**
* Set the upload destination path relative to the root folder
*/
set destination(path: string) {
if (typeof path !== 'string' || path === '') {
this.destinationFolder = '/'
return
set destination(folder: Folder) {
if (!(folder instanceof Folder)) {
throw new Error('Invalid destination folder')

Check warning on line 81 in lib/uploader.ts

View check run for this annotation

Codecov / codecov/patch

lib/uploader.ts#L81

Added line #L81 was not covered by tests
}

if (!path.startsWith('/')) {
path = `/${path}`
}
this.destinationFolder = path.replace(/\/$/, '')
this._destinationFolder = folder

Check warning on line 83 in lib/uploader.ts

View check run for this annotation

Codecov / codecov/patch

lib/uploader.ts#L83

Added line #L83 was not covered by tests
}

/**
* Get the root folder
*/
get root() {
return this.rootFolder
}

/**
* Set the root folder
*
* @param {string} path should be the remoteUrl path.
* This method uses the generateRemoteUrl method
*/
set root(path: string) {
if (typeof path !== 'string' || path === '') {
this.rootFolder = generateRemoteUrl(`dav/files/${getCurrentUser()?.uid}`)
return
}

if (path.startsWith('http')) {
throw new Error('The path should be a remote url string. E.g `dav/files/admin`.')
}

if (path.startsWith('/')) {
path = path.slice(1)
}
this.rootFolder = generateRemoteUrl(path)
return this._destinationFolder.source

Check warning on line 90 in lib/uploader.ts

View check run for this annotation

Codecov / codecov/patch

lib/uploader.ts#L90

Added line #L90 was not covered by tests
}

/**
Expand Down Expand Up @@ -169,10 +153,11 @@ export class Uploader {

/**
* Upload a file to the given path
* @param {string} destinationPath the destination path relative to the root folder. e.g. /foo/bar.txt
* @param {File} file the file to upload
*/
upload(destinationPath: string, file: File) {
const destinationFolder = this.destinationFolder === '/' ? '' : this.destinationFolder
const destinationFile = `${this.rootFolder}${destinationFolder}/${destinationPath.replace(/^\//, '')}`
const destinationFile = `${this.root}/${destinationPath.replace(/^\//, '')}`

Check warning on line 160 in lib/uploader.ts

View check run for this annotation

Codecov / codecov/patch

lib/uploader.ts#L160

Added line #L160 was not covered by tests

logger.debug(`Uploading ${file.name} to ${destinationFile}`)

Expand Down

0 comments on commit ad2ac74

Please sign in to comment.