This commit is contained in:
parent
e6211f1333
commit
29dc913ed1
10
CHANGELOG.md
10
CHANGELOG.md
@ -9,6 +9,13 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
|
||||
|
||||
---
|
||||
|
||||
## [1.26.10] — 2026-09-10
|
||||
|
||||
### Fixed
|
||||
- **Instant Dropzone Upload & Active Progress Card.** Dropping a PDF (or picking a file) now automatically initiates upload and ingestion immediately. The dropzone transforms into an active progress card with a spinning loader, animated progress bar, status note (`Uploading "filename.pdf" (X MB)`), and disabled input controls so users get un-missable, immediate feedback.
|
||||
|
||||
---
|
||||
|
||||
## [1.26.9] — 2026-09-10
|
||||
|
||||
### Fixed
|
||||
@ -3905,7 +3912,8 @@ Initial feature-complete release.
|
||||
|
||||
---
|
||||
|
||||
[Unreleased]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.26.9...HEAD
|
||||
[Unreleased]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.26.10...HEAD
|
||||
[1.26.10]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.26.9...v1.26.10
|
||||
[1.26.9]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.26.8...v1.26.9
|
||||
[1.26.1]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.26.0...v1.26.1
|
||||
[1.26.0]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.25.3...v1.26.0
|
||||
|
||||
@ -352,6 +352,47 @@
|
||||
.reader-extract-info p { margin: 2px 0 0; color: var(--subtext); font-size: 12.5px; }
|
||||
.reader-dropzone.dragover { border-color: var(--accent); background: rgba(37,99,235,.06); color: var(--accent); }
|
||||
.reader-dropzone.dragover .reader-dropzone-icon { opacity: 1; }
|
||||
.reader-dropzone.is-selected {
|
||||
border-style: solid;
|
||||
border-color: var(--accent);
|
||||
background: rgba(37, 99, 235, 0.04);
|
||||
}
|
||||
.reader-dropzone.is-selected .reader-dropzone-icon {
|
||||
opacity: 1;
|
||||
color: var(--accent);
|
||||
}
|
||||
.reader-dropzone.is-uploading {
|
||||
border-style: solid;
|
||||
border-color: var(--accent);
|
||||
background: rgba(37, 99, 235, 0.08);
|
||||
box-shadow: 0 0 16px rgba(37, 99, 235, 0.2);
|
||||
padding: 26px 16px;
|
||||
}
|
||||
.reader-dropzone.is-uploading .reader-dropzone-icon {
|
||||
opacity: 1;
|
||||
color: var(--accent);
|
||||
}
|
||||
.mag-dropzone-progress {
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
height: 6px;
|
||||
background: rgba(37, 99, 235, 0.2);
|
||||
border-radius: 999px;
|
||||
overflow: hidden;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.mag-dropzone-progress-bar {
|
||||
height: 100%;
|
||||
width: 40%;
|
||||
background: var(--accent);
|
||||
border-radius: 999px;
|
||||
animation: magIndeterminateProgress 1.4s infinite ease-in-out;
|
||||
}
|
||||
@keyframes magIndeterminateProgress {
|
||||
0% { transform: translateX(-100%); width: 30%; }
|
||||
50% { transform: translateX(100%); width: 50%; }
|
||||
100% { transform: translateX(300%); width: 30%; }
|
||||
}
|
||||
#s-reader .reader-file-pick {
|
||||
margin-top: 4px;
|
||||
cursor: pointer;
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<meta name="theme-color" content="#2563EB">
|
||||
<meta name="app-version" content="1.26.9">
|
||||
<meta name="app-version" content="1.26.10">
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/static/icon.svg">
|
||||
@ -27,12 +27,12 @@
|
||||
|
||||
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
|
||||
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" href="/static/style.css?v=1.26.9">
|
||||
<link rel="stylesheet" href="/static/css/resource-diagnostics.css?v=1.26.9">
|
||||
<link rel="stylesheet" href="/static/css/background-jobs.css?v=1.26.9">
|
||||
<link rel="stylesheet" href="/static/css/voice-design.css?v=1.26.9">
|
||||
<link rel="stylesheet" href="/static/css/rehearser.css?v=1.26.9">
|
||||
<link rel="stylesheet" href="/static/css/audiobook.css?v=1.26.9">
|
||||
<link rel="stylesheet" href="/static/style.css?v=1.26.10">
|
||||
<link rel="stylesheet" href="/static/css/resource-diagnostics.css?v=1.26.10">
|
||||
<link rel="stylesheet" href="/static/css/background-jobs.css?v=1.26.10">
|
||||
<link rel="stylesheet" href="/static/css/voice-design.css?v=1.26.10">
|
||||
<link rel="stylesheet" href="/static/css/rehearser.css?v=1.26.10">
|
||||
<link rel="stylesheet" href="/static/css/audiobook.css?v=1.26.10">
|
||||
|
||||
|
||||
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
||||
@ -403,7 +403,7 @@ window.toggleNavTree = function(treeId, chevronId) {
|
||||
</script>
|
||||
|
||||
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
||||
<script src="/static/loader.js?v=1.26.9"></script>
|
||||
<script src="/static/loader.js?v=1.26.10"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -189,11 +189,13 @@ function magShowDroppedFile(file) {
|
||||
const titleEl = $('mag-dropzone-title');
|
||||
const iconEl = $('mag-dropzone-icon');
|
||||
const titleInput = $('mag-new-title');
|
||||
const dropzone = $('mag-dropzone');
|
||||
|
||||
if (file) {
|
||||
const sizeMb = (file.size / (1024 * 1024)).toFixed(1);
|
||||
if (dropzone) dropzone.classList.add('is-selected');
|
||||
if (noteEl) noteEl.textContent = `Selected: ${file.name} (${sizeMb} MB)`;
|
||||
if (titleEl) titleEl.textContent = 'PDF file selected';
|
||||
if (titleEl) titleEl.textContent = 'PDF file selected — uploading...';
|
||||
if (iconEl) iconEl.className = 'mdi mdi-file-check-outline reader-dropzone-icon';
|
||||
|
||||
// Auto-fill title from filename if title input is empty
|
||||
@ -201,6 +203,7 @@ function magShowDroppedFile(file) {
|
||||
titleInput.value = magFormatFilenameAsTitle(file.name);
|
||||
}
|
||||
} else {
|
||||
if (dropzone) dropzone.classList.remove('is-selected', 'is-uploading');
|
||||
if (noteEl) noteEl.textContent = MAG_DROPZONE_DEFAULT_NOTE;
|
||||
if (titleEl) titleEl.textContent = 'Drop a PDF or click to browse';
|
||||
if (iconEl) iconEl.className = 'mdi mdi-cloud-upload-outline reader-dropzone-icon';
|
||||
@ -257,8 +260,15 @@ function setupMagDropzone() {
|
||||
dt.items.add(file);
|
||||
input.files = dt.files;
|
||||
magShowDroppedFile(file);
|
||||
magCreate();
|
||||
});
|
||||
input.addEventListener('change', () => {
|
||||
const file = input.files?.[0];
|
||||
if (file) {
|
||||
magShowDroppedFile(file);
|
||||
magCreate();
|
||||
}
|
||||
});
|
||||
input.addEventListener('change', () => magShowDroppedFile(input.files?.[0]));
|
||||
}
|
||||
|
||||
async function magCreate() {
|
||||
@ -276,29 +286,57 @@ async function magCreate() {
|
||||
const dropzone = $('mag-dropzone');
|
||||
const titleInp = $('mag-new-title');
|
||||
const issueInp = $('mag-new-issue');
|
||||
const progress = $('mag-dropzone-progress');
|
||||
const pickBtn = $('mag-dropzone-pick-btn');
|
||||
const titleEl = $('mag-dropzone-title');
|
||||
const noteEl = $('mag-dropzone-note');
|
||||
const iconEl = $('mag-dropzone-icon');
|
||||
const origBtnText = addBtn ? addBtn.innerHTML : '';
|
||||
|
||||
const setUploadingState = (uploading) => {
|
||||
if (addBtn) {
|
||||
addBtn.disabled = uploading;
|
||||
addBtn.innerHTML = uploading
|
||||
? '<span class="mdi mdi-loading mdi-spin"></span> Uploading PDF...'
|
||||
: origBtnText;
|
||||
const sizeMb = file ? (file.size / (1024 * 1024)).toFixed(1) : 0;
|
||||
if (uploading) {
|
||||
if (dropzone) {
|
||||
dropzone.classList.add('is-uploading');
|
||||
dropzone.style.pointerEvents = 'none';
|
||||
}
|
||||
if (progress) progress.hidden = false;
|
||||
if (pickBtn) pickBtn.hidden = true;
|
||||
if (iconEl) iconEl.className = 'mdi mdi-loading mdi-spin reader-dropzone-icon';
|
||||
if (titleEl) titleEl.textContent = 'Uploading & Ingesting PDF...';
|
||||
if (noteEl) noteEl.textContent = `Processing "${file.name}" (${sizeMb} MB). Transferring source file and extracting layout...`;
|
||||
if (addBtn) {
|
||||
addBtn.disabled = true;
|
||||
addBtn.innerHTML = '<span class="mdi mdi-loading mdi-spin"></span> Uploading PDF...';
|
||||
}
|
||||
if (titleInp) titleInp.disabled = true;
|
||||
if (issueInp) issueInp.disabled = true;
|
||||
} else {
|
||||
if (dropzone) {
|
||||
dropzone.classList.remove('is-uploading');
|
||||
dropzone.style.pointerEvents = 'auto';
|
||||
}
|
||||
if (progress) progress.hidden = true;
|
||||
if (pickBtn) pickBtn.hidden = false;
|
||||
if (addBtn) {
|
||||
addBtn.disabled = false;
|
||||
addBtn.innerHTML = origBtnText;
|
||||
}
|
||||
if (titleInp) titleInp.disabled = false;
|
||||
if (issueInp) issueInp.disabled = false;
|
||||
}
|
||||
if (titleInp) titleInp.disabled = uploading;
|
||||
if (issueInp) issueInp.disabled = uploading;
|
||||
if (dropzone) dropzone.style.pointerEvents = uploading ? 'none' : 'auto';
|
||||
};
|
||||
|
||||
try {
|
||||
setUploadingState(true);
|
||||
say(`Uploading ${file.name} (${(file.size / (1024 * 1024)).toFixed(1)} MB)...`, 'ok');
|
||||
const { id } = await api('/api/magazine/docs', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ title, issue }),
|
||||
});
|
||||
await api('/api/reader/docs/' + id + '/source?ext=pdf', { method: 'PUT', body: file });
|
||||
say('Magazine added — starting ingestion', 'ok');
|
||||
say('Magazine uploaded — starting ingestion', 'ok');
|
||||
|
||||
if ($('mag-new-title')) $('mag-new-title').value = '';
|
||||
if ($('mag-new-issue')) $('mag-new-issue').value = '';
|
||||
|
||||
@ -22,7 +22,10 @@
|
||||
<span class="mdi mdi-cloud-upload-outline reader-dropzone-icon" id="mag-dropzone-icon"></span>
|
||||
<strong id="mag-dropzone-title">Drop a PDF or click to browse</strong>
|
||||
<span class="note" id="mag-dropzone-note">Scanned issues work too — pages without selectable text are read with OCR.</span>
|
||||
<label class="btn-secondary btn-sm reader-file-pick" title="Choose a PDF file" onclick="event.stopPropagation()">
|
||||
<div class="mag-dropzone-progress" id="mag-dropzone-progress" hidden>
|
||||
<div class="mag-dropzone-progress-bar"></div>
|
||||
</div>
|
||||
<label class="btn-secondary btn-sm reader-file-pick" id="mag-dropzone-pick-btn" title="Choose a PDF file" onclick="event.stopPropagation()">
|
||||
<span class="mdi mdi-file-upload-outline"></span> Choose file
|
||||
<input type="file" id="mag-new-file" accept="application/pdf" style="display:none">
|
||||
</label>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user