diff --git a/public/js/myResources.js b/public/js/myResources.js index d9e9b827..63195843 100644 --- a/public/js/myResources.js +++ b/public/js/myResources.js @@ -787,6 +787,7 @@ wrap.style.cssText = 'padding:8px 12px;display:flex;align-items:center;gap:10px;flex-wrap:wrap;'; var body = document.createElement('div'); + body.className = 'mr-row-body'; body.style.flex = '1'; body.style.minWidth = '180px'; @@ -817,6 +818,7 @@ body.appendChild(from); } else if (row.owned !== false && row.shared_with_all) { var all = document.createElement('div'); + all.className = 'mr-shared-note'; all.style.cssText = 'font-size:11px;color:var(--g500);'; all.textContent = 'Shared with everyone'; body.appendChild(all); @@ -877,10 +879,11 @@ cloud.type = 'button'; cloud.dataset.nextcloud = String(row.id); cloud.dataset.format = row.kind === 'article' ? 'docx' : 'pptx'; - cloud.title = 'Save to my Nextcloud as ' + cloud.dataset.format.toUpperCase(); + cloud.title = 'Upload to your Nextcloud as ' + cloud.dataset.format.toUpperCase(); var cloudIcon = document.createElement('i'); cloudIcon.className = 'fas fa-cloud-arrow-up'; cloud.appendChild(cloudIcon); + cloud.appendChild(document.createTextNode(' Nextcloud')); wrap.appendChild(cloud); } @@ -1023,7 +1026,24 @@ } function load() { return fetch(base, { headers: getAuthHeaders() }).then(function (r) { return r.json(); }) - .then(function (d) { if (!d.success) throw new Error(d.error || 'Could not load'); paint(d); loadLibrary(); }) + // Painting the panel must not redraw the library: a redraw rebuilds the + // rows and the panel vanished the moment it opened. The row's own + // "shared with everyone" line is updated in place instead. + .then(function (d) { + if (!d.success) throw new Error(d.error || 'Could not load'); + paint(d); + var note = rowEl.querySelector('.mr-shared-note'); + if (d.sharedWithAll && !note) { + note = document.createElement('div'); + note.className = 'mr-shared-note'; + note.style.cssText = 'font-size:11px;color:var(--g500);'; + note.textContent = 'Shared with everyone'; + var body = rowEl.querySelector('.mr-row-body') || rowEl.firstElementChild; + if (body) body.appendChild(note); + } else if (!d.sharedWithAll && note) { + note.remove(); + } + }) .catch(function (e) { showToast(e.message, 'error'); }); } panel.querySelector('.mr-share-all').addEventListener('change', function (e) { diff --git a/test/backend-hardening.test.js b/test/backend-hardening.test.js index 78200fc2..c5040f99 100644 --- a/test/backend-hardening.test.js +++ b/test/backend-hardening.test.js @@ -324,3 +324,11 @@ test('a failed transcription keeps its tab, the retry puts the words after the l assert.doesNotMatch(read('public/components/settings.html'), /sessions-section|btn-revoke-all-sessions/); assert.doesNotMatch(read('public/js/auth.js'), /loadSessions/); }); + +test('opening the share panel does not redraw the library, and the Nextcloud upload is a labelled button', () => { + const js = read('public/js/myResources.js'); + const panel = js.slice(js.indexOf('function openSharePanel('), js.indexOf('function openPreview(')); + assert.doesNotMatch(panel, /loadLibrary\(\)/, 'a redraw rebuilds the rows and takes the panel with it'); + assert.match(panel, /mr-shared-note/); + assert.match(js, /createTextNode\(' Nextcloud'\)/); +});