Fix direct uploads and downloads, transfer bar UI

This commit is contained in:
Leo Vasanko 2023-11-21 16:11:54 +00:00
parent 369dc3ecaf
commit a383358369
5 changed files with 81 additions and 62 deletions

View File

@ -10,6 +10,10 @@
<main>
<RouterView :path="path.pathList" :query="path.query" />
</main>
<footer>
<TransferBar :status=store.uprogress @cancel=store.cancelUploads class=upload />
<TransferBar :status=store.dprogress @cancel=store.cancelDownloads class=download />
</footer>
</template>
<script setup lang="ts">

View File

@ -1,6 +1,5 @@
<template>
<SvgButton name="download" data-tooltip="Download" @click="download" />
<TransferBar :status=progress @cancel=cancelDownloads />
</template>
<script setup lang="ts">
@ -26,22 +25,22 @@ const status_init = {
filepos: 0,
status: 'idle',
}
const progress = reactive({...status_init})
store.dprogress = {...status_init}
setInterval(() => {
if (Date.now() - progress.tlast > 3000) {
if (Date.now() - store.dprogress.tlast > 3000) {
// Reset
progress.statbytes = 0
progress.statdur = 1
store.dprogress.statbytes = 0
store.dprogress.statdur = 1
} else {
// Running average by decay
progress.statbytes *= .9
progress.statdur *= .9
store.dprogress.statbytes *= .9
store.dprogress.statdur *= .9
}
}, 100)
const statReset = () => {
Object.assign(progress, status_init)
progress.t0 = Date.now()
progress.tlast = progress.t0 + 1
Object.assign(store.dprogress, status_init)
store.dprogress.t0 = Date.now()
store.dprogress.tlast = store.dprogress.t0 + 1
}
const cancelDownloads = () => {
location.reload() // FIXME
@ -61,9 +60,9 @@ const filesystemdl = async (sel: SelectedItems, handle: FileSystemDirectoryHandl
console.log('Downloading to filesystem', sel.recursive)
for (const [rel, full, doc] of sel.recursive) {
if (doc.dir) continue
progress.files.push(rel)
++progress.filecount
progress.total += doc.size
store.dprogress.files.push(rel)
++store.dprogress.filecount
store.dprogress.total += doc.size
}
for (const [rel, full, doc] of sel.recursive) {
// Create any missing directories
@ -73,6 +72,7 @@ const filesystemdl = async (sel: SelectedItems, handle: FileSystemDirectoryHandl
}
const r = rel.slice(hdir.length)
for (const dir of r.split('/').slice(0, doc.dir ? undefined : -1)) {
if (!dir) continue
hdir += `${dir}/`
try {
h = await h.getDirectoryHandle(dir.normalize('NFC'), { create: true })
@ -101,22 +101,22 @@ const filesystemdl = async (sel: SelectedItems, handle: FileSystemDirectoryHandl
throw new Error(`Failed to download ${url}: ${res.status} ${res.statusText}`)
}
if (res.body) {
++progress.fileidx
++store.dprogress.fileidx
const reader = res.body.getReader()
await writable.truncate(0)
store.error = "Direct download."
progress.tlast = Date.now()
store.dprogress.tlast = Date.now()
while (true) {
const { value, done } = await reader.read()
if (done) break
await writable.write(value)
const now = Date.now()
const size = value.byteLength
progress.xfer += size
progress.filepos += size
progress.statbytes += size
progress.statdur += now - progress.tlast
progress.tlast = now
store.dprogress.xfer += size
store.dprogress.filepos += size
store.dprogress.statbytes += size
store.dprogress.statdur += now - store.dprogress.tlast
store.dprogress.tlast = now
}
}
await writable.close()

View File

@ -57,13 +57,12 @@ const speeddisp = computed(() => speed.value ? speed.value.toFixed(speed.value <
display: flex;
flex-direction: column;
color: var(--primary-color);
position: fixed;
left: 0;
bottom: 0;
width: 100vw;
width: 100%;
}
.statustext {
display: flex;
align-items: center;
margin: 0 .5em;
padding: 0.5rem 0;
}
span {
@ -84,4 +83,12 @@ span {
.position { min-width: 4em }
.speed { min-width: 4em }
.upload .statustext::before {
font-size: 1.5em;
content: '🔺'
}
.download .statustext::before {
font-size: 1.5em;
content: '🔻'
}
</style>

View File

@ -1,3 +1,12 @@
<template>
<template>
<input ref="fileInput" @change="uploadHandler" type="file" multiple>
<input ref="folderInput" @change="uploadHandler" type="file" webkitdirectory>
</template>
<SvgButton name="add-file" data-tooltip="Upload files" @click="fileInput.click()" />
<SvgButton name="add-folder" data-tooltip="Upload folder" @click="folderInput.click()" />
</template>
<script setup lang="ts">
import { connect, uploadUrl } from '@/repositories/WS';
import { useMainStore } from '@/stores/main'
@ -108,50 +117,50 @@ const uprogress_init = {
filepos: 0,
status: 'idle',
}
const uprogress = reactive({...uprogress_init})
store.uprogress = {...uprogress_init}
setInterval(() => {
if (Date.now() - uprogress.tlast > 3000) {
if (Date.now() - store.uprogress.tlast > 3000) {
// Reset
uprogress.statbytes = 0
uprogress.statdur = 1
store.uprogress.statbytes = 0
store.uprogress.statdur = 1
} else {
// Running average by decay
uprogress.statbytes *= .9
uprogress.statdur *= .9
store.uprogress.statbytes *= .9
store.uprogress.statdur *= .9
}
}, 100)
const statUpdate = ({name, size, start, end}: {name: string, size: number, start: number, end: number}) => {
if (name !== uprogress.filename) return // If stats have been reset
if (name !== store.uprogress.filename) return // If stats have been reset
const now = Date.now()
uprogress.xfer = uprogress.filestart + end
uprogress.filepos = end
uprogress.statbytes += end - start
uprogress.statdur += now - uprogress.tlast
uprogress.tlast = now
store.uprogress.xfer = store.uprogress.filestart + end
store.uprogress.filepos = end
store.uprogress.statbytes += end - start
store.uprogress.statdur += now - store.uprogress.tlast
store.uprogress.tlast = now
// File finished?
if (end === size) {
uprogress.filestart += size
store.uprogress.filestart += size
statNextFile()
if (++uprogress.fileidx >= uprogress.filecount) statReset()
if (++store.uprogress.fileidx >= store.uprogress.filecount) statReset()
}
}
const statNextFile = () => {
const f = uprogress.files.shift()
const f = store.uprogress.files.shift()
if (!f) return statReset()
uprogress.filepos = 0
uprogress.filesize = f.file.size
uprogress.filename = f.cloudName
store.uprogress.filepos = 0
store.uprogress.filesize = f.file.size
store.uprogress.filename = f.cloudName
}
const statReset = () => {
Object.assign(uprogress, uprogress_init)
uprogress.t0 = Date.now()
uprogress.tlast = uprogress.t0 + 1
Object.assign(store.uprogress, uprogress_init)
store.uprogress.t0 = Date.now()
store.uprogress.tlast = store.uprogress.t0 + 1
}
const statsAdd = (f: CloudFile[]) => {
if (uprogress.files.length === 0) statReset()
uprogress.total += f.reduce((a, b) => a + b.file.size, 0)
uprogress.filecount += f.length
uprogress.files = [...uprogress.files, ...f]
if (store.uprogress.files.length === 0) statReset()
store.uprogress.total += f.reduce((a, b) => a + b.file.size, 0)
store.uprogress.filecount += f.length
store.uprogress.files = [...store.uprogress.files, ...f]
statNextFile()
}
let upqueue = [] as CloudFile[]
@ -181,7 +190,7 @@ const WSCreate = async () => await new Promise<WebSocket>(resolve => {
// @ts-ignore
ws.sendData = async (data: any) => {
// Wait until the WS is ready to send another message
uprogress.status = "uploading"
store.uprogress.status = "uploading"
await new Promise(resolve => {
const t = setInterval(() => {
if (ws.bufferedAmount > 1<<20) return
@ -189,7 +198,7 @@ const WSCreate = async () => await new Promise<WebSocket>(resolve => {
clearInterval(t)
}, 1)
})
uprogress.status = "processing"
store.uprogress.status = "processing"
ws.send(data)
}
})
@ -210,7 +219,7 @@ const worker = async () => {
if (f.cloudPos === f.file.size) upqueue.shift()
}
if (upqueue.length) startWorker()
uprogress.status = "idle"
store.uprogress.status = "idle"
workerRunning = false
}
let workerRunning: any = false
@ -233,12 +242,3 @@ onUnmounted(() => {
removeEventListener('drop', uploadHandler)
})
</script>
<template>
<template>
<input ref="fileInput" @change="uploadHandler" type="file" multiple>
<input ref="folderInput" @change="uploadHandler" type="file" webkitdirectory>
</template>
<SvgButton name="add-file" data-tooltip="Upload files" @click="fileInput.click()" />
<SvgButton name="add-folder" data-tooltip="Upload folder" @click="folderInput.click()" />
<TransferBar :status=uprogress @cancel=cancelUploads />
</template>

View File

@ -19,6 +19,8 @@ export const useMainStore = defineStore({
cursor: '' as string,
server: {} as Record<string, any>,
dialog: '' as '' | 'login' | 'settings',
uprogress: {} as any,
dprogress: {} as any,
prefs: {
gallery: false,
sortListing: '' as SortOrder,
@ -89,7 +91,13 @@ export const useMainStore = defineStore({
},
focusBreadcrumb() {
(document.querySelector('.breadcrumb') as HTMLAnchorElement).focus()
}
},
cancelDownloads() {
location.reload() // FIXME
},
cancelUploads() {
location.reload() // FIXME
},
},
getters: {
sortOrder(): SortOrder { return this.query ? this.prefs.sortFiltered : this.prefs.sortListing },