Improve upload progress UX — indeterminate bar and elapsed time
Local uploads appeared stuck at 0% because onUploadProgress doesn't fire granularly on fast local networks or when network buffering makes the browser report instant completion. Changes: - Animated indeterminate progress bar when percent unavailable - Elapsed seconds counter so user sees activity - Separate "Uploading" vs "Processing on server" stages - Hint message about large PDFs taking time Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
56fdc57389
commit
c44014c787
1 changed files with 32 additions and 8 deletions
|
|
@ -128,23 +128,30 @@ export default function UploadPage() {
|
|||
const hasNextcloud = !!localStorage.getItem('nc_username')
|
||||
|
||||
const [uploadName, setUploadName] = useState('')
|
||||
const [stage, setStage] = useState('uploading') // 'uploading' | 'processing'
|
||||
const [elapsed, setElapsed] = useState(0)
|
||||
const doUpload = async (f) => {
|
||||
if (!f) return
|
||||
setUploadName(f.name)
|
||||
setUploading(true); setError(''); setProgress(0)
|
||||
setUploading(true); setError(''); setProgress(0); setStage('uploading'); setElapsed(0)
|
||||
const start = Date.now()
|
||||
const timer = setInterval(() => setElapsed(Math.round((Date.now() - start) / 1000)), 500)
|
||||
const formData = new FormData()
|
||||
formData.append('file', f)
|
||||
try {
|
||||
const res = await api.post('/documents/upload', formData, {
|
||||
onUploadProgress: (e) => {
|
||||
if (e.progress != null) setProgress(Math.round(e.progress * 100))
|
||||
else if (e.total) setProgress(Math.round((e.loaded / e.total) * 100))
|
||||
const pct = e.progress != null
|
||||
? Math.round(e.progress * 100)
|
||||
: e.total ? Math.round((e.loaded / e.total) * 100) : 0
|
||||
setProgress(pct)
|
||||
if (pct >= 100) setStage('processing')
|
||||
},
|
||||
})
|
||||
navigate(`/documents/${res.data.id}`)
|
||||
} catch (err) {
|
||||
setError(err.response?.data?.detail || 'Upload failed')
|
||||
} finally { setUploading(false) }
|
||||
} finally { clearInterval(timer); setUploading(false) }
|
||||
}
|
||||
|
||||
const handleFile = (f, fromNextcloud = false) => {
|
||||
|
|
@ -222,12 +229,29 @@ export default function UploadPage() {
|
|||
{uploading && (
|
||||
<div style={{ marginTop: 16, padding: '16px', background: 'var(--option-sel-bg)', borderRadius: 8, border: '1px solid var(--option-sel-bd)' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8, fontSize: '0.9rem', fontWeight: 600 }}>
|
||||
<span>Uploading {uploadName || file?.name || 'file'}...</span>
|
||||
<span>{progress}%</span>
|
||||
<span>
|
||||
{stage === 'processing' ? 'Processing on server' : 'Uploading'} {uploadName || file?.name || 'file'}...
|
||||
</span>
|
||||
<span>
|
||||
{progress > 0 ? `${progress}%` : ''} {elapsed > 0 && `(${elapsed}s)`}
|
||||
</span>
|
||||
</div>
|
||||
<div className="progress-bar">
|
||||
<div className="fill" style={{ width: `${Math.max(progress, 5)}%`, transition: 'width 0.3s' }} />
|
||||
<div className="progress-bar" style={{ overflow: 'hidden', position: 'relative' }}>
|
||||
{progress > 0 ? (
|
||||
<div className="fill" style={{ width: `${progress}%`, transition: 'width 0.3s' }} />
|
||||
) : (
|
||||
<div style={{
|
||||
height: '100%',
|
||||
width: '30%',
|
||||
background: 'var(--primary)',
|
||||
animation: 'indeterminate 1.4s infinite linear',
|
||||
}} />
|
||||
)}
|
||||
</div>
|
||||
<style>{`@keyframes indeterminate { 0% { transform: translateX(-100%); } 100% { transform: translateX(400%); } }`}</style>
|
||||
<p style={{ fontSize: '0.78rem', color: 'var(--text-muted)', marginTop: 8, marginBottom: 0 }}>
|
||||
Large PDFs may take a few minutes — please keep this tab open.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue